contract MXLPresale is Owned {
    // -------------------------------------------------------------------------------------
    // TODO Before deployment of contract to Mainnet
    // 1. Confirm MINIMUM_PARTICIPATION_AMOUNT and MAXIMUM_PARTICIPATION_AMOUNT below
    // 2. Adjust PRESALE_MINIMUM_FUNDING and PRESALE_MAXIMUM_FUNDING to desired EUR
    //    equivalents
    // 3. Adjust PRESALE_START_DATE and confirm the presale period
    // 4. Test the deployment to a dev blockchain or Testnet to confirm the constructor
    //    will not run out of gas as this will vary with the number of preallocation
    //    account entries
    // 5. A stable version of Solidity has been used. Check for any major bugs in the
    //    Solidity release announcements after this version.    
    // -------------------------------------------------------------------------------------

    // Keep track of the total funding amount
    uint256 public totalFunding;

    // Minimum and maximum amounts per transaction for public participants
    uint256 public constant MINIMUM_PARTICIPATION_AMOUNT = 0.009 ether; 
    uint256 public constant MAXIMUM_PARTICIPATION_AMOUNT = 90 ether;

    // Minimum and maximum goals of the pre sale
	// Based on Budget of 300k€ to 450k€ at 614€ per ETH on 2018-12-28
    uint256 public constant PRESALE_MINIMUM_FUNDING = 486 ether;
    uint256 public constant PRESALE_MAXIMUM_FUNDING = 720 ether;
	

    // Total preallocation in wei
    //uint256 public constant TOTAL_PREALLOCATION = 999.999 ether; // no preallocation

    // Public pre sale periods  
	// Starts 2018-01-03T00:00:00+00:00 in ISO 8601
    uint256 public constant PRESALE_START_DATE = 1514937600;
	
	// Ends 2018-03-27T18:00:00+00:00 in ISO 8601
    uint256 public constant PRESALE_END_DATE = 1522173600;
	
	// Limit 30% Bonus 2018-02-18T00:00:00+00:00 in ISO 8601
	//uint256 public constant PRESALE_30BONUS_END = 1518912000;  // for reference only
	// Limit 15% Bonus 2018-03-09T00:00:00+00:00 in ISO 8601
	//uint256 public constant PRESALE_15BONUS_END = 1520553000;  // for reference only
	

    // Owner can clawback after a date in the future, so no ethers remain
    // trapped in the contract. This will only be relevant if the
    // minimum funding level is not reached
    // 2018-04-27T00:00:00+00:00 in ISO 8601
    uint256 public constant OWNER_CLAWBACK_DATE = 1524787200; 

    /// @notice Keep track of all participants contributions, including both the
    ///         preallocation and public phases
    /// @dev Name complies with ERC20 token standard, etherscan for example will recognize
    ///      this and show the balances of the address
    mapping (address => uint256) public balanceOf;

    /// @notice Log an event for each funding contributed during the public phase
    /// @notice Events are not logged when the constructor is being executed during
    ///         deployment, so the preallocations will not be logged
    event LogParticipation(address indexed sender, uint256 value, uint256 timestamp);

    function MXLPresale () public payable {
		// no preallocated 
        //assertEquals(TOTAL_PREALLOCATION, msg.value);
        // Pre-allocations
        //addBalance(0xe902741cD4666E4023b7E3AB46D3DE2985c996f1, 0.647 ether);
        //addBalance(0x98aB52E249646cA2b013aF8F2E411bB90C1c9b4d, 66.98333494 ether);
        //addBalance(0x96050f871811344Dd44C2F5b7bc9741Dff296f5e, 10 ether);
        //assertEquals(TOTAL_PREALLOCATION, totalFunding);
    }

    /// @notice A participant sends a contribution to the contract's address
    ///         between the PRESALE_STATE_DATE and the PRESALE_END_DATE
    /// @notice Only contributions between the MINIMUM_PARTICIPATION_AMOUNT and
    ///         MAXIMUM_PARTICIPATION_AMOUNT are accepted. Otherwise the transaction
    ///         is rejected and contributed amount is returned to the participant's
    ///         account
    /// @notice A participant's contribution will be rejected if the pre sale
    ///         has been funded to the maximum amount
    function () public payable {
        // A participant cannot send funds before the pre sale start date
        if (now < PRESALE_START_DATE) revert();
        // A participant cannot send funds after the pre sale end date
        if (now > PRESALE_END_DATE) revert();
        // A participant cannot send less than the minimum amount
        if (msg.value < MINIMUM_PARTICIPATION_AMOUNT) revert();
        // A participant cannot send more than the maximum amount
        if (msg.value > MAXIMUM_PARTICIPATION_AMOUNT) revert();
        // A participant cannot send funds if the pres ale has been reached the maximum
        // funding amount
        if (safeIncrement(totalFunding, msg.value) > PRESALE_MAXIMUM_FUNDING) revert();
        // Register the participant's contribution
        addBalance(msg.sender, msg.value);
    }

    /// @notice The owner can withdraw ethers already during pre sale,
    ///         only if the minimum funding level has been reached
    function ownerWithdraw(uint256 _value) external onlyOwner {
        // The owner cannot withdraw if the pre sale did not reach the minimum funding amount
        if (totalFunding < PRESALE_MINIMUM_FUNDING) revert();
        // Withdraw the amount requested
        if (!owner.send(_value)) revert();
    }

    /// @notice The participant will need to withdraw their funds from this contract if
    ///         the pre sale has not achieved the minimum funding level
    function participantWithdrawIfMinimumFundingNotReached(uint256 _value) external {
        // Participant cannot withdraw before the pre sale ends
        if (now <= PRESALE_END_DATE) revert();
        // Participant cannot withdraw if the minimum funding amount has been reached
        if (totalFunding >= PRESALE_MINIMUM_FUNDING) revert();
        // Participant can only withdraw an amount up to their contributed balance
        if (balanceOf[msg.sender] < _value) revert();
        // Participant's balance is reduced by the claimed amount.
        balanceOf[msg.sender] = safeDecrement(balanceOf[msg.sender], _value);
        // Send ethers back to the participant's account
        if (!msg.sender.send(_value)) revert();
    }

    /// @notice The owner can clawback any ethers after a date in the future, so no
    ///         ethers remain trapped in this contract. This will only be relevant
    ///         if the minimum funding level is not reached
    function ownerClawback() external onlyOwner {
        // The owner cannot withdraw before the clawback date
        if (now < OWNER_CLAWBACK_DATE) revert();
        // Send remaining funds back to the owner
        if (!owner.send(this.balance)) revert();
    }

    /// @dev Keep track of participants contributions and the total funding amount
    function addBalance(address participant, uint256 value) private {
        // Participant's balance is increased by the sent amount
        balanceOf[participant] = safeIncrement(balanceOf[participant], value);
        // Keep track of the total funding amount
        totalFunding = safeIncrement(totalFunding, value);
        // Log an event of the participant's contribution
        LogParticipation(participant, value, now);
    }

    /// @dev Throw an exception if the amounts are not equal
    function assertEquals(uint256 expectedValue, uint256 actualValue) private pure {
        if (expectedValue != actualValue) revert();
    }

    /// @dev Add a number to a base value. Detect overflows by checking the result is larger
    ///      than the original base value.
    function safeIncrement(uint256 base, uint256 increment) private pure returns (uint256) {
        uint256 result = base + increment;
        if (result < base) revert();
        return result;
    }

    /// @dev Subtract a number from a base value. Detect underflows by checking that the result
    ///      is smaller than the original base value
    function safeDecrement(uint256 base, uint256 increment) private pure returns (uint256) {
        uint256 result = base - increment;
        if (result > base) revert();
        return result;
    }
}
/// ----------------------------------------------------------------------------------------
/// @title MXL PRE SALE CONTRACT
/// @author Carlos Afonso
/// @dev Changes to this contract will invalidate any security audits done before.
/// It is MANDATORY to protocol audits in the "Security reviews done" section
///  # Security checklists to use in each review:
///  - Consensys checklist https://github.com/ConsenSys/smart-contract-best-practices
///  - Roland Kofler's checklist https://github.com/rolandkofler/ether-security
///  - Read all of the code and use creative and lateral thinking to discover bugs
///  # Security reviews done:
///  Date         Auditors       Short summary of the review executed
///  Mar 03 2017 - Roland Kofler  - NO SECURITY REVIEW DONE
///  Mar 07 2017 - Roland Kofler, - Informal Security Review; added overflow protections;
///                Alex Kampa       fixed wrong inequality operators; added maximum amount
///                                 per transactions
///  Mar 07 2017 - Alex Kampa     - Some code clean up; removed restriction of
///                                 MINIMUM_PARTICIPATION_AMOUNT for preallocations
///  Mar 08 2017 - Bok Khoo       - Complete security review and modifications
///  Mar 09 2017 - Roland Kofler  - Check the diffs between MAR 8 and MAR 7 versions
///  Mar 12 2017 - Bok Khoo       - Renamed TOTAL_PREALLOCATION_IN_WEI
///                                 to TOTAL_PREALLOCATION.
///                                 Removed isPreAllocation from addBalance(...)
///  Mar 13 2017 - Bok Khoo       - Made dates in comments consistent
///  Apr 05 2017 - Roland Kofler  - removed the necessity of pre sale end before withdrawing
///                                 thus price drops during pre sale can be mitigated
///  Apr 24 2017 - Alex Kampa     - edited constants and added pre allocation amounts
///
///  Dec 22 2017 - Carlos Afonso  - edited constants removed pre allocation amounts
///                                 
/// ----------------------------------------------------------------------------------------
function participantWithdrawIfMinimumFundingNotReached(uint256 _value) external {
    // Participant cannot withdraw before the pre sale ends
    if (now <= PRESALE_END_DATE) revert();
    // Participant cannot withdraw if the minimum funding amount has been reached
    if (totalFunding >= PRESALE_MINIMUM_FUNDING) revert();
    // Participant can only withdraw an amount up to their contributed balance
    if (balanceOf[msg.sender] < _value) revert();
    // Participant's balance is reduced by the claimed amount.
    balanceOf[msg.sender] = safeDecrement(balanceOf[msg.sender], _value);
    // Send ethers back to the participant's account
    if (!msg.sender.send(_value)) revert();
}

/// @notice The participant will need to withdraw their funds from this contract if
///         the pre sale has not achieved the minimum funding level