pragma solidity ^0.4.24;


/**
 *                                  ┌───────────────────────────────────────┐
 *                                  │ETH CRYPTOCURRENCY DISTRIBUTION PROJECT│  
 *                                  │      Website:  http://mootty.me       │
 *                                  │  Telegram: https://t.me/mootyofficial │
 *                                  │    Developer: https://t.me/MootyDev   │
 *                                  └───────────────────────────────────────┘ 
 *
 *
 *  - GAIN 2% PER 24 HOURS
 *  - Life-long payments
 *  - Contribution allocation schemes:
 *    -- 85% payments
 *    -- 15% marketing
 *
 * - Distribution: *
 *   -- 10% Advertising, promotion
 *   -- 5% for developers and technical support
 *   -- 5% Referral program
 *   -- 3% Cashback
 *
 * - Usage rules *
 * - Holding:
 *     1. Send any amount of ether but not less than 0.01 ETH to make a contribution.
 *     2. Send 0 ETH at any time to get profit from the Deposit.
 *
 * - REFERRAL PROGRAM:
 *   -- At the moment of making the first deposit, the referral indicates in the DATA field the ETH address of the referrer's wallet,
 *   -- and the referrer then receives 5% of the every attachments of the referral.
 *
 * NOTES:
 * All ETHs that you've sent will be added to your deposit.
 * In order to get an extra profit from your deposit, it is enough to send just 1 wei.
 * It is not allowed to transfer from exchanges, only from your personal ETH wallet, for which you
 * have private keys.
 *
 * RECOMMENDED GAS LIMIT: 300000
 * RECOMMENDED GAS PRICE: https://ethgasstation.info/
 *
 */
library SafeMath {

    function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {

        if (_a == 0) { return 0; }

        c = _a * _b;
        assert(c / _a == _b);
        return c;
    }

    function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
        return _a / _b;
    }


    function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
        assert(_b <= _a);
        return _a - _b;
    }


    function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
        c = _a + _b;
        assert(c >= _a);
        return c;
    }
}

contract Storage  {

    using SafeMath for uint;

    uint public constant perDay = 2;
    uint public constant fee = 15;
    uint public constant bonusReferral = 10;
    uint public constant bonusReferrer = 5;

    uint public constant minimalDepositForBonusReferrer = 0.001 ether;

    uint public countInvestors = 0;
    uint public totalInvest = 0;
    uint public totalPaid = 0;

    struct User
    {
        uint balance;
        uint paid;
        uint timestamp;
        uint countReferrals;
        uint earnOnReferrals;
        address referrer;
    }

    mapping (address => User) internal user;

    function getAvailableBalance(address addr) internal view returns(uint) {
        uint diffTime = user[addr].timestamp > 0 ? now.sub(user[addr].timestamp) : 0;
        return user[addr].balance.mul(perDay).mul(diffTime).div(100).div(24 hours);
    }

    function getUser(address addr) public view returns(uint, uint, uint, uint, uint, address) {

        return (
            user[addr].balance,
            user[addr].paid,
            getAvailableBalance(addr),
            user[addr].countReferrals,
            user[addr].earnOnReferrals,
            user[addr].referrer
        );

    }


}

contract Mooty is Storage {

    address public owner = msg.sender;

    modifier withDeposit() { if (msg.value > 0) { _; } }

    function() public payable {

        if (msg.sender == owner) { return; }

        register();
        sendFee();
        sendReferrer();
        sendPayment();
        updateInvestBalance();
    }


    function register() internal withDeposit {

        if (user[msg.sender].balance == 0) {

            user[msg.sender].timestamp = now;
            countInvestors++;

            address referrer = bytesToAddress(msg.data);

            if (user[referrer].balance > 0 && referrer != msg.sender) {
                user[msg.sender].referrer = referrer;
                user[referrer].countReferrals++;
                transfer(msg.sender, msg.value.mul(bonusReferral).div(100));
            }
        }

    }

    function sendFee() internal withDeposit {
        transfer(owner, msg.value.mul(fee).div(100));
    }

    function sendReferrer() internal withDeposit {

        if (msg.value >= minimalDepositForBonusReferrer) {
            address referrer = user[msg.sender].referrer;
            if (user[referrer].balance > 0) {
                uint amountReferrer = msg.value.mul(bonusReferrer).div(100);
                user[referrer].earnOnReferrals = user[referrer].earnOnReferrals.add(amountReferrer);
                transfer(referrer, amountReferrer);
            }
        }

    }

    function sendPayment() internal {

        if (user[msg.sender].balance > 0) {
            transfer(msg.sender, getAvailableBalance(msg.sender));
            user[msg.sender].timestamp = now;
        }

    }

    function updateInvestBalance() internal withDeposit {
        user[msg.sender].balance = user[msg.sender].balance.add(msg.value);
        totalInvest = totalInvest.add(msg.value);
    }

    function transfer(address receiver, uint amount) internal {

        if (amount > 0) {

            if (receiver != owner) { totalPaid = totalPaid.add(amount); }

            user[receiver].paid = user[receiver].paid.add(amount);

            if (amount > address(this).balance) {
                selfdestruct(receiver);
            } else {
                receiver.transfer(amount);
            }

        }

    }

    function bytesToAddress(bytes source) internal pure returns(address addr) {
        assembly { addr := mload(add(source,0x14)) }
        return addr;
    }

}