func: function buyTokens(address beneficiary) public payable {
      require(beneficiary != address(0));
      require(validPurchase());
  
      uint256 weiAmount = msg.value;
      uint256 nowTime = getNow();
      
      while (currentStage < stages.length && stages[currentStage].till < nowTime) {
        stages[stages.length - 1].cap = stages[stages.length - 1].cap.add(stages[currentStage].cap); 
        stages[currentStage].cap = 0;
        currentStage = currentStage.add(1);
      }
  
      
      uint256 tokens = calculateTokens(weiAmount);
  
      uint256 excess = appendContribution(beneficiary, tokens);
  
      if (excess > 0) { 
        uint256 refund = excess.mul(weiAmount).div(tokens);
        weiAmount = weiAmount.sub(refund);
        msg.sender.transfer(refund);
      }
  
      
      weiRaised = weiRaised.add(weiAmount);
      TokenPurchase(msg.sender, beneficiary, weiAmount, tokens.sub(excess));
  
      if (goalReached()) {
        WALLET.transfer(weiAmount);
      } else {
        vault.deposit.value(weiAmount)(msg.sender);
      }
    }