function Buy(
        uint32 maturityTimeInDays,
        bool hasExtraRedeemRange,
        bool canBeRedeemedPrematurely,
        address agent 
        ) 
        public payable
    {
        
        require(msg.value >= MinNominalBondPrice);
        
        
        require(
            maturityTimeInDays >= MinMaturityTimeInDays && 
            maturityTimeInDays <= MaxMaturityTimeInDays
            );
            
        
        bool hasRefBonus = false;
            
        
        if (Users[msg.sender].agent == 0 && Users[msg.sender].totalBonds == 0)
        {
            
            if (agent != 0)
            {
                
                if (Users[agent].totalBonds > 0)
                {
                    Users[msg.sender].agent = agent;
                    hasRefBonus = true;
                }
                else
                {
                    agent = 0;
                }
            }
        }
        
        else
        {
            agent = Users[msg.sender].agent;
        }
            
        
        Bond memory newBond;
        newBond.id = NextBondID;
        newBond.owner = msg.sender;
        newBond.issueTime = uint32(block.timestamp);
        newBond.canBeRedeemedPrematurely = canBeRedeemedPrematurely;
        
        
        newBond.maturityTime = 
            newBond.issueTime + maturityTimeInDays*24*60*60;
        
            
        newBond.maxRedeemTime = 
            newBond.maturityTime + (hasExtraRedeemRange?ExtraRedeemRangeInDays:RedeemRangeInDays)*24*60*60;
        
        newBond.nominalPrice = msg.value;
        
        newBond.maturityPrice = MaturityPrice(
            newBond.nominalPrice,
            maturityTimeInDays,
            hasExtraRedeemRange,
            canBeRedeemedPrematurely,
            hasRefBonus
            );
        
        Bonds[newBond.id] = newBond;
        NextBondID += 1;
        
        
        var user = Users[newBond.owner];
        user.bonds[user.totalBonds] = newBond.id;
        user.totalBonds += 1;
        
        
        Issued(newBond.id, newBond.owner);
        
        
        uint moneyToFounder = div(
            mul(newBond.nominalPrice, FounderFeeInPercent), 
            100
            );
        
        uint moneyToAgent = div(
            mul(newBond.nominalPrice, AgentBonusInPercent), 
            100
            );
        
        if (agent != 0 && moneyToAgent > 0)
        {
            
            Balances[agent] = add(Balances[agent], moneyToAgent);
        }
        
        
        require(moneyToFounder > 0);
        
        Founder.transfer(moneyToFounder);
    }