pragma solidity ^0.4.17;

        library SafeMath {
        
            /**
            * @dev Multiplies two numbers, throws on overflow.
            */
            function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                if (a == 0) {
                    return 0;
                }
                uint256 c = a * b;
                assert(c / a == b);
                return c;
            }
        
            /**
            * @dev Integer division of two numbers, truncating the quotient.
            */
            function div(uint256 a, uint256 b) internal pure returns (uint256) {
                // assert(b > 0); // Solidity automatically throws when dividing by 0
                uint256 c = a / b;
                // assert(a == b * c + a % b); // There is no case in which this doesn't hold
                return c;
            }
        
            /**
            * @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
            */
            function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                assert(b <= a);
                return a - b;
            }
        
            /**
            * @dev Adds two numbers, throws on overflow.
            */
            function add(uint256 a, uint256 b) internal pure returns (uint256) {
                uint256 c = a + b;
                assert(c >= a);
                return c;
            }
        }
        
        contract Ownable {
            address public owner;
        
            event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
        
        
            /**
             * @dev The Ownable constructor sets the original `owner` of the contract to the sender
             * account.
             */
            function Ownable() public {
                owner = msg.sender;
            }
        
            /**
             * @dev Throws if called by any account other than the owner.
             */
            modifier onlyOwner() {
                require(msg.sender == owner);
                _;
            }
        
            /**
             * @dev Allows the current owner to transfer control of the contract to a newOwner.
             * @param newOwner The address to transfer ownership to.
             */
            function transferOwnership(address newOwner) public onlyOwner {
                require(newOwner != address(0));
                OwnershipTransferred(owner, newOwner);
                owner = newOwner;
            }
        
        }
        
        contract ERC20Basic {
            function totalSupply() public view returns (uint256);
            function balanceOf(address who) public view returns (uint256);
            function transfer(address to, uint256 value) public returns (bool);
            event Transfer(address indexed from, address indexed to, uint256 value);
        }
        
        contract BasicToken is ERC20Basic {
            using SafeMath for uint256;
        
            mapping(address => uint256) balances;
        
            uint256 totalSupply_;
        
            /**
            * @dev total number of tokens in existence
            */
            function totalSupply() public view returns (uint256) {
                return totalSupply_;
            }
        
            /**
            * @dev transfer token for a specified address
            * @param _to The address to transfer to.
            * @param _value The amount to be transferred.
            */
            function transfer(address _to, uint256 _value) public returns (bool) {
                require(_to != address(0));
                require(_value <= balances[msg.sender]);
        
                // SafeMath.sub will throw if there is not enough balance.
                balances[msg.sender] = balances[msg.sender].sub(_value);
                balances[_to] = balances[_to].add(_value);
                Transfer(msg.sender, _to, _value);
                return true;
            }
        
            /**
            * @dev Gets the balance of the specified address.
            * @param _owner The address to query the the balance of.
            * @return An uint256 representing the amount owned by the passed address.
            */
            function balanceOf(address _owner) public view returns (uint256 balance) {
                return balances[_owner];
            }
        
        }
        
        contract BurnableToken is BasicToken {
        
            event Burn(address indexed burner, uint256 value);
        
            /**
             * @dev Burns a specific amount of tokens.
             * @param _value The amount of token to be burned.
             */
            function burn(uint256 _value) public {
                require(_value <= balances[msg.sender]);
                // no need to require value <= totalSupply, since that would imply the
                // sender's balance is greater than the totalSupply, which *should* be an assertion failure
        
                address burner = msg.sender;
                balances[burner] = balances[burner].sub(_value);
                totalSupply_ = totalSupply_.sub(_value);
                Burn(burner, _value);
            }
        }
        
        contract ERC20 is ERC20Basic {
            function allowance(address owner, address spender) public view returns (uint256);
            function transferFrom(address from, address to, uint256 value) public returns (bool);
            function approve(address spender, uint256 value) public returns (bool);
            event Approval(address indexed owner, address indexed spender, uint256 value);
        }
        
        library SafeERC20 {
            function safeTransfer(ERC20Basic token, address to, uint256 value) internal {
                assert(token.transfer(to, value));
            }
        
            function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
                assert(token.transferFrom(from, to, value));
            }
        
            function safeApprove(ERC20 token, address spender, uint256 value) internal {
                assert(token.approve(spender, value));
            }
        }
        
        contract StandardToken is ERC20, BasicToken {
        
            mapping (address => mapping (address => uint256)) internal allowed;
        
        
            /**
             * @dev Transfer tokens from one address to another
             * @param _from address The address which you want to send tokens from
             * @param _to address The address which you want to transfer to
             * @param _value uint256 the amount of tokens to be transferred
             */
            function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
                require(_to != address(0));
                require(_value <= balances[_from]);
                require(_value <= allowed[_from][msg.sender]);
        
                balances[_from] = balances[_from].sub(_value);
                balances[_to] = balances[_to].add(_value);
                allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
                Transfer(_from, _to, _value);
                return true;
            }
        
            /**
             * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
             *
             * Beware that changing an allowance with this method brings the risk that someone may use both the old
             * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
             * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
             * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
             * @param _spender The address which will spend the funds.
             * @param _value The amount of tokens to be spent.
             */
            function approve(address _spender, uint256 _value) public returns (bool) {
                allowed[msg.sender][_spender] = _value;
                Approval(msg.sender, _spender, _value);
                return true;
            }
        
            /**
             * @dev Function to check the amount of tokens that an owner allowed to a spender.
             * @param _owner address The address which owns the funds.
             * @param _spender address The address which will spend the funds.
             * @return A uint256 specifying the amount of tokens still available for the spender.
             */
            function allowance(address _owner, address _spender) public view returns (uint256) {
                return allowed[_owner][_spender];
            }
        
            /**
             * @dev Increase the amount of tokens that an owner allowed to a spender.
             *
             * approve should be called when allowed[_spender] == 0. To increment
             * allowed value is better to use this function to avoid 2 calls (and wait until
             * the first transaction is mined)
             * From MonolithDAO Token.sol
             * @param _spender The address which will spend the funds.
             * @param _addedValue The amount of tokens to increase the allowance by.
             */
            function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
                allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
                Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
                return true;
            }
        
            /**
             * @dev Decrease the amount of tokens that an owner allowed to a spender.
             *
             * approve should be called when allowed[_spender] == 0. To decrement
             * allowed value is better to use this function to avoid 2 calls (and wait until
             * the first transaction is mined)
             * From MonolithDAO Token.sol
             * @param _spender The address which will spend the funds.
             * @param _subtractedValue The amount of tokens to decrease the allowance by.
             */
            function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
                uint oldValue = allowed[msg.sender][_spender];
                if (_subtractedValue > oldValue) {
                    allowed[msg.sender][_spender] = 0;
                } else {
                    allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
                }
                Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
                return true;
            }
        
        }
        
        contract PixelToken is StandardToken, BurnableToken, Ownable {
            using SafeMath for uint;
        
            string constant public symbol = "PXLT";
            string constant public name = "Pixel Crowdsale Token";
        
            uint8 constant public decimals = 18;
            uint256 INITIAL_SUPPLY = 20000000e18;
        
            uint constant ITSStartTime = 1523350800; //  Tuesday, April 10, 2018 5:00:00 PM
            uint constant unlockTime = 1546300800; //  Tuesday, January 1, 2019 12:00:00 AM
        
            address company = 0x5028aea7b621782ca58fe066b5b16b4fe2ead8d6;
            address team = 0x628f126d16acf0ba234f5ece4aa5bc2baba7ffda;
        
            address crowdsale = 0x7085a139792aec99514352a3cfa657cdd4aeabbc;
            address bounty = 0x214c50f0133943f06060ee693353d91ef2c693c7;
        
            address beneficiary = 0x143f85a5e90ed6a1409536a723589203b59bbe7e;
        
            uint constant companyTokens = 2400000e18;
            uint constant teamTokens = 1800000e18;
            uint constant crowdsaleTokens = 15000000e18;
            uint constant bountyTokens = 800000e18;
        
            function PixelToken() public {
        
                totalSupply_ = INITIAL_SUPPLY;
        
                // InitialDistribution
                preSale(company, companyTokens);
                preSale(team, teamTokens);
                preSale(crowdsale, crowdsaleTokens);
                preSale(bounty, bountyTokens);
            }
        
            function preSale(address _address, uint _amount) internal returns (bool) {
                balances[_address] = _amount;
                Transfer(address(0x0), _address, _amount);
            }
        
            function checkPermissions(address _from) internal constant returns (bool) {
        
                if (_from == team && now < unlockTime) {
                    return false;
                }
        
                if (_from == bounty || _from == crowdsale || _from == company) {
                    return true;
                }
        
                return true;
            }
        
            function transfer(address _to, uint256 _value) public returns (bool) {
        
                require(checkPermissions(msg.sender));
                super.transfer(_to, _value);
            }
        
            function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        
                require(checkPermissions(_from));
                super.transferFrom(_from, _to, _value);
            }
        
            function () public payable {
                require(msg.value >= 1e16);
                beneficiary.transfer(msg.value);
            }
        
        }