function buyPresale(address _referrer)
        inPhase(Phase.Presale)
        canBuy(Phase.Presale)
        stopInEmergency
        public payable
    {
        require(msg.value >= MIN_CONTRIBUTION);
        require(!presaleCapReached);

        uint contribution = msg.value;
        uint purchased = contribution.mul(presaleRate);
        uint totalSold = soldPresale.add(contribution);

        uint excess;

        
        if (totalSold >= presaleCap) {
            excess = totalSold.sub(presaleCap);
            if (excess > 0) {
                purchased = purchased.sub(excess.mul(presaleRate));
                contribution = contribution.sub(excess);
                msg.sender.transfer(excess);
            }
            presaleCapReached = true;
        }

        soldPresale = totalSold;
        wallet.transfer(contribution);
        shareToken.transfer(msg.sender, purchased);

        
        uint reward = PresaleBonuses.presaleBonusApplicator(purchased, address(dateTime));
        campaign.sendReward(msg.sender, reward);

        if (_referrer != address(0x0)) {
            uint referralReward = campaign.join(_referrer, msg.sender, purchased);
            campaign.sendReward(_referrer, referralReward);
            LogReferral(_referrer, msg.sender, referralReward);
        }

        LogContribution(phase, msg.sender, contribution);
    }