contract Hut34ICOAbstract
{
    /// @dev Logged upon receiving a deposit
    /// @param _from The address from which value has been recieved
    /// @param _value The value of ether received
    event Deposit(address indexed _from, uint _value);

    /// @dev Logged upon a withdrawal
    /// @param _from the address of the withdrawer
    /// @param _to Address to which value was sent
    /// @param _value The value in ether which was withdrawn
    event Withdrawal(address indexed _from, address indexed _to, uint _value);

    /// @dev Logged when new owner accepts ownership
    /// @param _from the old owner address
    /// @param _to the new owner address
    event ChangedOwner(address indexed _from, address indexed _to);

    /// @dev Logged when owner initiates a change of ownership
    /// @param _to the new owner address
    event ChangeOwnerTo(address indexed _to);

    /// @dev Logged when a funder exceeds the KYC limit
    /// @param _addr Address to set or clear KYC flag
    /// @param _kyc A boolean flag
    event Kyc(address indexed _addr, bool _kyc);

    /// @dev Logged when vested tokens are released back to HUT32_WALLET
    /// @param _releaseDate The official release date (even if released at
    /// later date)
    event VestingReleased(uint _releaseDate);

    /// @dev Logged if the contract is aborted
    event Aborted();

//
// Constants
//

    /// @dev The Hut34 vesting 'psudo-address' for transferring and releasing
    /// vested tokens to the Hut34 Wallet. The address is UTF8 encoding of the
    /// string and can only be accessed by the 'releaseVested()' function.
    /// @return `0x48757433342056657374696e6700000000000000`
    address public constant HUT34_VEST_ADDR = address(bytes20("Hut34 Vesting"));

//
// State Variables
//

    /// @dev This fuse blows upon calling abort() which forces a fail state
    /// @return the abort state. true == not aborted
    bool public __abortFuse = true;

    /// @dev Sets to true after the fund is swept to the fund wallet, allows
    /// token transfers and prevents abort()
    /// @return final success state of ICO
    bool public icoSucceeded;

    /// @dev An address permissioned to enact owner restricted functions
    /// @return owner
    address public owner;

    /// @dev An address permissioned to take ownership of the contract
    /// @return new owner address
    address public newOwner;

    /// @dev A tally of total ether raised during the funding period
    /// @return Total ether raised during funding
    uint public etherRaised;

    /// @return Wholesale tokens available for sale
    uint public wholesaleLeft;

    /// @return Total ether refunded. Used to permision call to `destroy()`
    uint public refunded;

    /// @returns Date of next vesting release
    uint public nextReleaseDate;

    /// @return Ether paid by an address
    mapping (address => uint) public etherContributed;

    /// @returns KYC flag for an address
    mapping (address => bool) public mustKyc;

//
// Modifiers
//

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

//
// Function Abstracts
//

    /// @return `true` if MIN_FUNDS were raised
    function fundRaised() public view returns (bool);

    /// @return `true` if MIN_FUNDS were not raised before END_DATE or contract
    /// has been aborted
    function fundFailed() public view returns (bool);

    /// @return The current retail rate for token purchase
    function currentRate() public view returns (uint);

    /// @param _wei A value of ether in units of wei
    /// @return allTokens_ returnable tokens for the funding amount
    /// @return wholesaleToken_ Number of tokens purchased at wholesale rate
    function ethToTokens(uint _wei)
        public view returns (uint allTokens_, uint wholesaleTokens_);

    /// @notice Processes a token purchase for `_addr`
    /// @param _addr An address to purchase tokens
    /// @return Boolean success value
    /// @dev Requires <150,000 gas
    function proxyPurchase(address _addr) public payable returns (bool);

    /// @notice Finalize the ICO and transfer funds
    /// @return Boolean success value
    function finalizeICO() public returns (bool);

    /// @notice Clear the KYC flags for an array of addresses to allow tokens
    /// transfers
    function clearKyc(address[] _addrs) public returns (bool);

    /// @notice Make bulk transfer of tokens to many addresses
    /// @param _addrs An array of recipient addresses
    /// @param _amounts An array of amounts to transfer to respective addresses
    /// @return Boolean success value
    function transferToMany(address[] _addrs, uint[] _amounts)
        public returns (bool);

    /// @notice Release vested tokens after a maturity date
    /// @return Boolean success value
    function releaseVested() public returns (bool);

    /// @notice Claim refund on failed ICO
    /// @return Boolean success value
    function refund() public returns (bool);

    /// @notice Push refund for `_addr` from failed ICO
    /// @param _addrs An array of address to refund
    /// @return Boolean success value
    function refundFor(address[] _addrs) public returns (bool);

    /// @notice Abort the token sale prior to finalizeICO()
    function abort() public returns (bool);

    /// @notice Salvage `_amount` tokens at `_kaddr` and send them to `_to`
    /// @param _kAddr An ERC20 contract address
    /// @param _to and address to send tokens
    /// @param _amount The number of tokens to transfer
    /// @return Boolean success value
    function transferExternalToken(address _kAddr, address _to, uint _amount)
        public returns (bool);
}
/*-----------------------------------------------------------------------------\
 
 ## Conditional Entry Table
 
 Functions must throw on F conditions
 
 Renetry prevention is on all public mutating functions
 Reentry mutex set in finalizeICO(), externalXfer(), refund()
 
 |function                |<startDate |<endDate  |fundFailed  |fundRaised|icoSucceeded
 |------------------------|:---------:|:--------:|:----------:|:--------:|:---------:|
 |()                      |F          |T         |F           |T         |F          |
 |abort()                 |T          |T         |T           |T         |F          |
 |proxyPurchase()         |F          |T         |F           |T         |F          |
 |finalizeICO()           |F          |F         |F           |T         |T          |
 |refund()                |F          |F         |T           |F         |F          |
 |refundFor()             |F          |F         |T           |F         |F          |
 |transfer()              |F          |F         |F           |F         |T          |
 |transferFrom()          |F          |F         |F           |F         |T          |
 |transferToMany()        |F          |F         |F           |F         |T          |
 |approve()               |F          |F         |F           |F         |T          |
 |clearKyc()              |T          |T         |T           |T         |T          |
 |releaseVested()         |F          |F         |F           |F         |now>release|
 |changeOwner()           |T          |T         |T           |T         |T          |
 |acceptOwnership()       |T          |T         |T           |T         |T          |
 |transferExternalTokens()|T          |T         |T           |T         |T          |
 |destroy()               |F          |F         |!__abortFuse|F         |F          |
 
 \*----------------------------------------------------------------------------*/
function finalizeICO() public returns (bool);

/// @notice Finalize the ICO and transfer funds
/// @return Boolean success value