ETH Price: $1,951.21 (-1.89%)
Gas: 0.03 Gwei

Transaction Decoder

Block:
9202084 at Jan-02-2020 05:00:33 PM +UTC
Transaction Fee:
0.00395453 ETH $7.72
Gas Used:
395,453 Gas / 10 Gwei

Emitted Events:

100 Absolutus.PaymentForHolder( _addr=0x292ba92eeac6081d15286c0c3fb62756472c9835, _index=1, _value=42000000000000000 )
101 Absolutus.PaymentForHolder( _addr=0x1a89f6af888035c8e2512f3701c9f7b478ec4a4c, _index=2, _value=4000000000000000 )
102 Absolutus.PaymentForHolder( _addr=0x38b13ec169f30518ed220c72e70a306edbea96d3, _index=3, _value=4000000000000000 )
103 Absolutus.GetMoneyForLevelEvent( _user=0x9dc56c606938cd32267ec9e81ef92325e99cb692, _referral=[Sender] 0x82683f46c69e068f244d86103317b37ebbf93779, _level=1, _time=1577984433, _price=450000000000000000, _prevLost=False )
104 Absolutus.PaymentForHolder( _addr=0x292ba92eeac6081d15286c0c3fb62756472c9835, _index=1, _value=84000000000000000 )
105 Absolutus.PaymentForHolder( _addr=0x1a89f6af888035c8e2512f3701c9f7b478ec4a4c, _index=2, _value=8000000000000000 )
106 Absolutus.PaymentForHolder( _addr=0x38b13ec169f30518ed220c72e70a306edbea96d3, _index=3, _value=8000000000000000 )
107 Absolutus.GetMoneyForLevelEvent( _user=0xc04c4c118d9fa554e19af2c1dfa5427d6c40926f, _referral=0x9dc56c606938cd32267ec9e81ef92325e99cb692, _level=2, _time=1577984433, _price=900000000000000000, _prevLost=False )
108 Absolutus.BuyLevelEvent( _user=0x9dc56c606938cd32267ec9e81ef92325e99cb692, _level=2, _time=1577984433 )
109 Absolutus.RegLevelEvent( _user=[Sender] 0x82683f46c69e068f244d86103317b37ebbf93779, _referrer=0x9dc56c606938cd32267ec9e81ef92325e99cb692, _id=745, _time=1577984433 )

Account State Difference:

  Address   Before After State Difference Code
0x0C9e046e...FbD827260 134.1 Eth133.2 Eth0.9
0x1a89f6AF...478ec4A4c 9.5939105 Eth9.6059105 Eth0.012
0x292BA92E...6472c9835 4.91756986867 Eth5.04356986867 Eth0.126
0x38b13eC1...EDBEA96d3 10.08087041 Eth10.09287041 Eth0.012
0x82683f46...ebbF93779
0.5388651749 Eth
Nonce: 94
0.0349106449 Eth
Nonce: 95
0.50395453
(F2Pool Old)
5,775.062534558657312112 Eth5,775.066489088657312112 Eth0.00395453
0x9DC56C60...5e99cb692 1.185189121788329593 Eth1.535189121788329593 Eth0.35
0xc04C4c11...d6C40926f 0.5433392413 Eth1.4433392413 Eth0.9

Execution Trace

