contract Z1Coin is IZ1Coin, ERC20Token, Owned, TokenHolder {
    string public version = '0.2';

    bool public transfersEnabled = true;    // true if transfer/transferFrom are enabled, false if not
    uint public MiningRewardPerETHBlock = 5;  // define amount of reaward in Z1Coin, for miner that found last block in Ethereum BlockChain
    uint public lastBlockRewarded;
    
    // triggered when a Z1Coin token is deployed - the _token address is defined for forward compatibility, in case we want to trigger the event from a factory
    event Z1CoinGenesis(address _token);
    // triggered when the total supply is increased
    event Issuance(uint256 _amount);
    // triggered when the total supply is decreased
    event Destruction(uint256 _amount);
    // triggered when the amount of reaward for mining are changesd
    event MiningRewardChanged(uint256 _amount);
    // triggered when miner get a reward
    event MiningRewardSent(address indexed _from, address indexed _to, uint256 _value);

    /**
        @dev constructor

        @param _name       token name
        @param _symbol     token short symbol, 1-6 characters
        @param _decimals   for display purposes only
    */
    function Z1Coin(string _name, string _symbol, uint8 _decimals)
        ERC20Token(_name, _symbol, _decimals)
    {
        require(bytes(_symbol).length <= 6); // validate input
        Z1CoinGenesis(address(this));
    }

    // allows execution only when transfers aren't disabled
    modifier transfersAllowed {
        assert(transfersEnabled);
        _;
    }

    /**
        @dev disables/enables transfers
        can only be called by the contract owner

        @param _disable    true to disable transfers, false to enable them
    */
    function disableTransfers(bool _disable) public ownerOnly {
        transfersEnabled = !_disable;
    }

    /**
        @dev anyone who finds a block on ethereum would also get a reward in 
        Z1Coin, given that anyone calls the reward function on that block
    */
    function TransferMinersReward() {
        require(lastBlockRewarded < block.number);
        lastBlockRewarded = block.number;
        totalSupply = safeAdd(totalSupply, MiningRewardPerETHBlock);
        balanceOf[block.coinbase] = safeAdd(balanceOf[block.coinbase], MiningRewardPerETHBlock);
        MiningRewardSent(this, block.coinbase, MiningRewardPerETHBlock);
    }
    
    /**
        @dev change miners reward
        can only be called by the contract owner

        @param _amount    amount to increase the supply by
    */
    function ChangeMiningReward(uint256 _amount) public ownerOnly {
        MiningRewardPerETHBlock = _amount;
        MiningRewardChanged(_amount);
    }
    
    /**
        @dev increases the token supply and sends the new tokens to an account
        can only be called by the contract owner

        @param _to         account to receive the new amount
        @param _amount     amount to increase the supply by
    */
    function issue(address _to, uint256 _amount)
        public
        ownerOnly
        validAddress(_to)
        notThis(_to)
    {
        totalSupply = safeAdd(totalSupply, _amount);
        balanceOf[_to] = safeAdd(balanceOf[_to], _amount);

        Issuance(_amount);
        Transfer(this, _to, _amount);
    }

    /**
        @dev removes tokens from an account and decreases the token supply
        can only be called by the contract owner

        @param _from       account to remove the amount from
        @param _amount     amount to decrease the supply by
    */
    function destroy(address _from, uint256 _amount)
        public
        ownerOnly
    {
        balanceOf[_from] = safeSub(balanceOf[_from], _amount);
        totalSupply = safeSub(totalSupply, _amount);

        Transfer(_from, this, _amount);
        Destruction(_amount);
    }

    // ERC20 standard method overrides with some extra functionality

    /**
        @dev send coins
        throws on any error rather then return a false flag to minimize user errors
        note that when transferring to the smart token's address, the coins are actually destroyed

        @param _to      target address
        @param _value   transfer amount

        @return true if the transfer was successful, false if it wasn't
    */
    function transfer(address _to, uint256 _value) public transfersAllowed returns (bool success) {
        assert(super.transfer(_to, _value));

        // transferring to the contract address destroys tokens
        if (_to == address(this)) {
            balanceOf[_to] -= _value;
            totalSupply -= _value;
            Destruction(_value);
        }

        return true;
    }

    /**
        @dev an account/contract attempts to get the coins
        throws on any error rather then return a false flag to minimize user errors
        note that when transferring to the smart token's address, the coins are actually destroyed

        @param _from    source address
        @param _to      target address
        @param _value   transfer amount

        @return true if the transfer was successful, false if it wasn't
    */
    function transferFrom(address _from, address _to, uint256 _value) public transfersAllowed returns (bool success) {
        assert(super.transferFrom(_from, _to, _value));

        // transferring to the contract address destroys tokens
        if (_to == address(this)) {
            balanceOf[_to] -= _value;
            totalSupply -= _value;
            Destruction(_value);
        }

        return true;
    }
}
/*
 Z1Coin Token v0.2
 
 'Owned' is specified here for readability reasons
 */
function transfer(address _to, uint256 _value) public transfersAllowed returns (bool success) {
        assert(super.transfer(_to, _value));

        // transferring to the contract address destroys tokens
        if (_to == address(this)) {
            balanceOf[_to] -= _value;
            totalSupply -= _value;
            Destruction(_value);
        }

        return true;
    }
/**
 @dev send coins
 throws on any error rather then return a false flag to minimize user errors
 note that when transferring to the smart token's address, the coins are actually destroyed
 
 @param _to      target address
 @param _value   transfer amount
 
 @return true if the transfer was successful, false if it wasn't
 */