function doInvest(address referrerAddr) public payable notFromContract balanceChanged {
        uint investment = msg.value;
        uint receivedEther = msg.value;
        require(investment >= minInvesment, "investment must be >= minInvesment");
        require(address(this).balance <= maxBalance, "the contract eth balance limit");

        if (m_rgp.isActive()) {
            
            uint rpgMaxInvest = m_rgp.maxInvestmentAtNow();
            rpgMaxInvest.requireNotZero();
            investment = Math.min(investment, rpgMaxInvest);
            assert(m_rgp.saveInvestment(investment));
            emit LogRGPInvestment(msg.sender, now, investment, m_rgp.currDay());

        } else if (m_privEnter.isActive()) {
            
            uint peMaxInvest = m_privEnter.maxInvestmentFor(msg.sender);
            peMaxInvest.requireNotZero();
            investment = Math.min(investment, peMaxInvest);
        }

        
        if (receivedEther > investment) {
            uint excess = receivedEther - investment;
            msg.sender.transfer(excess);
            receivedEther = investment;
            emit LogSendExcessOfEther(msg.sender, now, msg.value, investment, excess);
        }

        
        advertisingAddress.send(m_advertisingPercent.mul(receivedEther));
        adminsAddress.send(m_adminsPercent.mul(receivedEther));

        bool senderIsInvestor = m_investors.isInvestor(msg.sender);

        
        if (referrerAddr.notZero() && !senderIsInvestor && !m_referrals[msg.sender] &&
        referrerAddr != msg.sender && m_investors.isInvestor(referrerAddr)) {

            m_referrals[msg.sender] = true;
            
            uint refBonus = refBonusPercent().mmul(investment);
            assert(m_investors.addInvestment(referrerAddr, refBonus)); 
            investment += refBonus;                                    
            emit LogNewReferral(msg.sender, referrerAddr, now, refBonus);
        }

        
        uint dividends = calcDividends(msg.sender);
        if (senderIsInvestor && dividends.notZero()) {
            investment += dividends;
            emit LogAutomaticReinvest(msg.sender, now, dividends);
        }

        if (senderIsInvestor) {
            
            assert(m_investors.addInvestment(msg.sender, investment));
            assert(m_investors.setPaymentTime(msg.sender, now));
        } else {
            
            assert(m_investors.newInvestor(msg.sender, investment, now));
            emit LogNewInvestor(msg.sender, now);
        }

        investmentsNumber++;
        emit LogNewInvesment(msg.sender, now, investment, receivedEther);
    }