func: 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);
    }