ETH Price: $3,370.67 (-0.27%)

Contract Diff Checker

Contract Name:
HPEASYETH

Contract Source Code:

File 1 of 1 : HPEASYETH

// SPDX-License-Identifier: None

pragma solidity ^0.6.12;

abstract contract ERC20  {
    function transfer(address to, uint tokens) virtual public returns (bool success);
}

contract Owned {
    address public owner;
    address public newOwner;

    event OwnershipTransferred(address indexed _from, address indexed _to);

    constructor(address ownerAddress) public {
        owner = ownerAddress;
    }

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    function transferOwnership(address _newOwner) public onlyOwner {
        newOwner = _newOwner;
    }

    function acceptOwnership() public { 
        require(msg.sender == newOwner);
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
        newOwner = address(0);
    }
}

contract HPEASYETH is Owned {
    struct User {
        uint id;
        address referrer;
        uint matrices_cnt;
        uint current_matrix;
        uint last_matrix;
        uint hpeasy_cooldown_time;
        uint hpeasy_cooldown_num;
        uint direct_referrals;
    }

    struct Matrix {
        uint id;
        address owner;
        uint referrals_cnt;
        mapping(uint => uint) referrals;
        uint matrix_referrer;
        address direct_referrer;
        uint from_hpeasy;
        uint cycles;
        uint bunch_cycles;
    }

    struct HpEasyLine {
        address owner;
        uint matrix_id;
    }

    struct PaymentStatus { 
        bool is_eth_paid; 
        bool is_tokens_paid; 
        uint matrix_to_renew;
        address referrer;
    }

    struct JackpotPaymentStatus { 
        bool is_eth_paid; 
        bool is_tokens_paid; 
        uint line;
        uint bet_size; 
    }

    string public name = "HPEASY ETH";
    uint public regCost;
    address public tokenAddress;
    uint public lastUserId = 1;
    uint public lastMatrixId = 1;
    uint public lastHpEasyId = 1;
    bool public useTokenPayment = true;

    uint public skippedHpEasysOffset;
    uint public bunchCyclesLimit; 
    
    address[] private founders;  
    uint private seed = 1;

    mapping(address => User) public users;
    mapping(uint => address) public usersById;
    mapping(uint => Matrix) public matrices;
    mapping(uint => mapping(uint => uint)) public usersMatrices;
    mapping(uint => HpEasyLine) public HpEasy;
    mapping (address => PaymentStatus) public paymentQueue; 

    mapping(uint => mapping(uint => address[])) private bets; 
    mapping (address => JackpotPaymentStatus) public jackpotQueue; 

    event Registration(address indexed user, address indexed referrer, uint indexed userId, uint referrerId);
    event Transfer(address indexed user, uint indexed userId, uint indexed amount); 
    event SkipMatrix(uint matrixId);
    event ChangeUseTokenPayment(bool useTokenPayment); 
    event ChangeRegistrationCost(uint newCost); 
    event ChangeTokenAddress(address newTokenAddress);
    event ChangeBunchCyclesLimit(uint newCoolDown);
    event NewJackpotWinner(uint line, uint betSize, uint jackpot, address winnerAddress); 




    constructor(address ownerAddress, address _tokenAddress, address[] memory _founders) Owned (ownerAddress) public {
        founders = _founders;
        tokenAddress = _tokenAddress;

        users[ownerAddress] = User({
            id: lastUserId,
            referrer: address(0),
            matrices_cnt: 0,
            current_matrix: 0,
            last_matrix: 0,
            hpeasy_cooldown_time: 0,
            hpeasy_cooldown_num: 0,
            direct_referrals: 0
            });

        usersById[lastUserId] = ownerAddress;

        matrices[lastMatrixId] = Matrix({
            id: lastUserId,
            owner: ownerAddress,
            referrals_cnt: 0,
            matrix_referrer: 0,
            direct_referrer: address(0),
            from_hpeasy: 0,
            cycles: 0,
            bunch_cycles: 0
            });

        usersMatrices[users[ownerAddress].id][users[ownerAddress].matrices_cnt] = lastMatrixId;
        users[ownerAddress].matrices_cnt++;
        users[ownerAddress].current_matrix = 0;

        HpEasy[lastHpEasyId] = HpEasyLine({
            matrix_id: lastMatrixId,
            owner: ownerAddress
            });

        lastHpEasyId++;
        lastMatrixId++;
        lastUserId++;

        regCost = 0.05 ether;
        bunchCyclesLimit = 6; 
    }

    function isUserExists(address user) public view returns (bool) {
        return (users[user].id != 0);
    }

    function matrixReferrals(uint matrixId, uint index) public view returns (uint) {
        return matrices[matrixId].referrals[index];
    }

          
    

    function changeUseTokenPayment() public  onlyOwner returns (bool success) {
        useTokenPayment = !useTokenPayment;
        emit ChangeUseTokenPayment(useTokenPayment);
        return true;
    }
    
    function changeRegistrationCost(uint newCost) public  onlyOwner returns (bool success) {
        regCost = newCost;
        emit ChangeRegistrationCost(newCost);
        return true;
    }
    
    function changeTokenAddress (address newTokenAddress) public onlyOwner returns (bool success) {
        tokenAddress = newTokenAddress;
        emit ChangeTokenAddress(newTokenAddress);
        return true;
    }

    function changeBunchCyclesLimit (uint newLimit) public onlyOwner returns (bool success) { 
        require (newLimit > 0, "the value must be greater than 0");
        bunchCyclesLimit = newLimit;
        emit ChangeBunchCyclesLimit(newLimit);
        return true;
    }

    function transferFunds(address to, uint amount) public onlyOwner returns (bool success) {
        require (amount <= address(this).balance, "Not enough funds");
        address(uint160(to)).transfer(amount);
        return true;
    }




    function receiveTransfer(address from, uint tokens, bytes memory data) public returns (string memory status) {
        require(msg.sender == tokenAddress, "Unknown token");

        string memory result;
        if (data.length == 0) { //registration, purchase or renew cost
            require(tokens == regCost, "Wrong token amount");
            require(!paymentQueue[from].is_tokens_paid, "tokens paid, ETH awaiting");

            if (!isUserExists(from)) {
                if (!paymentQueue[from].is_eth_paid) {
                    paymentQueue[from].is_tokens_paid = true;
                    result = "Tokens accepted. Waiting ETH payment for registration completion";
                } else {
                    paymentQueue[from].is_eth_paid = false;
                    registration(from, paymentQueue[from].referrer);
                    result = "Registration is completed";
                }
            } else {
                require(users[from].matrices_cnt < 150 || paymentQueue[from].matrix_to_renew != 0, "max 150 hpeasy allowed");

                if (!paymentQueue[from].is_eth_paid) {
                    paymentQueue[from].is_tokens_paid = true;
                    result = "Tokens accepted. Waiting ETH payment for HpEasy purchase/renew";
                } else {
                    paymentQueue[from].is_eth_paid = false;
                    if (paymentQueue[from].matrix_to_renew != 0) {
                        renew(from, paymentQueue[from].matrix_to_renew);
                        paymentQueue[from].matrix_to_renew = 0;
                        result = "Renew is completed";
                    } else {
                        purchase(from);
                        result = "Purchase is completed";
                    }
                }
            }
        } else { //jackpot 
            require(!jackpotQueue[from].is_tokens_paid, "already paid jackpot cost in tokens, ETH awaiting");
            
            uint line = deserializeUint32(data);

            if (!jackpotQueue[from].is_eth_paid) {
                require(tokens == 0.001 ether || tokens == 0.005 ether || tokens == 0.015 ether || tokens == 0.05 ether || tokens == 0.15 ether || tokens == 0.5 ether, "No such bet size"); 
                require(line == 10 || line == 50 || line == 200 || line == 500, "No such bet line"); 
                jackpotQueue[from].is_tokens_paid = true;
                jackpotQueue[from].line = line;
                jackpotQueue[from].bet_size = tokens;
                result = "Waiting ETH payment for jackpot bet acceptance";
            } else {
                require(jackpotQueue[from].line == line && jackpotQueue[from].bet_size == tokens, "wrong line or bet size");
                result = addJackpotBet(jackpotQueue[from].line, jackpotQueue[from].bet_size);
                delete jackpotQueue[from];
            }
        }

        return result;
    }     

    function register(address referrer) public payable {
        require(msg.value == regCost, "not correct registration cost");
        require(!isUserExists(msg.sender), "user exists");
        require(isUserExists(referrer), "referrer not exists");
        require(!paymentQueue[msg.sender].is_eth_paid, "already paid registration cost in ETH, tokens awaiting");
        
        if (!useTokenPayment) {
            registration(msg.sender, referrer);
        } else if (!paymentQueue[msg.sender].is_tokens_paid) {
            paymentQueue[msg.sender].is_eth_paid = true;
            paymentQueue[msg.sender].referrer = referrer;
        } else {
            paymentQueue[msg.sender].is_tokens_paid = false;
            registration(msg.sender, referrer);
        }
    }

    function purchaseHpEasyPosition() public payable {
        require(msg.value == regCost, "not correct purchase cost"); 
        require(isUserExists(msg.sender), "user not exists");
        require(users[msg.sender].matrices_cnt < 150, "max 150 hpeasy allowed");
        require(!paymentQueue[msg.sender].is_eth_paid, "already paid in ETH, tokens awaiting");

        if (!useTokenPayment) {
            purchase(msg.sender);
        } else if(!paymentQueue[msg.sender].is_tokens_paid) {
            paymentQueue[msg.sender].is_eth_paid = true;
        } else {
            paymentQueue[msg.sender].is_tokens_paid = false;
            purchase(msg.sender);
        }
    }
    
    function renewMatrix(uint matrixToRenew) public payable {
        require(msg.value == regCost, "not correct renew cost"); 
        require(matrices[matrixToRenew].bunch_cycles >= bunchCyclesLimit, "matrix is active");
        require(isUserExists(msg.sender), "user not exists");
        require(!paymentQueue[msg.sender].is_eth_paid, "already paid in ETH, token payment awaiting");
        require(matrices[matrixToRenew].owner == msg.sender, "not user's matrix");

        if (!useTokenPayment) { 
            renew(msg.sender, matrixToRenew);
        } else if(!paymentQueue[msg.sender].is_tokens_paid) {
            paymentQueue[msg.sender].is_eth_paid = true;
            paymentQueue[msg.sender].matrix_to_renew = matrixToRenew;
        } else {
            paymentQueue[msg.sender].is_tokens_paid = false;
            renew(msg.sender, matrixToRenew);
        }
    }




    function registration(address userAddress, address referrerAddress) private {
        users[userAddress] = User({
            id: lastUserId,
            referrer: referrerAddress,
            matrices_cnt: 0,
            current_matrix: 0,
            last_matrix: 0,
            hpeasy_cooldown_time: 0,
            hpeasy_cooldown_num: 0,
            direct_referrals: 0
            });

        usersById[lastUserId] = userAddress;

        lastUserId++;

        users[referrerAddress].direct_referrals++;

        payUser(referrerAddress, regCost * 10 / 100); 
        payFounders(regCost * 10 / 100); 
        joinHpEasy(lastMatrixId, userAddress, false);
        fillMatrix(userAddress, referrerAddress, 0);
        
        emit Registration(userAddress, referrerAddress, users[userAddress].id, users[referrerAddress].id);
    }

    function purchase(address userAddress) private  {
        if (users[userAddress].hpeasy_cooldown_time < now - 86400) {
            users[userAddress].hpeasy_cooldown_time = now;
            users[userAddress].hpeasy_cooldown_num = 1;
        } else {
            if (users[userAddress].hpeasy_cooldown_num < 3) {
                users[userAddress].hpeasy_cooldown_num++;
            } else {
                revert("24h purchase limit");
            }
        }

        payUser(users[userAddress].referrer, regCost * 10 / 100); 
        payFounders(regCost * 10 / 100); 
        joinHpEasy(lastMatrixId, userAddress, false); 
        fillMatrix(userAddress, users[userAddress].referrer, 1);
    }

    function renew(address userAddress, uint matrixToRenew) private  {
        payUser(users[userAddress].referrer, regCost * 10 / 100); 
        payFounders(regCost * 10 / 100); 
        joinHpEasy(matrixToRenew, userAddress, true); 
        payForMatrix(matrices[matrixToRenew].matrix_referrer);
    }

    function joinHpEasy(uint matrixId, address matrixOwner, bool isRenew) private {
        HpEasy[lastHpEasyId] = HpEasyLine({
            matrix_id: matrixId,
            owner: matrixOwner
            });
        lastHpEasyId++;

        if (matrices[matrixId].id != 0) {
            if (isRenew) {
                matrices[matrixId].bunch_cycles = 0; 
            } else {
                matrices[matrixId].cycles++;
                matrices[matrixId].bunch_cycles++; 
            }
        }
        
        if (lastHpEasyId % 2 == 0) {
            if (lastHpEasyId > 2) {
                uint currentHp = skippedHpEasysOffset + lastHpEasyId / 2 - 1;
                
                while (matrices[HpEasy[currentHp].matrix_id].bunch_cycles >= bunchCyclesLimit
                        && (lastHpEasyId / 2 + skippedHpEasysOffset < lastHpEasyId - 2)) { 
                    emit SkipMatrix(HpEasy[currentHp].matrix_id);
                    skippedHpEasysOffset++;
                    currentHp++;
                }

                payHpEasy(HpEasy[currentHp].owner);
                joinHpEasy(HpEasy[currentHp].matrix_id, HpEasy[currentHp].owner, false);
                payForMatrix(matrices[HpEasy[currentHp].matrix_id].matrix_referrer);
            } else {
                payHpEasy(owner);
                payForMatrix(0);
            }
        }
    }

    function payForMatrix(uint slotId) private {
        if (slotId == 0) {
            payUser(matrices[1].owner, regCost * 25 / 100); 
            return;
        }

        uint unspent = 0;
        address lastEligible;
        uint level1 = slotId;

        if (users[matrices[level1].owner].direct_referrals < 4 || matrices[level1].bunch_cycles >= bunchCyclesLimit) { 
            unspent = regCost * 25 / 1000;
        } else {
            payUser(matrices[level1].owner, regCost * 25 / 1000);
            lastEligible = matrices[level1].owner;
        }

        uint level2 = matrices[level1].matrix_referrer;

        if (level2 == 0) {
            if (lastEligible != address(0)) {
                payUser(lastEligible, regCost * 225 / 1000); 
            } else {
                payUser(matrices[1].owner, regCost * 25 / 100); 
            }
            return;
        } else if (users[matrices[level2].owner].direct_referrals < 4 || matrices[level2].bunch_cycles >= bunchCyclesLimit) { 
            unspent += regCost * 5 / 100;
        } else {
            payUser(matrices[level2].owner, unspent + regCost * 5 / 100);
            lastEligible = matrices[level2].owner;
            unspent = 0;
        }

        uint level3 = matrices[level2].matrix_referrer;

        if (level3 == 0) {
            if (lastEligible != address(0)) {
                payUser(lastEligible, regCost * 175 / 1000 + unspent); 
            } else {
                payUser(matrices[1].owner, regCost * 25 / 100); 
            }
            return;
        } else if (users[matrices[level3].owner].direct_referrals < 4 || matrices[level3].bunch_cycles >= bunchCyclesLimit) { 
            unspent += regCost * 75 / 1000;
        } else {
            payUser(matrices[level3].owner, unspent + regCost * 75 / 1000);
            lastEligible = matrices[level3].owner;
            unspent = 0;
        }

        uint level4 = matrices[level3].matrix_referrer;

        if (level4 == 0) {
            if (lastEligible != address(0)) {
                payUser(lastEligible, regCost * 10 / 100 + unspent); 
            } else {
                payUser(matrices[1].owner, regCost * 25 / 100); 
            }
            return;
        } else if (users[matrices[level4].owner].direct_referrals < 4 || matrices[level4].bunch_cycles >= bunchCyclesLimit) { 
            unspent += regCost * 10 / 100;
        } else {
            payUser(matrices[level4].owner, unspent + regCost * 10 / 100);
            lastEligible = matrices[level4].owner;
            unspent = 0;
        }

        if (unspent == regCost * 25 / 100) {
            while (users[matrices[level4].owner].direct_referrals < 4 || matrices[level4].bunch_cycles >= bunchCyclesLimit) {
                if (level4 == 0) {
                    payUser(matrices[1].owner, unspent);
                    return;
                }

                level4 = matrices[level4].matrix_referrer;
            }

            payUser(matrices[level4].owner, unspent);
        } else if (unspent != 0) {
            payUser(lastEligible, unspent);
        }
    }

    function fillMatrix(address user, address referrer, uint from_hpeasy) private {
        if (referrer == address(0)) {
            referrer = usersById[1];
        }

        uint slotId = findSlot(usersMatrices[users[referrer].id][users[referrer].current_matrix], 1, 4);

        if (slotId == 0) {
            if (users[referrer].current_matrix == users[referrer].matrices_cnt-1) {
                revert("all matrices are full");
            }

            users[referrer].current_matrix++;
            slotId = findSlot(usersMatrices[users[referrer].id][users[referrer].current_matrix], 1, 4);
        }

        payForMatrix(slotId);

        matrices[lastMatrixId] = Matrix({
            id: lastMatrixId,
            owner: user,
            referrals_cnt: 0,
            matrix_referrer: slotId,
            from_hpeasy: from_hpeasy,
            direct_referrer: referrer,
            cycles: 0,
            bunch_cycles: 0
            });

        usersMatrices[users[user].id][users[user].matrices_cnt] = lastMatrixId;
        users[user].matrices_cnt++;
        users[user].last_matrix = lastMatrixId;

        matrices[lastMatrixId].matrix_referrer = slotId;

        lastMatrixId++;

        matrices[slotId].referrals[matrices[slotId].referrals_cnt] = lastMatrixId-1;
        matrices[slotId].referrals_cnt++;
    }

    function findSlot(uint matrix, uint level, uint maxLevel) private returns (uint) {
        if (level > maxLevel) {
            return(0);
        }

        if (matrices[matrix].referrals_cnt < 4) {
            return(matrix);
        }

        uint tmpMaxLevel = level+1;

        while (tmpMaxLevel <= maxLevel) {
            uint i=0;

            do {
                uint slot = findSlot(matrices[matrix].referrals[i], level+1, tmpMaxLevel);
                if (slot != 0) {
                    return(slot);
                }

                i++;
            } while (i<4);

            tmpMaxLevel++;
        }

        return(0);
    }

    function payUser(address user, uint amount) private {
        emit Transfer(user, users[user].id, amount);
        address(uint160(user)).transfer(amount);
        if (useTokenPayment) {
            require(payInTokens(user, amount));
        }
    }

    function payHpEasy(address user) private {
        emit Transfer(user, users[user].id, regCost * 30 / 100);
        address(uint160(user)).transfer(regCost * 30 / 100);
        if (useTokenPayment) {
            require(payInTokens(user, regCost * 30 / 100)); 
        }
    }

    function payFounders(uint amount) private {
        uint founderAmount;

		for (uint i=0; i < founders.length; i++) {
			if (i < 4 ) {
                founderAmount = amount * 20 / 100;
            } else {
                founderAmount = amount * 5 / 100;
            }
            emit Transfer(founders[i], 0, founderAmount);
            address(uint160(founders[i])).transfer(founderAmount);
            if (useTokenPayment) { 
                payInTokens(founders[i], founderAmount);
            }
		}
    }

    function payInTokens(address to, uint amount) private returns (bool success) {
        return ERC20(tokenAddress).transfer(to, amount);
    }



    
    function joinJackpot(uint line) public payable returns(string memory status) {
        require(!jackpotQueue[msg.sender].is_eth_paid, "already paid ETH, tokens awaiting");
        
        string memory result;
        if (!useTokenPayment) {
            result = addJackpotBet(line, msg.value);
        } else if (!jackpotQueue[msg.sender].is_tokens_paid) {
            require(msg.value == 0.001 ether || msg.value == 0.005 ether || msg.value == 0.015 ether || msg.value == 0.05 ether || msg.value == 0.15 ether || msg.value == 0.5 ether, "No such bet size"); 
            require(line == 10 || line == 50 || line == 200 || line == 500, "No such bet line");  
            jackpotQueue[msg.sender].line = line;
            jackpotQueue[msg.sender].is_eth_paid = true;
            jackpotQueue[msg.sender].bet_size = msg.value;
            result = "Waiting token payment for jackpot bet acceptance";
        } else {
            require(jackpotQueue[msg.sender].line == line && jackpotQueue[msg.sender].bet_size == msg.value, "wrong line or bet size");
            result = addJackpotBet(jackpotQueue[msg.sender].line, jackpotQueue[msg.sender].bet_size);
            delete jackpotQueue[msg.sender];
        }

        return result;
    }

    function addJackpotBet(uint line, uint betSize) private returns(string memory status) {
        bets[line][betSize].push(msg.sender);
        
        if (bets[line][betSize].length == line) { 
            defineWinner(line);
            return ("This line winner is defined");
        } else {
            return ("Your bet is accepted");
        }
    }
    
    function betsLineFilling(uint line, uint betSize) public view returns (uint length) { 
        return bets[line][betSize].length;
    }

    function betsLineAddresses(uint line, uint betSize) public view returns (address[] memory participants) { 
        return bets[line][betSize];
    }

    function defineWinner(uint line) private {  
        uint additionalSeed = uint(blockhash(block.number - 1)); 
        uint rnd = 0;
        
        while(rnd < line) { 
            rnd += additionalSeed * seed;
        }
        
        address winnerAddress = bets[line][msg.value][rnd % line];
        uint winnerAmount = line * msg.value * 9 / 10;
        uint transactionalCost = line * msg.value / 10;
        
        address(uint160(winnerAddress)).transfer(winnerAmount);
        payInTokens(winnerAddress, winnerAmount);
        emit NewJackpotWinner(line, msg.value, winnerAmount, winnerAddress);

        payFounders(transactionalCost);

        delete bets[line][msg.value]; 

        seed = additionalSeed;
    }

    function deserializeUint32(bytes memory data) private pure returns (uint)
    {
        uint32 res = 0;

        for (uint i = 0; i < 4; i++)
        {
            uint32 temp = uint32(uint8(data[i]));
            temp <<= 8 * i;
            res ^= temp;
        }

        return uint(res);
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):