ETH 0.5 Absolutus.9dc56c60( )
  • AbsDAO.STATICCALL( )
  • AbsDAO.getHolderPieAt( i=1 ) => ( 84 )
  • AbsDAO.getHolder( i=1 ) => ( 0x292BA92EeAC6081d15286c0c3fb62756472c9835 )
  • ETH 0.042 0x292ba92eeac6081d15286c0c3fb62756472c9835.CALL( )
  • AbsDAO.getHolderPieAt( i=2 ) => ( 8 )
  • AbsDAO.getHolder( i=2 ) => ( 0x1a89f6AF888035C8e2512F3701C9f7B478ec4A4c )
  • ETH 0.004 0x1a89f6af888035c8e2512f3701c9f7b478ec4a4c.CALL( )
  • AbsDAO.getHolderPieAt( i=3 ) => ( 8 )
  • AbsDAO.getHolder( i=3 ) => ( 0x38b13eC169f30518eD220C72E70a306EDBEA96d3 )
  • ETH 0.004 0x38b13ec169f30518ed220c72e70a306edbea96d3.CALL( )
  • AbsDAO.STATICCALL( )
  • AbsDAO.getHolderPieAt( i=1 ) => ( 84 )
  • AbsDAO.getHolder( i=1 ) => ( 0x292BA92EeAC6081d15286c0c3fb62756472c9835 )
  • ETH 0.084 0x292ba92eeac6081d15286c0c3fb62756472c9835.CALL( )
  • AbsDAO.getHolderPieAt( i=2 ) => ( 8 )
  • AbsDAO.getHolder( i=2 ) => ( 0x1a89f6AF888035C8e2512F3701C9f7B478ec4A4c )
  • ETH 0.008 0x1a89f6af888035c8e2512f3701c9f7b478ec4a4c.CALL( )
  • AbsDAO.getHolderPieAt( i=3 ) => ( 8 )
  • AbsDAO.getHolder( i=3 ) => ( 0x38b13eC169f30518eD220C72E70a306EDBEA96d3 )
  • ETH 0.008 0x38b13ec169f30518ed220c72e70a306edbea96d3.CALL( )
  • ETH 0.9 0xc04c4c118d9fa554e19af2c1dfa5427d6c40926f.CALL( )
  • ETH 0.35 0x9dc56c606938cd32267ec9e81ef92325e99cb692.CALL( )
    File 1 of 2: Absolutus
    /**
    * Absolutus smart contract by BioHazzardt
    */
    pragma solidity ^0.5.7;
    
    
    /**
     * @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 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) {
            uint256 c = a * b;
            require(a == 0 || c / a == b, 'Invalid values');
            return c;
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts with custom message 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.
         *
         * _Available since v2.4.0._
         */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a / b;
            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, 'Substraction result smaller than zero');
            return 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, 'Invalid values');
            return c;
        }
    }
    
    
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    contract Ownable {
        address public owner;
        address public manager;
        address public ownerWallet;
        address public adminWallet;
        uint adminPersent;
    
        constructor() public {
            owner = msg.sender;
            manager = msg.sender;
            adminWallet = 0xcFebf7C3Ec7B407DFf17aa20a2631c95c8ff508c;
            ownerWallet = 0xcFebf7C3Ec7B407DFf17aa20a2631c95c8ff508c;
            adminPersent = 10;
        }
    
        modifier onlyOwner() {
            require(msg.sender == owner, "only for owner");
            _;
        }
    
        modifier onlyOwnerOrManager() {
            require((msg.sender == owner)||(msg.sender == manager), "only for owner or manager");
            _;
        }
    
        function transferOwnership(address newOwner) public onlyOwner {
            owner = newOwner;
        }
    
        function setManager(address _manager) public onlyOwnerOrManager {
            manager = _manager;
        }
    
        function setAdminWallet(address _admin) public onlyOwner {
            adminWallet = _admin;
        }
    }
    
    
    contract WalletOnly {
        function isContract(address account) internal view returns (bool) {
            // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
            // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
            // for accounts without code, i.e. `keccak256('')`
            bytes32 codehash;
            bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
            // solhint-disable-next-line no-inline-assembly
            assembly { codehash := extcodehash(account) }
            return (codehash != accountHash && codehash != 0x0);
        }
    }
    
    
    contract Absolutus is Ownable, WalletOnly {
        // Events
        event RegLevelEvent(address indexed _user, address indexed _referrer, uint _id, uint _time);
        event BuyLevelEvent(address indexed _user, uint _level, uint _time);
        event ProlongateLevelEvent(address indexed _user, uint _level, uint _time);
        event GetMoneyForLevelEvent(address indexed _user, address indexed _referral, uint _level, uint _time, uint _price, bool _prevLost);
        event LostMoneyForLevelEvent(address indexed _user, address indexed _referral, uint _level, uint _time, uint _price, bool _prevLost);
    
        // New events
        event PaymentForHolder(address indexed _addr, uint _index, uint _value);
        event PaymentForHolderLost(address indexed _addr, uint _index, uint _value);
    
        // Common values
        mapping (uint => uint) public LEVEL_PRICE;
        address canSetLevelPrice;
        uint REFERRER_1_LEVEL_LIMIT = 3;
        uint PERIOD_LENGTH = 365 days; // uncomment before production
        uint MAX_AUTOPAY_COUNT = 5;     // Automatic level buying limit per one transaction (to prevent gas limit reaching)
    
        struct UserStruct {
            bool isExist;
            uint id;
            uint referrerID;
            uint fund;          // Fund for the automatic level pushcase
            uint currentLvl;    // Current user's level
            address[] referral;
            mapping (uint => uint) levelExpired;
            mapping (uint => uint) paymentsCount;
        }
    
        mapping (address => UserStruct) public users;
        mapping (uint => address) public userList;
        mapping (address => uint) public allowUsers;
    
        uint public currUserID = 0;
        bool nostarted = false;
    
        AbsDAO _dao; // DAO contract
        bool daoSet = false; // if true payment processed for DAO holders
    
        using SafeMath for uint; // <== do not forget about this
    
        constructor() public {
            // Prices in ETH: production
            LEVEL_PRICE[1] = 0.5 ether;
            LEVEL_PRICE[2] = 1.0 ether;
            LEVEL_PRICE[3] = 2.0 ether;
            LEVEL_PRICE[4] = 4.0 ether;
            LEVEL_PRICE[5] = 16.0 ether;
            LEVEL_PRICE[6] = 32.0 ether;
            LEVEL_PRICE[7] = 64.0 ether;
            LEVEL_PRICE[8] = 128.0 ether;
    
            UserStruct memory userStruct;
            currUserID++;
    
            canSetLevelPrice = owner;
    
            // Create root user
            userStruct = UserStruct({
                isExist : true,
                id : currUserID,
                referrerID : 0,
                fund: 0,
                currentLvl: 1,
                referral : new address[](0)
            });
    
            users[ownerWallet] = userStruct;
            userList[currUserID] = ownerWallet;
    
            users[ownerWallet].levelExpired[1] = 77777777777;
            users[ownerWallet].levelExpired[2] = 77777777777;
            users[ownerWallet].levelExpired[3] = 77777777777;
            users[ownerWallet].levelExpired[4] = 77777777777;
            users[ownerWallet].levelExpired[5] = 77777777777;
            users[ownerWallet].levelExpired[6] = 77777777777;
            users[ownerWallet].levelExpired[7] = 77777777777;
            users[ownerWallet].levelExpired[8] = 77777777777;
    
            // Set inviting registration only
            nostarted = true;
        }
    
        function () external payable {
            require(!isContract(msg.sender), 'This contract cannot support payments from other contracts');
    
            uint level;
    
            // Check for payment with level price
            if (msg.value == LEVEL_PRICE[1]) {
                level = 1;
            } else if (msg.value == LEVEL_PRICE[2]) {
                level = 2;
            } else if (msg.value == LEVEL_PRICE[3]) {
                level = 3;
            } else if (msg.value == LEVEL_PRICE[4]) {
                level = 4;
            } else if (msg.value == LEVEL_PRICE[5]) {
                level = 5;
            } else if (msg.value == LEVEL_PRICE[6]) {
                level = 6;
            } else if (msg.value == LEVEL_PRICE[7]) {
                level = 7;
            } else if (msg.value == LEVEL_PRICE[8]) {
                level = 8;
            } else {
                // Pay to user's fund
                if (!users[msg.sender].isExist || users[msg.sender].currentLvl >= 8)
                    revert('Incorrect Value send');
    
                users[msg.sender].fund += msg.value;
                updateCurrentLevel(msg.sender);
                // if the referer is have funds for autobuy next level
                if (LEVEL_PRICE[users[msg.sender].currentLvl+1] <= users[msg.sender].fund) {
                    buyLevelByFund(msg.sender, 0);
                }
                return;
            }
    
            // Buy level or register user
            if (users[msg.sender].isExist) {
                buyLevel(level);
            } else if (level == 1) {
                uint refId = 0;
                address referrer = bytesToAddress(msg.data);
    
                if (users[referrer].isExist) {
                    refId = users[referrer].id;
                } else {
                    revert('Incorrect referrer');
                    // refId = 1;
                }
    
                regUser(refId);
            } else {
                revert("Please buy first level for 0.1 ETH");
            }
        }
    
        // allow user in invite mode
        function allowUser(address _user) public onlyOwner {
            require(nostarted, 'You cant allow user in battle mode');
            allowUsers[_user] = 1;
        }
    
        // disable inviting
        function battleMode() public onlyOwner {
            require(nostarted, 'Battle mode activated');
            nostarted = false;
        }
    
        // this function sets the DAO contract address
        function setDAOAddress(address payable _dao_addr) public onlyOwner {
            require(!daoSet, 'DAO address already set');
            _dao = AbsDAO(_dao_addr);
            daoSet = true;
        }
    
        // process payment to administrator wallet
        // or DAO holders
        function payToAdmin(uint _amount) internal {
            if (daoSet) {
                // Pay for DAO
                uint holderCount = _dao.getHolderCount();       // get the DAO holders count
                for (uint i = 1; i <= holderCount; i++) {
                    uint val = _dao.getHolderPieAt(i);          // get pie of holder with index == i
                    address payable holder = _dao.getHolder(i); // get the holder address
    
                    if (val > 0) {                              // check of the holder pie value
                        uint payValue = _amount.div(100).mul(val); // calculate amount for pay to the holder
                        holder.transfer(payValue);
                        emit PaymentForHolder(holder, i, payValue); // payment ok
                    } else {
                        emit PaymentForHolderLost(holder, i, val); // holder's pie value is zero
                    }
                }
            } else {
                // pay to admin wallet
                address(uint160(adminWallet)).transfer(_amount);
            }
        }
    
        // user registration
        function regUser(uint referrerID) public payable {
            require(!isContract(msg.sender), 'This contract cannot support payments from other contracts');
    
            if (nostarted) {
                require(allowUsers[msg.sender] > 0, 'You cannot use this contract on start');
            }
    
            require(!users[msg.sender].isExist, 'User exist');
            require(referrerID > 0 && referrerID <= currUserID, 'Incorrect referrer Id');
            require(msg.value==LEVEL_PRICE[1], 'Incorrect Value');
    
            // NOTE: use one more variable to prevent 'Security/No-assign-param' error (for vscode-solidity extension).
            // Need to check the gas consumtion with it
            uint _referrerID = referrerID;
    
            if (users[userList[referrerID]].referral.length >= REFERRER_1_LEVEL_LIMIT) {
                _referrerID = users[findFreeReferrer(userList[referrerID])].id;
            }
    
    
            UserStruct memory userStruct;
            currUserID++;
    
            // add user to list
            userStruct = UserStruct({
                isExist : true,
                id : currUserID,
                referrerID : _referrerID,
                fund: 0,
                currentLvl: 1,
                referral : new address[](0)
            });
    
            users[msg.sender] = userStruct;
            userList[currUserID] = msg.sender;
    
            users[msg.sender].levelExpired[1] = now + PERIOD_LENGTH;
            users[msg.sender].levelExpired[2] = 0;
            users[msg.sender].levelExpired[3] = 0;
            users[msg.sender].levelExpired[4] = 0;
            users[msg.sender].levelExpired[5] = 0;
            users[msg.sender].levelExpired[6] = 0;
            users[msg.sender].levelExpired[7] = 0;
            users[msg.sender].levelExpired[8] = 0;
    
            users[userList[_referrerID]].referral.push(msg.sender);
    
            // pay for referer
            payForLevel(
                1,
                msg.sender,
                msg.sender,
                0,
                false
            );
    
            emit RegLevelEvent(
                msg.sender,
                userList[_referrerID],
                currUserID,
                now
            );
        }
    
        // buy level function
        function buyLevel(uint _level) public payable {
            require(!isContract(msg.sender), 'This contract cannot support payments from other contracts');
    
            require(users[msg.sender].isExist, 'User not exist');
            require(_level>0 && _level<=8, 'Incorrect level');
            require(msg.value==LEVEL_PRICE[_level], 'Incorrect Value');
    
            if (_level > 1) { // Replace for condition (_level == 1) on top (done)
                for (uint i = _level-1; i>0; i--) {
                    require(users[msg.sender].levelExpired[i] >= now, 'Buy the previous level');
                }
            }
    
            // if(users[msg.sender].levelExpired[_level] == 0){ <-- BUG
            // if the level expired in the future, need add PERIOD_LENGTH to the level expiration time,
            // or set the level expiration time to 'now + PERIOD_LENGTH' in other cases.
            if (users[msg.sender].levelExpired[_level] > now) {
                users[msg.sender].levelExpired[_level] += PERIOD_LENGTH;
            } else {
                users[msg.sender].levelExpired[_level] = now + PERIOD_LENGTH;
            }
    
            // Set user's current level
            if (users[msg.sender].currentLvl < _level)
                users[msg.sender].currentLvl = _level;
    
            // provide payment for the user's referer
            payForLevel(
                _level,
                msg.sender,
                msg.sender,
                0,
                false
            );
    
            emit BuyLevelEvent(msg.sender, _level, now);
        }
    
        function setLevelPrice(uint _level, uint _price) public {
            require(_level >= 0 && _level <= 8, 'Invalid level');
            require(msg.sender == canSetLevelPrice, 'Invalid caller');
            require(_price > 0, 'Price cannot be zero or negative');
    
            LEVEL_PRICE[_level] = _price * 1.0 finney;
        }
    
        function setCanUpdateLevelPrice(address addr) public onlyOwner {
            canSetLevelPrice = addr;
        }
    
        // for interactive correction of the limitations
        function setMaxAutopayForLevelCount(uint _count) public onlyOwnerOrManager {
            MAX_AUTOPAY_COUNT = _count;
        }
    
        // buyLevelByFund provides automatic payment for next level for user
        function buyLevelByFund(address referer, uint _counter) internal {
            require(users[referer].isExist, 'User not exists');
    
            uint _level = users[referer].currentLvl + 1; // calculate a next level
            require(users[referer].fund >= LEVEL_PRICE[_level], 'Not have funds to autobuy level');
    
            uint remaining = users[referer].fund - LEVEL_PRICE[_level]; // Amount for pay to the referer
    
            // extend the level's expiration time
            if (users[referer].levelExpired[_level] >= now) {
                users[referer].levelExpired[_level] += PERIOD_LENGTH;
            } else {
                users[referer].levelExpired[_level] = now + PERIOD_LENGTH;
            }
    
            users[referer].currentLvl = _level; // set current level for referer
            users[referer].fund = 0;            // clear the referer's fund
    
            // process payment for next referer with increment autopay counter
            payForLevel(
                _level,
                referer,
                referer,
                _counter+1,
                false
            );
            address(uint160(referer)).transfer(remaining); // send the remaining amount to referer
    
            emit BuyLevelEvent(referer, _level, now); // emit the buy level event for referer
        }
    
        // updateCurrentLevel calculate 'currentLvl' value for given user
        function updateCurrentLevel(address _user) internal {
            users[_user].currentLvl = actualLevel(_user);
        }
    
        // helper function
        function actualLevel(address _user) public view returns(uint) {
            require(users[_user].isExist, 'User not found');
    
            for (uint i = 1; i <= 8; i++) {
                if (users[_user].levelExpired[i] <= now) {
                    return i-1;
                }
            }
    
            return 8;
        }
    
        // payForLevel provides payment processing for user's referer and automatic buying referer's next
        // level.
        function payForLevel(uint _level, address _user, address _sender, uint _autoPayCtr, bool prevLost) internal {
            address referer;
            address referer1;
            address referer2;
            address referer3;
    
            if (_level == 1 || _level == 5) {
                referer = userList[users[_user].referrerID];
            } else if (_level == 2 || _level == 6) {
                referer1 = userList[users[_user].referrerID];
                referer = userList[users[referer1].referrerID];
            } else if (_level == 3 || _level == 7) {
                referer1 = userList[users[_user].referrerID];
                referer2 = userList[users[referer1].referrerID];
                referer = userList[users[referer2].referrerID];
            } else if (_level == 4 || _level == 8) {
                referer1 = userList[users[_user].referrerID];
                referer2 = userList[users[referer1].referrerID];
                referer3 = userList[users[referer2].referrerID];
                referer = userList[users[referer3].referrerID];
            }
    
            if (!users[referer].isExist) {
                referer = userList[1];
            }
    
            uint amountToUser;
            uint amountToAdmin;
    
            amountToAdmin = LEVEL_PRICE[_level] / 100 * adminPersent;
            amountToUser = LEVEL_PRICE[_level] - amountToAdmin;
    
            if (users[referer].id <= 4) {
                payToAdmin(LEVEL_PRICE[_level]);
    
                emit GetMoneyForLevelEvent(
                    referer,
                    _sender,
                    _level,
                    now,
                    amountToUser,
                    prevLost
                );
    
                return;
            }
    
            if (users[referer].levelExpired[_level] >= now) {
                payToAdmin(amountToAdmin);
    
                // update current referer's level
                updateCurrentLevel(referer);
    
    
                // check for the user has right level and automatic payment counter
                // smaller than the 'MAX_AUTOPAY_COUNT' value
                if (_level == users[referer].currentLvl && _autoPayCtr < MAX_AUTOPAY_COUNT && users[referer].currentLvl < 8) {
                    users[referer].fund += amountToUser;
    
                    emit GetMoneyForLevelEvent(
                        referer,
                        _sender,
                        _level,
                        now,
                        amountToUser,
                        prevLost
                    );
    
                    // if the referer is have funds for autobuy next level
                    if (LEVEL_PRICE[users[referer].currentLvl+1] <= users[referer].fund) {
                        buyLevelByFund(referer, _autoPayCtr);
                    }
                } else {
                    // send the ethers to referer
                    address(uint160(referer)).transfer(amountToUser);
    
                    emit GetMoneyForLevelEvent(
                        referer,
                        _sender,
                        _level,
                        now,
                        amountToUser,
                        prevLost
                    );
                }
            } else {
                // pay for the referer's referer
                emit LostMoneyForLevelEvent(
                    referer,
                    _sender,
                    _level,
                    now,
                    amountToUser,
                    prevLost
                );
    
                payForLevel(
                    _level,
                    referer,
                    _sender,
                    _autoPayCtr,
                    true
                );
            }
        }
    
        function findFreeReferrer(address _user) public view returns(address) {
            if (users[_user].referral.length < REFERRER_1_LEVEL_LIMIT) {
                return _user;
            }
    
            address[] memory referrals = new address[](363);
            referrals[0] = users[_user].referral[0];
            referrals[1] = users[_user].referral[1];
            referrals[2] = users[_user].referral[2];
    
            address freeReferrer;
            bool noFreeReferrer = true;
    
            for (uint i = 0; i<363; i++) {
                if (users[referrals[i]].referral.length == REFERRER_1_LEVEL_LIMIT) {
                    if (i<120) {
                        referrals[(i+1)*3] = users[referrals[i]].referral[0];
                        referrals[(i+1)*3+1] = users[referrals[i]].referral[1];
                        referrals[(i+1)*3+2] = users[referrals[i]].referral[2];
                    }
                } else {
                    noFreeReferrer = false;
                    freeReferrer = referrals[i];
                    break;
                }
            }
            require(!noFreeReferrer, 'No Free Referrer');
            return freeReferrer;
        }
    
        function viewUserReferral(address _user) public view returns(address[] memory) {
            return users[_user].referral;
        }
    
        function viewUserLevelExpired(address _user, uint _level) public view returns(uint) {
            return users[_user].levelExpired[_level];
        }
    
        function bytesToAddress(bytes memory bys) private pure returns (address  addr ) {
            assembly {
                addr := mload(add(bys, 20))
            }
        }
    }
    
    
    contract AbsDAO is Ownable, WalletOnly {
        // events
        event TransferPie(address indexed _from, address indexed _to, uint _value);
        event NewHolder(address indexed _addr, uint _index);
        event HolderChanged(address indexed _from, address indexed _to, uint _index);
        event PaymentReceived(address indexed _from, uint _value);
        event PaymentForHolder(address indexed _addr, uint _index, uint _value);
        event PaymentForHolderLost(address indexed _addr, uint _index, uint _value);
    
        struct Holder {
            bool isExist;
            uint id;
            uint value;
            address payable addr;
        }
    
        mapping(address => Holder) public holders;
        mapping(uint=>address payable) holderAddrs;
    
        uint holderCount;
        uint _initialPie = 100;
    
        using SafeMath for uint;
    
        constructor() public {
            // creating root hoder
            holderCount = 1;
            holders[msg.sender] = Holder({
                isExist: true,
                id: 1,
                value: _initialPie,
                addr: msg.sender
            });
    
            holderAddrs[1] = msg.sender;
        }
    
        function () external payable {
            require(!isContract(msg.sender), 'This contract cannot support payments from other contracts');
    
            emit PaymentReceived(msg.sender, msg.value);
    
            for (uint i = 1; i <= holderCount; i++) {
                if (holders[holderAddrs[i]].value > 0) {
                    uint payValue = msg.value.div(100).mul(holders[holderAddrs[i]].value);
                    holderAddrs[i].transfer(payValue);
                    emit PaymentForHolder(holderAddrs[i], i, payValue);
                } else {
                    emit PaymentForHolderLost(holderAddrs[i], i, holders[holderAddrs[i]].value);
                }
            }
        }
    
        function getHolderPieAt(uint i) public view returns(uint) {
            return holders[holderAddrs[i]].value;
        }
    
        function getHolder(uint i) public view returns(address payable) {
            return holderAddrs[i];
        }
    
        function getHolderCount() public view returns(uint) {
            return holderCount;
        }
    
        function transferPie(uint _amount, address payable _to) public {
            require(holders[msg.sender].isExist, 'Holder not found');
            require(_amount > 0 && _amount <= holders[msg.sender].value, 'Invalid amount');
    
            if (_amount == holders[msg.sender].value) {
                uint id = holders[msg.sender].id;
                delete holders[msg.sender];
    
                holders[_to] = Holder({
                    isExist: true,
                    id: id,
                    value: _amount,
                    addr: _to
                });
    
                holderAddrs[id] = _to;
    
                emit HolderChanged(msg.sender, _to, id);
            } else {
                if (holders[_to].isExist) {
                    holders[msg.sender].value -= _amount;
                    holders[_to].value += _amount;
                } else if (holderCount < 20) {
                    holderCount += 1;
                    holders[msg.sender].value -= _amount;
                    holders[_to] = Holder({
                        isExist: true,
                        id: holderCount,
                        value: _amount,
                        addr: _to
                    });
    
                    holderAddrs[holderCount] = _to;
    
                    emit NewHolder(_to, holderCount);
                } else {
                    revert('Holder limit excised');
                }
            }
    
            emit TransferPie(msg.sender, _to, _amount);
        }
    }

    File 2 of 2: AbsDAO
    /*
    ❤ https://cryptohands.org - first open MLM smart-contract without comission
    ❤ https://doubleway.io - high-income binary matrix from the creators of CryptoHands
     
    
    ____0000000000______0000000000_____
    __000________000__000________000___
    _000___________0000___________000__
    000_____________00_____________000_
    000____________________________000_
    000____________________________000_
    _000________CRYPTOHANDS_______000__
    __000________DOUBLEWAY_______000___
    ___000_____________________000____
    _____000__________________000______
    _______000______________000________
    _________000__________000__________
    ____________000____000_____________
    ______________000000_______________
    ________________00_________________
    */
    pragma solidity ^0.5.7;
    /**
     * @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 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) {
            uint256 c = a * b;
            require(a == 0 || c / a == b, 'Invalid values');
            return c;
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts with custom message 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.
         *
         * _Available since v2.4.0._
         */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a / b;
            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, 'Substraction result smaller than zero');
            return 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, 'Invalid values');
            return c;
        }
    }
    
    contract Ownable {
        address public owner;
        address public manager;
        address public ownerWallet;
        address public adminWallet;
        uint adminPersent;
    
        constructor() public {
            owner = msg.sender;
            manager = msg.sender;
            adminWallet = 0xcFebf7C3Ec7B407DFf17aa20a2631c95c8ff508c;
            ownerWallet = 0xcFebf7C3Ec7B407DFf17aa20a2631c95c8ff508c;
            adminPersent = 10;
        }
    
        modifier onlyOwner() {
            require(msg.sender == owner, "only for owner");
            _;
        }
    
        modifier onlyOwnerOrManager() {
            require((msg.sender == owner)||(msg.sender == manager), "only for owner or manager");
            _;
        }
    
        function transferOwnership(address newOwner) public onlyOwner {
            owner = newOwner;
        }
    
        function setManager(address _manager) public onlyOwnerOrManager {
            manager = _manager;
        }
    
        function setAdminWallet(address _admin) public onlyOwner {
            adminWallet = _admin;
        }
    }
    
    
    contract WalletOnly {
        function isContract(address account) internal view returns (bool) {
            // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
            // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
            // for accounts without code, i.e. `keccak256('')`
            bytes32 codehash;
            bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
            // solhint-disable-next-line no-inline-assembly
            assembly { codehash := extcodehash(account) }
            return (codehash != accountHash && codehash != 0x0);
        }
    }
    
    contract AbsDAO is Ownable, WalletOnly {
        // events
        event TransferPie(address indexed _from, address indexed _to, uint _value);
        event NewHolder(address indexed _addr, uint _index);
        event HolderChanged(address indexed _from, address indexed _to, uint _index);
        event PaymentReceived(address indexed _from, uint _value);
        event PaymentForHolder(address indexed _addr, uint _index, uint _value);
        event PaymentForHolderLost(address indexed _addr, uint _index, uint _value);
    
        struct Holder {
            bool isExist;
            uint id;
            uint value;
            address payable addr;
        }
    
        mapping(address => Holder) public holders;
        mapping(uint=>address payable) holderAddrs;
    
        uint holderCount;
        uint _initialPie = 100;
    
        using SafeMath for uint;
    
        constructor() public {
            // creating root hoder
            holderCount = 1;
            holders[msg.sender] = Holder({
                isExist: true,
                id: 1,
                value: _initialPie,
                addr: msg.sender
            });
    
            holderAddrs[1] = msg.sender;
        }
    
        function () external payable {
            require(!isContract(msg.sender), 'This contract cannot support payments from other contracts');
    
            emit PaymentReceived(msg.sender, msg.value);
    
            for (uint i = 1; i <= holderCount; i++) {
                if (holders[holderAddrs[i]].value > 0) {
                    uint payValue = msg.value.div(100).mul(holders[holderAddrs[i]].value);
                    holderAddrs[i].transfer(payValue);
                    emit PaymentForHolder(holderAddrs[i], i, payValue);
                } else {
                    emit PaymentForHolderLost(holderAddrs[i], i, holders[holderAddrs[i]].value);
                }
            }
        }
    
        function getHolderPieAt(uint i) public view returns(uint) {
            return holders[holderAddrs[i]].value;
        }
    
        function getHolder(uint i) public view returns(address payable) {
            return holderAddrs[i];
        }
    
        function getHolderCount() public view returns(uint) {
            return holderCount;
        }
    
        function transferPie(uint _amount, address payable _to) public {
            require(holders[msg.sender].isExist, 'Holder not found');
            require(_amount > 0 && _amount <= holders[msg.sender].value, 'Invalid amount');
    
            if (_amount == holders[msg.sender].value) {
                uint id = holders[msg.sender].id;
                delete holders[msg.sender];
    
                holders[_to] = Holder({
                    isExist: true,
                    id: id,
                    value: _amount,
                    addr: _to
                });
    
                holderAddrs[id] = _to;
    
                emit HolderChanged(msg.sender, _to, id);
            } else {
                if (holders[_to].isExist) {
                    holders[msg.sender].value -= _amount;
                    holders[_to].value += _amount;
                } else if (holderCount < 20) {
                    holderCount += 1;
                    holders[msg.sender].value -= _amount;
                    holders[_to] = Holder({
                        isExist: true,
                        id: holderCount,
                        value: _amount,
                        addr: _to
                    });
    
                    holderAddrs[holderCount] = _to;
    
                    emit NewHolder(_to, holderCount);
                } else {
                    revert('Holder limit excised');
                }
            }
    
            emit TransferPie(msg.sender, _to, _amount);
        }
    }