Contract 0x75D745EAeA0Ab0A8C9542959311C1C3166F6567D

 

Contract Overview

Balance:
180.2565025 Ether

EtherValue:
$22,398.67 (@ $124.26/ETH)
TxHash Block Age From To Value [TxFee]
0x3891fc57d4e69de8b3ef434f66c2893a1215864d3538c669a73d7606f0d92c7072303663 hrs 6 mins ago0x555c6cdd6f1a4b6c3db8018b8e9c4ca9ed2018ae  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.00101596
0x18a75690a39ff23b28212e7e9def1952bd420f3cf7cc1e3d55edbc3995e72b5972303633 hrs 6 mins ago0x13fb97da9d2407da6dbc2d6c175b51d0f5d9d903  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0.017 Ether0.000479608
0xf596c036592ca86437f56cb195423fb3f294c86b6bac33c577c86b28a7f4ad8d72301874 hrs 6 mins ago0x03014be565459aa0829f2641935949d7be8b1ed9  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.0083663745
0x322c9b47b1951ba2c2edf042bda4a562696b2d8d555944b74fe89cc4809dfca072301874 hrs 6 mins ago0x1e849ad655f7f364c4022bd8129f51083570d95f  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.0083668035
0x33ced3346a8a78ad6b8b50940ea20759eb4b791a8e001e5e9c33ad4ae73373c672301844 hrs 6 mins ago0x9e315e9701908501f6dc68a2af6e28a20c75d970  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0.33 Ether0.000619536
0x45179767d1ed1ed22ee505a8cabd0420479bb608f687cc22cc6e665e3a34e43172292639 hrs 24 mins ago0x55f74949a15ce98c9e9d8ebbdd774d5d7a25b473  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.0083669465
0x56a6a605767e5462dd285e970e0451534ec94fcc282659861f4c9e7164ff3e9372292639 hrs 24 mins ago0xa6c58da995d30a3562d2e81eb06c42cfb5ffefd7  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.0083668035
0x6185e3eea7befdc94c2591afffd506c63dfda598b00e670012db29991ae716c472292609 hrs 25 mins ago0x9e315e9701908501f6dc68a2af6e28a20c75d970  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0.33 Ether0.00038721
0x23941b706de57cbc03f3dea7ae303b4a1d7cdad1814b806554954c4de6d6ce8272292509 hrs 28 mins ago0x7f4d43c46073f656ff231a3a6bf3170043f731f3  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.00351387729
0x1b2a144720a515f7d9ec63b27a2ec5d5bae9342e66b4c65ba21baeb97e0dddb672292489 hrs 28 mins ago0xf921f632516c5805720204eacef0a6d525b8f724  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.00351411753
0x6dbc15ca30efd08f501d5da802033cfab36f351b51f1987d7c13df269a8d314872292469 hrs 29 mins ago0x9e315e9701908501f6dc68a2af6e28a20c75d970  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0.33 Ether0.00038721
0x6a13deafb0ba121e4832da4ed499c1ed656cebfa70ce7da05ea8287efaedc4f4722888911 hrs 26 mins ago0x6ba5835665a95462c414b5fad64782444402951e  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.0050202207
0x27aa02d58cee5df0d3d069110f020d519e3449f5d8ab33b50b90940384e54dcf722888811 hrs 26 mins ago0xc92d7f1fa2938c74b590f4495e53cb35b98c2d2a  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.0050198247
0xef631860aeccfbe07f48966d9825368d89e7b48f796a7b2ca620f7186f8075f5722887911 hrs 29 mins ago0xf0bb18303f9adf2b3852926438daf80900f005d0  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0.33 Ether0.000929304
0x02eac34ea87e6c1b0043573f9083e878fbf2feb37716484850d5fb7d4557da18722852113 hrs 36 mins ago0x0d518269cfd6044b839927192ed35502055785e9  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.0008126536
0x4c394f5ffd39985de97ff4fe727b306bca8e38bc24e442b61ce789b84b7dbf7b722850313 hrs 42 mins ago0x13fb97da9d2407da6dbc2d6c175b51d0f5d9d903  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0.017 Ether0.000359706
0xb04616e297b13729676f63af710abadbb004ddc1312bda17038fa174e92d1bfe722821515 hrs 17 mins ago0x555c6cdd6f1a4b6c3db8018b8e9c4ca9ed2018ae  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.0032551541
0x44248c2108b0fce01840de7abbe9978aa249504dd72fdbab6c6c18e58d65fbb7722820015 hrs 23 mins ago0x13fb97da9d2407da6dbc2d6c175b51d0f5d9d903  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0.085 Ether0.000479864
0x06841543a3d9db2aeb362544ad7429a0f75e7dd0d173e1d09845bec728f16bf4722814815 hrs 41 mins ago0x03014be565459aa0829f2641935949d7be8b1ed9  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.0014221438
0x4e7ca0d0b373859f2e48a4a9393a4a28c275b8e6f18b218d39836ac11165f1fc722814315 hrs 42 mins ago0x6eac7d87a9f2ad5c8c03c79e71b9038468043780  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0.017 Ether0.0007314022
0x598de559a0d67dc18c08575d9ee7a5891c0579837ae34074ec306ed04a4bb61a72237171 day 17 hrs ago0x1e849ad655f7f364c4022bd8129f51083570d95f  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.0150610185
0xb7979a6fff34e29ae1fe4d9a2fd3cf84ca92051b60963a729c0243fb491169ea72237171 day 17 hrs ago0x55f74949a15ce98c9e9d8ebbdd774d5d7a25b473  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.0150599889
0xc4bff5f0476ce6d7918b49683adba50e7831b141330f20dcc2f819bb840f02a572237131 day 17 hrs ago0x1d18e6494ce1e5f12eae7df7a44a9156bbc9941f  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0.33 Ether0.001122966
0x56b04d8b9663545c5db233a808511d4b12670747300c94ff4b7f3cb7246f065872236561 day 17 hrs ago0xa6c58da995d30a3562d2e81eb06c42cfb5ffefd7  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.00886835697
0x00806915a571bed46e99965a4c99758addbff60dabe2b6e39af7caffa9e683ae72236561 day 17 hrs ago0x7f4d43c46073f656ff231a3a6bf3170043f731f3  IN   0x75d745eaea0ab0a8c9542959311c1c3166f6567d0 Ether0.00886860183
[ Download CSV Export 

Latest 25 Internal Transaction, Click here to view more Internal Transactions as a result of Contract Execution

Parent TxHash Block Age From To Value
0x18a75690a39ff23b28212e7e9def1952bd420f3cf7cc1e3d55edbc3995e72b5972303633 hrs 6 mins ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00085 Ether
0x4c394f5ffd39985de97ff4fe727b306bca8e38bc24e442b61ce789b84b7dbf7b722850313 hrs 42 mins ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00085 Ether
0x44248c2108b0fce01840de7abbe9978aa249504dd72fdbab6c6c18e58d65fbb7722820015 hrs 23 mins ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00425 Ether
0x4e7ca0d0b373859f2e48a4a9393a4a28c275b8e6f18b218d39836ac11165f1fc722814315 hrs 42 mins ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0x9e6033fb9bc60653266d35275e764a0b1e0dca4b0.00085 Ether
0xc4bff5f0476ce6d7918b49683adba50e7831b141330f20dcc2f819bb840f02a572237131 day 17 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0x9e6033fb9bc60653266d35275e764a0b1e0dca4b0.0165 Ether
0x2ab1fb5747e10e6f21cfe5f420515db36aa7aa98aab799cf3a5a49fbb4cc1ccd72236481 day 17 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0x9e6033fb9bc60653266d35275e764a0b1e0dca4b0.0165 Ether
0x4520494f16e8d7c4031bede653f46bd113482b04875557f5a0fa911118a142d872220902 days 2 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00425 Ether
0x834a17166cc08fea991f48ee627638a1fe6ca46a199379d3c594287ac368b94272220882 days 2 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00425 Ether
0x8e51810384303f7a6967bd8eddecf97ea5a67aeb26b0149f2f11bfb0c4b7804772217972 days 4 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00425 Ether
0xcc94a5e6ccb0d83ce1f728f811e8e5104951f3a5391a8b158e01cc8e2d8c166c72217952 days 4 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00425 Ether
0xdd3aae562c2b944462c6cfff6920ccd193eceed704fecda8138c6de48354320172215562 days 5 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0x9e6033fb9bc60653266d35275e764a0b1e0dca4b0.00085 Ether
0x23f6504ca2c27dd84071ce133adb9b214104433d0dfe10beafd5382a16fd761a72178843 days 2 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00425 Ether
0xa74793a1f9140751faa1d103f816d15c0cfb19d25277eb084c8cab846157f25972178823 days 2 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00425 Ether
0xc0749662aab4c433695ea3c2bc6d4cdd8c357a00a90650cc99445ecbd23056f472174133 days 5 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00425 Ether
0xae851d37af1ce2e73520d3d1dccd005f10faeb1998c896f4a6e5e1a7d7720dd272174123 days 5 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00425 Ether
0x33fb1087e25668f7d9a164d8adce145da1f86d106393bc3b6a33eb1010dda2cd72174103 days 5 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00425 Ether
0x6662e18d16e08db09333369739157b8cb721fa6e59c3226db28142a5538d5a6372167673 days 9 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0x5d7f92c45c2b6a1711a0a1a7b7f6608437d17e760.0165 Ether
0x23b73a3aad36ea897257662e5650493c72d33027477b7cf8218855fd0066c96272140554 days 38 mins ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00425 Ether
0x1598ad003e87e85358f1a8dfe6d27cc82667201d8aaf70fd3cb154170703429672140534 days 38 mins ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0xab7c859ba9c82d6120e48fb8c6194c724408e2440.00425 Ether
0xe603ba5a43c028baaffd4e5401024afc574dfd989a42ea17dff33011adc07a4872137204 days 2 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0x9e6033fb9bc60653266d35275e764a0b1e0dca4b0.00085 Ether
0x8ebe672cb58e29a28aae2f8c8560733c7a10415334cea3fcd1e51395131a7c1472137084 days 2 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0x9e6033fb9bc60653266d35275e764a0b1e0dca4b0.00085 Ether
0xa129ca0004ddb94a8d6a212be27bbc86b972191fa1f1e801de9da624262dbaf472128304 days 7 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0x5d7f92c45c2b6a1711a0a1a7b7f6608437d17e760.0165 Ether
0xffa0a21945938f82ce8653dbac76fa8631d4b8f3509468a4ada998b7ade3740f72126754 days 8 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0x5d7f92c45c2b6a1711a0a1a7b7f6608437d17e760.0165 Ether
0x0e2c75ebd6654cdf49d3a4da4ba2f3cba3bdb5d1e079cc46f213986e9b46784e72126504 days 8 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0x5d7f92c45c2b6a1711a0a1a7b7f6608437d17e760.0165 Ether
0x8cd69774954f3c7da1cc5276c6b5f9939e9761af76589347910ee19633b2a11b72126224 days 8 hrs ago0x75d745eaea0ab0a8c9542959311c1c3166f6567d0x5d7f92c45c2b6a1711a0a1a7b7f6608437d17e760.0165 Ether
[ Download CSV Export 
Warning: The compiled contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity) Solidity Compiler Bugs.

Contract Source Code Verified (Similar Match)
Note: This contract matches the deployed ByteCode of the Verified Source Code for Contract 0x7f0a2c82cd2ef606310d377b9895ee76e1277ae6
Contract Name: PackSale
Compiler Version: v0.4.24+commit.e67f0147
Optimization Enabled: Yes
Runs (Optimizer):  200


Contract Source Code
pragma solidity ^0.4.24;

// File: contracts/openzeppelin-solidity/introspection/ERC165.sol

/**
 * @title ERC165
 * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
 */
interface ERC165 {

  /**
   * @notice Query if a contract implements an interface
   * @param _interfaceId The interface identifier, as specified in ERC-165
   * @dev Interface identification is specified in ERC-165. This function
   * uses less than 30,000 gas.
   */
  function supportsInterface(bytes4 _interfaceId)
    external
    view
    returns (bool);
}

// File: contracts/openzeppelin-solidity/token/ERC721/ERC721Basic.sol

/**
 * @title ERC721 Non-Fungible Token Standard basic interface
 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract ERC721Basic is ERC165 {
  event Transfer(
    address indexed _from,
    address indexed _to,
    uint256 indexed _tokenId
  );
  event Approval(
    address indexed _owner,
    address indexed _approved,
    uint256 indexed _tokenId
  );
  event ApprovalForAll(
    address indexed _owner,
    address indexed _operator,
    bool _approved
  );

  function balanceOf(address _owner) public view returns (uint256 _balance);
  function ownerOf(uint256 _tokenId) public view returns (address _owner);
  function exists(uint256 _tokenId) public view returns (bool _exists);

  function approve(address _to, uint256 _tokenId) public;
  function getApproved(uint256 _tokenId)
    public view returns (address _operator);

  function setApprovalForAll(address _operator, bool _approved) public;
  function isApprovedForAll(address _owner, address _operator)
    public view returns (bool);

  function transferFrom(address _from, address _to, uint256 _tokenId) public;
  function safeTransferFrom(address _from, address _to, uint256 _tokenId)
    public;

  function safeTransferFrom(
    address _from,
    address _to,
    uint256 _tokenId,
    bytes _data
  )
    public;
}

// File: contracts/openzeppelin-solidity/token/ERC721/ERC721.sol

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract ERC721Enumerable is ERC721Basic {
  function totalSupply() public view returns (uint256);
  function tokenOfOwnerByIndex(
    address _owner,
    uint256 _index
  )
    public
    view
    returns (uint256 _tokenId);

  function tokenByIndex(uint256 _index) public view returns (uint256);
}


/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract ERC721Metadata is ERC721Basic {
  function name() external view returns (string _name);
  function symbol() external view returns (string _symbol);
  function tokenURI(uint256 _tokenId) public view returns (string);
}


/**
 * @title ERC-721 Non-Fungible Token Standard, full implementation interface
 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata {
}

// File: contracts/openzeppelin-solidity/token/ERC721/ERC721Receiver.sol

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
contract ERC721Receiver {
  /**
   * @dev Magic value to be returned upon successful reception of an NFT
   *  Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`,
   *  which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
   */
  bytes4 internal constant ERC721_RECEIVED = 0x150b7a02;

  /**
   * @notice Handle the receipt of an NFT
   * @dev The ERC721 smart contract calls this function on the recipient
   * after a `safetransfer`. This function MAY throw to revert and reject the
   * transfer. Return of other than the magic value MUST result in the 
   * transaction being reverted.
   * Note: the contract address is always the message sender.
   * @param _operator The address which called `safeTransferFrom` function
   * @param _from The address which previously owned the token
   * @param _tokenId The NFT identifier which is being transfered
   * @param _data Additional data with no specified format
   * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
   */
  function onERC721Received(
    address _operator,
    address _from,
    uint256 _tokenId,
    bytes _data
  )
    public
    returns(bytes4);
}

// File: contracts/openzeppelin-solidity/math/SafeMath.sol

/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, throws on overflow.
  */
  function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
    // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
    if (a == 0) {
      return 0;
    }

    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 a / b;
  }

  /**
  * @dev Subtracts 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 c) {
    c = a + b;
    assert(c >= a);
    return c;
  }
}

// File: contracts/openzeppelin-solidity/AddressUtils.sol

/**
 * Utility library of inline functions on addresses
 */
library AddressUtils {

  /**
   * Returns whether the target address is a contract
   * @dev This function will return false if invoked during the constructor of a contract,
   * as the code is not actually created until after the constructor finishes.
   * @param addr address to check
   * @return whether the target address is a contract
   */
  function isContract(address addr) internal view returns (bool) {
    uint256 size;
    // XXX Currently there is no better way to check if there is a contract in an address
    // than to check the size of the code at that address.
    // See https://ethereum.stackexchange.com/a/14016/36603
    // for more details about how this works.
    // TODO Check this again before the Serenity release, because all addresses will be
    // contracts then.
    // solium-disable-next-line security/no-inline-assembly
    assembly { size := extcodesize(addr) }
    return size > 0;
  }

}

// File: contracts/openzeppelin-solidity/introspection/SupportsInterfaceWithLookup.sol

/**
 * @title SupportsInterfaceWithLookup
 * @author Matt Condon (@shrugs)
 * @dev Implements ERC165 using a lookup table.
 */
contract SupportsInterfaceWithLookup is ERC165 {
  bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7;
  /**
   * 0x01ffc9a7 ===
   *   bytes4(keccak256('supportsInterface(bytes4)'))
   */

  /**
   * @dev a mapping of interface id to whether or not it's supported
   */
  mapping(bytes4 => bool) internal supportedInterfaces;

  /**
   * @dev A contract implementing SupportsInterfaceWithLookup
   * implement ERC165 itself
   */
  constructor()
    public
  {
    _registerInterface(InterfaceId_ERC165);
  }

  /**
   * @dev implement supportsInterface(bytes4) using a lookup table
   */
  function supportsInterface(bytes4 _interfaceId)
    external
    view
    returns (bool)
  {
    return supportedInterfaces[_interfaceId];
  }

  /**
   * @dev private method for registering an interface
   */
  function _registerInterface(bytes4 _interfaceId)
    internal
  {
    require(_interfaceId != 0xffffffff);
    supportedInterfaces[_interfaceId] = true;
  }
}

// File: contracts/openzeppelin-solidity/token/ERC721/ERC721BasicToken.sol

/**
 * @title ERC721 Non-Fungible Token Standard basic implementation
 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract ERC721BasicToken is SupportsInterfaceWithLookup, ERC721Basic {

  bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd;
  /*
   * 0x80ac58cd ===
   *   bytes4(keccak256('balanceOf(address)')) ^
   *   bytes4(keccak256('ownerOf(uint256)')) ^
   *   bytes4(keccak256('approve(address,uint256)')) ^
   *   bytes4(keccak256('getApproved(uint256)')) ^
   *   bytes4(keccak256('setApprovalForAll(address,bool)')) ^
   *   bytes4(keccak256('isApprovedForAll(address,address)')) ^
   *   bytes4(keccak256('transferFrom(address,address,uint256)')) ^
   *   bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
   *   bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
   */

  bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79;
  /*
   * 0x4f558e79 ===
   *   bytes4(keccak256('exists(uint256)'))
   */

  using SafeMath for uint256;
  using AddressUtils for address;

  // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
  // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
  bytes4 private constant ERC721_RECEIVED = 0x150b7a02;

  // Mapping from token ID to owner
  mapping (uint256 => address) internal tokenOwner;

  // Mapping from token ID to approved address
  mapping (uint256 => address) internal tokenApprovals;

  // Mapping from owner to number of owned token
  mapping (address => uint256) internal ownedTokensCount;

  // Mapping from owner to operator approvals
  mapping (address => mapping (address => bool)) internal operatorApprovals;

  /**
   * @dev Guarantees msg.sender is owner of the given token
   * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender
   */
  modifier onlyOwnerOf(uint256 _tokenId) {
    require(ownerOf(_tokenId) == msg.sender);
    _;
  }

  /**
   * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator
   * @param _tokenId uint256 ID of the token to validate
   */
  modifier canTransfer(uint256 _tokenId) {
    require(isApprovedOrOwner(msg.sender, _tokenId));
    _;
  }

  constructor()
    public
  {
    // register the supported interfaces to conform to ERC721 via ERC165
    _registerInterface(InterfaceId_ERC721);
    _registerInterface(InterfaceId_ERC721Exists);
  }

  /**
   * @dev Gets the balance of the specified address
   * @param _owner address to query the balance of
   * @return uint256 representing the amount owned by the passed address
   */
  function balanceOf(address _owner) public view returns (uint256) {
    require(_owner != address(0));
    return ownedTokensCount[_owner];
  }

  /**
   * @dev Gets the owner of the specified token ID
   * @param _tokenId uint256 ID of the token to query the owner of
   * @return owner address currently marked as the owner of the given token ID
   */
  function ownerOf(uint256 _tokenId) public view returns (address) {
    address owner = tokenOwner[_tokenId];
    require(owner != address(0));
    return owner;
  }

  /**
   * @dev Returns whether the specified token exists
   * @param _tokenId uint256 ID of the token to query the existence of
   * @return whether the token exists
   */
  function exists(uint256 _tokenId) public view returns (bool) {
    address owner = tokenOwner[_tokenId];
    return owner != address(0);
  }

  /**
   * @dev Approves another address to transfer the given token ID
   * The zero address indicates there is no approved address.
   * There can only be one approved address per token at a given time.
   * Can only be called by the token owner or an approved operator.
   * @param _to address to be approved for the given token ID
   * @param _tokenId uint256 ID of the token to be approved
   */
  function approve(address _to, uint256 _tokenId) public {
    address owner = ownerOf(_tokenId);
    require(_to != owner);
    require(msg.sender == owner || isApprovedForAll(owner, msg.sender));

    tokenApprovals[_tokenId] = _to;
    emit Approval(owner, _to, _tokenId);
  }

  /**
   * @dev Gets the approved address for a token ID, or zero if no address set
   * @param _tokenId uint256 ID of the token to query the approval of
   * @return address currently approved for the given token ID
   */
  function getApproved(uint256 _tokenId) public view returns (address) {
    return tokenApprovals[_tokenId];
  }

  /**
   * @dev Sets or unsets the approval of a given operator
   * An operator is allowed to transfer all tokens of the sender on their behalf
   * @param _to operator address to set the approval
   * @param _approved representing the status of the approval to be set
   */
  function setApprovalForAll(address _to, bool _approved) public {
    require(_to != msg.sender);
    operatorApprovals[msg.sender][_to] = _approved;
    emit ApprovalForAll(msg.sender, _to, _approved);
  }

  /**
   * @dev Tells whether an operator is approved by a given owner
   * @param _owner owner address which you want to query the approval of
   * @param _operator operator address which you want to query the approval of
   * @return bool whether the given operator is approved by the given owner
   */
  function isApprovedForAll(
    address _owner,
    address _operator
  )
    public
    view
    returns (bool)
  {
    return operatorApprovals[_owner][_operator];
  }

  /**
   * @dev Transfers the ownership of a given token ID to another address
   * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
   * Requires the msg sender to be the owner, approved, or operator
   * @param _from current owner of the token
   * @param _to address to receive the ownership of the given token ID
   * @param _tokenId uint256 ID of the token to be transferred
  */
  function transferFrom(
    address _from,
    address _to,
    uint256 _tokenId
  )
    public
    canTransfer(_tokenId)
  {
    require(_from != address(0));
    require(_to != address(0));

    clearApproval(_from, _tokenId);
    removeTokenFrom(_from, _tokenId);
    addTokenTo(_to, _tokenId);

    emit Transfer(_from, _to, _tokenId);
  }

  /**
   * @dev Safely transfers the ownership of a given token ID to another address
   * If the target address is a contract, it must implement `onERC721Received`,
   * which is called upon a safe transfer, and return the magic value
   * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
   * the transfer is reverted.
   *
   * Requires the msg sender to be the owner, approved, or operator
   * @param _from current owner of the token
   * @param _to address to receive the ownership of the given token ID
   * @param _tokenId uint256 ID of the token to be transferred
  */
  function safeTransferFrom(
    address _from,
    address _to,
    uint256 _tokenId
  )
    public
    canTransfer(_tokenId)
  {
    // solium-disable-next-line arg-overflow
    safeTransferFrom(_from, _to, _tokenId, "");
  }

  /**
   * @dev Safely transfers the ownership of a given token ID to another address
   * If the target address is a contract, it must implement `onERC721Received`,
   * which is called upon a safe transfer, and return the magic value
   * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
   * the transfer is reverted.
   * Requires the msg sender to be the owner, approved, or operator
   * @param _from current owner of the token
   * @param _to address to receive the ownership of the given token ID
   * @param _tokenId uint256 ID of the token to be transferred
   * @param _data bytes data to send along with a safe transfer check
   */
  function safeTransferFrom(
    address _from,
    address _to,
    uint256 _tokenId,
    bytes _data
  )
    public
    canTransfer(_tokenId)
  {
    transferFrom(_from, _to, _tokenId);
    // solium-disable-next-line arg-overflow
    require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data));
  }

  /**
   * @dev Returns whether the given spender can transfer a given token ID
   * @param _spender address of the spender to query
   * @param _tokenId uint256 ID of the token to be transferred
   * @return bool whether the msg.sender is approved for the given token ID,
   *  is an operator of the owner, or is the owner of the token
   */
  function isApprovedOrOwner(
    address _spender,
    uint256 _tokenId
  )
    internal
    view
    returns (bool)
  {
    address owner = ownerOf(_tokenId);
    // Disable solium check because of
    // https://github.com/duaraghav8/Solium/issues/175
    // solium-disable-next-line operator-whitespace
    return (
      _spender == owner ||
      getApproved(_tokenId) == _spender ||
      isApprovedForAll(owner, _spender)
    );
  }

  /**
   * @dev Internal function to mint a new token
   * Reverts if the given token ID already exists
   * @param _to The address that will own the minted token
   * @param _tokenId uint256 ID of the token to be minted by the msg.sender
   */
  function _mint(address _to, uint256 _tokenId) internal {
    require(_to != address(0));
    addTokenTo(_to, _tokenId);
    emit Transfer(address(0), _to, _tokenId);
  }

  /**
   * @dev Internal function to burn a specific token
   * Reverts if the token does not exist
   * @param _tokenId uint256 ID of the token being burned by the msg.sender
   */
  function _burn(address _owner, uint256 _tokenId) internal {
    clearApproval(_owner, _tokenId);
    removeTokenFrom(_owner, _tokenId);
    emit Transfer(_owner, address(0), _tokenId);
  }

  /**
   * @dev Internal function to clear current approval of a given token ID
   * Reverts if the given address is not indeed the owner of the token
   * @param _owner owner of the token
   * @param _tokenId uint256 ID of the token to be transferred
   */
  function clearApproval(address _owner, uint256 _tokenId) internal {
    require(ownerOf(_tokenId) == _owner);
    if (tokenApprovals[_tokenId] != address(0)) {
      tokenApprovals[_tokenId] = address(0);
    }
  }

  /**
   * @dev Internal function to add a token ID to the list of a given address
   * @param _to address representing the new owner of the given token ID
   * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
   */
  function addTokenTo(address _to, uint256 _tokenId) internal {
    require(tokenOwner[_tokenId] == address(0));
    tokenOwner[_tokenId] = _to;
    ownedTokensCount[_to] = ownedTokensCount[_to].add(1);
  }

  /**
   * @dev Internal function to remove a token ID from the list of a given address
   * @param _from address representing the previous owner of the given token ID
   * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
   */
  function removeTokenFrom(address _from, uint256 _tokenId) internal {
    require(ownerOf(_tokenId) == _from);
    ownedTokensCount[_from] = ownedTokensCount[_from].sub(1);
    tokenOwner[_tokenId] = address(0);
  }

  /**
   * @dev Internal function to invoke `onERC721Received` on a target address
   * The call is not executed if the target address is not a contract
   * @param _from address representing the previous owner of the given token ID
   * @param _to target address that will receive the tokens
   * @param _tokenId uint256 ID of the token to be transferred
   * @param _data bytes optional data to send along with the call
   * @return whether the call correctly returned the expected magic value
   */
  function checkAndCallSafeTransfer(
    address _from,
    address _to,
    uint256 _tokenId,
    bytes _data
  )
    internal
    returns (bool)
  {
    if (!_to.isContract()) {
      return true;
    }
    bytes4 retval = ERC721Receiver(_to).onERC721Received(
      msg.sender, _from, _tokenId, _data);
    return (retval == ERC721_RECEIVED);
  }
}

// File: contracts/openzeppelin-solidity/token/ERC721/ERC721Token.sol

/**
 * @title Full ERC721 Token
 * This implementation includes all the required and some optional functionality of the ERC721 standard
 * Moreover, it includes approve all functionality using operator terminology
 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract ERC721Token is SupportsInterfaceWithLookup, ERC721BasicToken, ERC721 {

  bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63;
  /**
   * 0x780e9d63 ===
   *   bytes4(keccak256('totalSupply()')) ^
   *   bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^
   *   bytes4(keccak256('tokenByIndex(uint256)'))
   */

  bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f;
  /**
   * 0x5b5e139f ===
   *   bytes4(keccak256('name()')) ^
   *   bytes4(keccak256('symbol()')) ^
   *   bytes4(keccak256('tokenURI(uint256)'))
   */

  // Token name
  string internal name_;

  // Token symbol
  string internal symbol_;

  // Mapping from owner to list of owned token IDs
  mapping(address => uint256[]) internal ownedTokens;

  // Mapping from token ID to index of the owner tokens list
  mapping(uint256 => uint256) internal ownedTokensIndex;

  // Array with all token ids, used for enumeration
  uint256[] internal allTokens;

  // Mapping from token id to position in the allTokens array
  mapping(uint256 => uint256) internal allTokensIndex;

  // Optional mapping for token URIs
  mapping(uint256 => string) internal tokenURIs;

  /**
   * @dev Constructor function
   */
  constructor(string _name, string _symbol) public {
    name_ = _name;
    symbol_ = _symbol;

    // register the supported interfaces to conform to ERC721 via ERC165
    _registerInterface(InterfaceId_ERC721Enumerable);
    _registerInterface(InterfaceId_ERC721Metadata);
  }

  /**
   * @dev Gets the token name
   * @return string representing the token name
   */
  function name() external view returns (string) {
    return name_;
  }

  /**
   * @dev Gets the token symbol
   * @return string representing the token symbol
   */
  function symbol() external view returns (string) {
    return symbol_;
  }

  /**
   * @dev Returns an URI for a given token ID
   * Throws if the token ID does not exist. May return an empty string.
   * @param _tokenId uint256 ID of the token to query
   */
  function tokenURI(uint256 _tokenId) public view returns (string) {
    require(exists(_tokenId));
    return tokenURIs[_tokenId];
  }

  /**
   * @dev Gets the token ID at a given index of the tokens list of the requested owner
   * @param _owner address owning the tokens list to be accessed
   * @param _index uint256 representing the index to be accessed of the requested tokens list
   * @return uint256 token ID at the given index of the tokens list owned by the requested address
   */
  function tokenOfOwnerByIndex(
    address _owner,
    uint256 _index
  )
    public
    view
    returns (uint256)
  {
    require(_index < balanceOf(_owner));
    return ownedTokens[_owner][_index];
  }

  /**
   * @dev Gets the total amount of tokens stored by the contract
   * @return uint256 representing the total amount of tokens
   */
  function totalSupply() public view returns (uint256) {
    return allTokens.length;
  }

  /**
   * @dev Gets the token ID at a given index of all the tokens in this contract
   * Reverts if the index is greater or equal to the total number of tokens
   * @param _index uint256 representing the index to be accessed of the tokens list
   * @return uint256 token ID at the given index of the tokens list
   */
  function tokenByIndex(uint256 _index) public view returns (uint256) {
    require(_index < totalSupply());
    return allTokens[_index];
  }

  /**
   * @dev Internal function to set the token URI for a given token
   * Reverts if the token ID does not exist
   * @param _tokenId uint256 ID of the token to set its URI
   * @param _uri string URI to assign
   */
  function _setTokenURI(uint256 _tokenId, string _uri) internal {
    require(exists(_tokenId));
    tokenURIs[_tokenId] = _uri;
  }

  /**
   * @dev Internal function to add a token ID to the list of a given address
   * @param _to address representing the new owner of the given token ID
   * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
   */
  function addTokenTo(address _to, uint256 _tokenId) internal {
    super.addTokenTo(_to, _tokenId);
    uint256 length = ownedTokens[_to].length;
    ownedTokens[_to].push(_tokenId);
    ownedTokensIndex[_tokenId] = length;
  }

  /**
   * @dev Internal function to remove a token ID from the list of a given address
   * @param _from address representing the previous owner of the given token ID
   * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
   */
  function removeTokenFrom(address _from, uint256 _tokenId) internal {
    super.removeTokenFrom(_from, _tokenId);

    uint256 tokenIndex = ownedTokensIndex[_tokenId];
    uint256 lastTokenIndex = ownedTokens[_from].length.sub(1);
    uint256 lastToken = ownedTokens[_from][lastTokenIndex];

    ownedTokens[_from][tokenIndex] = lastToken;
    ownedTokens[_from][lastTokenIndex] = 0;
    // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to
    // be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping
    // the lastToken to the first position, and then dropping the element placed in the last position of the list

    ownedTokens[_from].length--;
    ownedTokensIndex[_tokenId] = 0;
    ownedTokensIndex[lastToken] = tokenIndex;
  }

  /**
   * @dev Internal function to mint a new token
   * Reverts if the given token ID already exists
   * @param _to address the beneficiary that will own the minted token
   * @param _tokenId uint256 ID of the token to be minted by the msg.sender
   */
  function _mint(address _to, uint256 _tokenId) internal {
    super._mint(_to, _tokenId);

    allTokensIndex[_tokenId] = allTokens.length;
    allTokens.push(_tokenId);
  }

  /**
   * @dev Internal function to burn a specific token
   * Reverts if the token does not exist
   * @param _owner owner of the token to burn
   * @param _tokenId uint256 ID of the token being burned by the msg.sender
   */
  function _burn(address _owner, uint256 _tokenId) internal {
    super._burn(_owner, _tokenId);

    // Clear metadata (if any)
    if (bytes(tokenURIs[_tokenId]).length != 0) {
      delete tokenURIs[_tokenId];
    }

    // Reorg all tokens array
    uint256 tokenIndex = allTokensIndex[_tokenId];
    uint256 lastTokenIndex = allTokens.length.sub(1);
    uint256 lastToken = allTokens[lastTokenIndex];

    allTokens[tokenIndex] = lastToken;
    allTokens[lastTokenIndex] = 0;

    allTokens.length--;
    allTokensIndex[_tokenId] = 0;
    allTokensIndex[lastToken] = tokenIndex;
  }

}

// File: contracts/openzeppelin-solidity/ownership/Ownable.sol

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  address public owner;


  event OwnershipRenounced(address indexed previousOwner);
  event OwnershipTransferred(
    address indexed previousOwner,
    address indexed newOwner
  );


  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  constructor() 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 relinquish control of the contract.
   * @notice Renouncing to ownership will leave the contract without an owner.
   * It will not be possible to call the functions with the `onlyOwner`
   * modifier anymore.
   */
  function renounceOwnership() public onlyOwner {
    emit OwnershipRenounced(owner);
    owner = address(0);
  }

  /**
   * @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 {
    _transferOwnership(_newOwner);
  }

  /**
   * @dev Transfers control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function _transferOwnership(address _newOwner) internal {
    require(_newOwner != address(0));
    emit OwnershipTransferred(owner, _newOwner);
    owner = _newOwner;
  }
}

// File: contracts/ERC721TokenWithData.sol

// import "./ERC721SlimTokenArray.sol";



// an ERC721 token with additional data storage,
contract ERC721TokenWithData is ERC721Token("CryptoAssaultUnit", "CAU"), Ownable {

  /**
   * @dev Returns whether the given spender can transfer a given token ID
   * @param _spender address of the spender to query
   * @param _tokenId uint256 ID of the token to be transferred
   * @return bool whether the msg.sender is approved for the given token ID,
   *  is an operator of the owner, or is the owner of the token
   */
	function isApprovedOrOwner(
		address _spender,
		uint256 _tokenId
	)
		internal
		view
		returns (bool)
	{
		address owner = ownerOf(_tokenId);
		// Disable solium check because of
		// https://github.com/duaraghav8/Solium/issues/175
		// solium-disable-next-line operator-whitespace
		return (
			_spender == owner ||
			approvedContractAddresses[_spender] ||
			getApproved(_tokenId) == _spender ||
			isApprovedForAll(owner, _spender)
		);
	}

	mapping (address => bool) internal approvedContractAddresses;
	bool approvedContractsFinalized = false;

	/**
	* @notice Approve a contract address for minting tokens and transferring tokens, when approved by the owner
	* @param contractAddress The address that will be approved
	*/
	function addApprovedContractAddress(address contractAddress) public onlyOwner
	{
		require(!approvedContractsFinalized);
		approvedContractAddresses[contractAddress] = true;
	}

	/**
	* @notice Unapprove a contract address for minting tokens and transferring tokens
	* @param contractAddress The address that will be unapproved
	*/
	function removeApprovedContractAddress(address contractAddress) public onlyOwner
	{
		require(!approvedContractsFinalized);
		approvedContractAddresses[contractAddress] = false;
	}

	/**
	* @notice Finalize the contract so it will be forever impossible to change the approved contracts list
	*/
	function finalizeApprovedContracts() public onlyOwner {
		approvedContractsFinalized = true;
	}

	mapping(uint256 => mapping(uint256 => uint256)) data;

	function getData(uint256 _tokenId, uint256 _index) public view returns (uint256) {
		return data[_index][_tokenId];
	}

	function getData3(uint256 _tokenId1, uint256 _tokenId2, uint256 _tokenId3, uint256 _index) public view returns (uint256, uint256, uint256) {
		return (
			data[_index][_tokenId1],
			data[_index][_tokenId2],
			data[_index][_tokenId3]
		);
	}
	
	function getDataAndOwner3(uint256 _tokenId1, uint256 _tokenId2, uint256 _tokenId3, uint256 _index) public view returns (uint256, uint256, uint256, address, address, address) {
		return (
			data[_index][_tokenId1],
			data[_index][_tokenId2],
			data[_index][_tokenId3],
			ownerOf(_tokenId1),
			ownerOf(_tokenId2),
			ownerOf(_tokenId3)
		);
	}
	
	function _setData(uint256 _tokenId, uint256 _index, uint256 _data) internal {
		
		data[_index][_tokenId] = _data;
	}

	function setData(uint256 _tokenId, uint256 _index, uint256 _data) public {
		
		require(approvedContractAddresses[msg.sender], "not an approved sender");
		data[_index][_tokenId] = _data;
	}

	/**
	* @notice Gets the list of tokens owned by a given address
	* @param _owner address to query the tokens of
	* @return uint256[] representing the list of tokens owned by the passed address
	*/
	function tokensOfWithData(address _owner, uint256 _index) public view returns (uint256[], uint256[]) {
		uint256[] memory tokensList = ownedTokens[_owner];
		uint256[] memory dataList = new uint256[](tokensList.length);
		for (uint i=0; i<tokensList.length; i++) {
			dataList[i] = data[_index][tokensList[i]];
		}
		return (tokensList, dataList);
	}

	// The tokenId of the next minted token. It auto-increments.
	uint256 nextTokenId = 1;

	function getNextTokenId() public view returns (uint256) {
		return nextTokenId;
	}

	/**
	* @notice Mint token function
	* @param _to The address that will own the minted token
	*/
	function mintAndSetData(address _to, uint256 _data) public returns (uint256) {

		require(approvedContractAddresses[msg.sender], "not an approved sender");

		uint256 tokenId = nextTokenId;
		nextTokenId++;
		_mint(_to, tokenId);
		_setData(tokenId, 0, _data);

		return tokenId;
	}

	function burn(uint256 _tokenId) public {
		require(
			approvedContractAddresses[msg.sender] ||
			msg.sender == owner, "burner not approved"
		);

		_burn(ownerOf(_tokenId), _tokenId);
	}
	
	function burn3(uint256 _tokenId1, uint256 _tokenId2, uint256 _tokenId3) public {
		require(
			approvedContractAddresses[msg.sender] ||
			msg.sender == owner, "burner not approved"
		);

		_burn(ownerOf(_tokenId1), _tokenId1);
		_burn(ownerOf(_tokenId2), _tokenId2);
		_burn(ownerOf(_tokenId3), _tokenId3);
	}
}

// File: contracts/strings/Strings.sol

library Strings {
  // via https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol
  function strConcat(string _a, string _b, string _c, string _d, string _e) internal pure returns (string) {
      bytes memory _ba = bytes(_a);
      bytes memory _bb = bytes(_b);
      bytes memory _bc = bytes(_c);
      bytes memory _bd = bytes(_d);
      bytes memory _be = bytes(_e);
      string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length);
      bytes memory babcde = bytes(abcde);
      uint k = 0;
      for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i];
      for (i = 0; i < _bb.length; i++) babcde[k++] = _bb[i];
      for (i = 0; i < _bc.length; i++) babcde[k++] = _bc[i];
      for (i = 0; i < _bd.length; i++) babcde[k++] = _bd[i];
      for (i = 0; i < _be.length; i++) babcde[k++] = _be[i];
      return string(babcde);
    }

    function strConcat(string _a, string _b, string _c, string _d) internal pure returns (string) {
        return strConcat(_a, _b, _c, _d, "");
    }

    function strConcat(string _a, string _b, string _c) internal pure returns (string) {
        return strConcat(_a, _b, _c, "", "");
    }

    function strConcat(string _a, string _b) internal pure returns (string) {
        return strConcat(_a, _b, "", "", "");
    }

    function uint2str(uint i) internal pure returns (string) {
        if (i == 0) return "0";
        uint j = i;
        uint len;
        while (j != 0){
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint k = len - 1;
        while (i != 0){
            bstr[k--] = byte(48 + i % 10);
            i /= 10;
        }
        return string(bstr);
    }
}

// File: contracts/Token.sol

contract Token is ERC721TokenWithData {

	string metadataUrlPrefix = "https://metadata.cryptoassault.io/unit/";

	/**
	* @dev Returns an URI for a given token ID
	* Throws if the token ID does not exist. May return an empty string.
	* @param _tokenId uint256 ID of the token to query
	*/
	function tokenURI(uint256 _tokenId) public view returns (string) {
		require(exists(_tokenId));
		return Strings.strConcat(metadataUrlPrefix, Strings.uint2str(_tokenId));
	}

	function setMetadataUrlPrefix(string _metadataUrlPrefix) public onlyOwner
	{
		metadataUrlPrefix = _metadataUrlPrefix;
	}
}

// File: contracts/openzeppelin-solidity/lifecycle/Pausable.sol

/**
 * @title Pausable
 * @dev Base contract which allows children to implement an emergency stop mechanism.
 */
contract Pausable is Ownable {
  event Pause();
  event Unpause();

  bool public paused = false;


  /**
   * @dev Modifier to make a function callable only when the contract is not paused.
   */
  modifier whenNotPaused() {
    require(!paused);
    _;
  }

  /**
   * @dev Modifier to make a function callable only when the contract is paused.
   */
  modifier whenPaused() {
    require(paused);
    _;
  }

  /**
   * @dev called by the owner to pause, triggers stopped state
   */
  function pause() onlyOwner whenNotPaused public {
    paused = true;
    emit Pause();
  }

  /**
   * @dev called by the owner to unpause, returns to normal state
   */
  function unpause() onlyOwner whenPaused public {
    paused = false;
    emit Unpause();
  }
}

// File: contracts/PackSale.sol

contract PackSale is Pausable {

	event Sold(address buyer, uint256 sku, uint256 totalPrice);
	event Hatched(address buyer, uint256 amount);

	uint256 constant PRESALE_START_TIME = 1544126400;
	uint256 constant NUM_UNIT_TYPES = 30;

	Token token;

	function setTokenContractAddress(address newAddress) onlyOwner public {
		token = Token(newAddress);
	}
	
	struct WaitingToHatch {
		address owner;
		uint16 amount;
		uint16 rarity;
		uint16 sku;
		uint48 purchasedOnBlockNumber;
	}
	mapping (uint256 => WaitingToHatch) waitingToHatch; // This is a FIFO queue.

	uint64 waitingToHatchNum = 0;
	uint64 waitingToHatchFirstIndex = 0;
	uint64 hatchNonce = 1;

	// maps amount to a price.
	mapping(uint256 => uint256) prices;

	constructor() public {
		prices[1] = 0.017 ether;
		prices[2] = 0.085 ether;
		prices[3] = 0.33 ether;
		prices[4] = 0.587 ether;
		prices[5] = 1.2 ether;
		prices[6] = 2.99 ether;
	}
	
	function withdrawBalance() onlyOwner public {
		owner.transfer(address(this).balance);
	}

	function setPrice(uint32 sku, uint64 price) public onlyOwner {
		prices[sku] = price;
	}

	function getPrice(uint32 sku) public view returns (uint256)
	{
		require(now >= PRESALE_START_TIME, "The sale hasn't started yet");

		uint256 price = prices[sku];
		require (price > 0);

		// Apply the pre-sale discount
		uint256 intervalsSinceSaleStarted = (now - PRESALE_START_TIME) / (2 days);
		// The discount starts at 30% and goes down 1% every 2 days.
		uint256 pricePercentage = 70 + intervalsSinceSaleStarted;
		if (pricePercentage < 100) {
			price = (price * pricePercentage) / 100;
		}

		return price;
	}

	function pushHatch(address to, uint16 amount, uint16 rarity, uint16 sku) private {

		waitingToHatch[waitingToHatchFirstIndex + waitingToHatchNum] = WaitingToHatch(to, amount, rarity, sku, uint32(block.number));
		waitingToHatchNum = waitingToHatchNum + 1;
	}

	function popHatch() private {

		require(waitingToHatchNum > 0, "trying to popHatch() an empty stack");
		waitingToHatchNum = waitingToHatchNum - 1;
		waitingToHatchFirstIndex = waitingToHatchFirstIndex + 1;
	}

	function peekHatch() private view returns (WaitingToHatch) {

		return waitingToHatch[waitingToHatchFirstIndex];
	}

	function buy(uint16 sku, address referral) external payable whenNotPaused {

		uint256 price = getPrice(sku);
		require(msg.value >= price, "Amount paid is too low");

		// push the purchase onto a FIFO, to be minted in a later transaction.

		if (sku == 1) {
			pushHatch(msg.sender, 1, 0, sku); // 1 common or better
		} else if (sku == 2) {
			pushHatch(msg.sender, 5, 0, sku); // 5 common or better
		} else if (sku == 3) {
			// 20 common or better
			pushHatch(msg.sender, 10, 0, sku); 
			pushHatch(msg.sender, 10, 0, sku); 
		} else if (sku == 4) {
			pushHatch(msg.sender, 10, 1, sku);  // 10 rare or better
		} else if (sku == 5) {
			pushHatch(msg.sender, 10, 1, sku);  // 10 rare or better
			// 40 common or better
			pushHatch(msg.sender, 10, 0, sku);
			pushHatch(msg.sender, 10, 0, sku);
			pushHatch(msg.sender, 10, 0, sku);
			pushHatch(msg.sender, 10, 0, sku);
		} else if (sku == 6) {
			// 3 epic or better
			pushHatch(msg.sender, 3, 2, sku);
			// 47 rare or better
			pushHatch(msg.sender, 10, 1, sku);
			pushHatch(msg.sender, 10, 1, sku);
			pushHatch(msg.sender, 10, 1, sku);
			pushHatch(msg.sender, 10, 1, sku);
			pushHatch(msg.sender, 7, 1, sku);
		} else {
			require(false, "Invalid sku");
		}

		// Pay the referral 5%
		if (referral != address(0) && referral != msg.sender) {
			referral.transfer(price / 20);
		}

		emit Sold(msg.sender, sku, price);
	}

	function giveFreeUnit(address to, uint16 minRarity) onlyOwner public
	{
		pushHatch(to, 1, minRarity, 0);
	}

	function getNumMyHatchingUnits() public view returns (uint256) {
		uint256 num = 0;
		for (uint256 i=0; i<waitingToHatchNum; i++) {
			if (waitingToHatch[waitingToHatchFirstIndex + i].owner == msg.sender) {
				num += waitingToHatch[waitingToHatchFirstIndex + i].amount;
			}
		}
		return num;
	}

	function hatchingsNeeded() external view returns (uint256) {

		return waitingToHatchNum;
	}
	
	function getProjectedBlockHash(uint256 blockNumber) internal view returns (uint256) {

		uint256 blockToHash = blockNumber;
		uint256 blocksAgo = block.number - blockToHash;
		blockToHash += ((blocksAgo-1) / 256) * 256;
		return uint256(blockhash(blockToHash));
	}

	function getRandomType(uint16 rand) internal pure returns (uint8)
	{
		return uint8(rand % NUM_UNIT_TYPES);
	}
 
	function getRandomRarity(uint32 rand, uint256 minimumRarity) internal pure returns (uint256)
	{

		uint256 rarityRand;
		if (minimumRarity == 0) {
			rarityRand = rand % 100;
		} else if (minimumRarity == 1) {
			rarityRand = rand % 20 + 80;
		} else if (minimumRarity == 2) {
			rarityRand = rand % 5 + 95;
		} else if (minimumRarity == 3) {
			rarityRand = 99;
		} else {
			require(false, "Invalid minimumRarity");
		}

		if (rarityRand < 80) return 0;
		if (rarityRand < 95) return 1;
		if (rarityRand < 99) return 2;
		return 3;
	}

	function hatch() external whenNotPaused {

		require(waitingToHatchNum > 0, "nothing to hatch");

		WaitingToHatch memory w = peekHatch();
		
		// can't hatch on the same block. its block hash would be unknown.
		require (w.purchasedOnBlockNumber < block.number, "Can't hatch on the same block.");

		uint256 rand = getProjectedBlockHash(w.purchasedOnBlockNumber) + hatchNonce;

		for (uint256 i=0; i<w.amount; i++) {
			rand = uint256(keccak256(abi.encodePacked(rand)));
			uint256 thisRand = rand;
			uint8 unitType = getRandomType(uint16(thisRand));
			thisRand >>= 16;

			uint256 rarity = getRandomRarity(uint32(thisRand), w.rarity);
			thisRand >>= 32;

			// TPRDATEDARSKRANDOM__RANDOM__RANDOM__RANDOM__RAND0000000000000000

			uint256 data = unitType; // 8 bits

			data <<= 4;
			// data |= 0; // tier 0

			// birth timestamp
			data <<= 24;
			data |= now / (1 days);

			data <<= 4;
			data |= rarity;
			data <<= 8;
			data |= w.sku;
			data <<= 208;
			data |= thisRand & 0xffffffffffffffffffffffffffffffffffff0000000000000000;

			token.mintAndSetData(w.owner, data);
		}

		popHatch();

		hatchNonce++;

		emit Hatched(w.owner, w.amount);
	}

}

Contract ABI
[{"constant":true,"inputs":[],"name":"hatchingsNeeded","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdrawBalance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getNumMyHatchingUnits","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"minRarity","type":"uint16"}],"name":"giveFreeUnit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"sku","type":"uint32"},{"name":"price","type":"uint64"}],"name":"setPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newAddress","type":"address"}],"name":"setTokenContractAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"hatch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"sku","type":"uint32"}],"name":"getPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"sku","type":"uint16"},{"name":"referral","type":"address"}],"name":"buy","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"buyer","type":"address"},{"indexed":false,"name":"sku","type":"uint256"},{"indexed":false,"name":"totalPrice","type":"uint256"}],"name":"Sold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"buyer","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Hatched","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]

Contract Creation Code
60806040526000805460a060020a60ff021916905560038054600160c060020a03191670010000000000000000000000000000000017905534801561004357600080fd5b5060008054600160a060020a031916331781556004602052663c6568f12e80007fabd6e7cb50984ff9c2f3e18a2660c3353dadf4e3291deeb275dae2cd1e44fe055567012dfb0cb5e880007f91da3fd0782e51c6b3986e9e672fd566868e71f3dbc2d6c2cd6fbb3e361af2a755670494654067e100007f2e174c10e159ea99b867ce3205125c24a42d128804e4070ed6fcc8cc98166aa0556708257163d32780007f1a1e6821cde7d0159c0d293177871e09677b4e42307c7db3ba94f8648a5a050f556710a741a4627800007f04cde762ef08b6b6c5ded8e8c4c0b3f4e5c9ad7342c88fcc93681b4588b73f05556006905267297e9d28866b00007fc59312466997bb42aaaf719ece141047820e6b34531e1670dc1852a453648f0f556112778061016f6000396000f3006080604052600436106100da5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633e3d64e281146100df5780633f4ba83a146101065780635c975abb1461011d5780635fd8c7101461014657806366b567da1461015b578063715018a614610170578063819abe80146101855780638456cb59146101ad5780638da5cb5b146101c257806398764f22146101f3578063b23d48541461021e578063d0db50831461023f578063da26663a14610254578063e4bdaa6114610272578063f2fde38b1461028d575b600080fd5b3480156100eb57600080fd5b506100f46102ae565b60408051918252519081900360200190f35b34801561011257600080fd5b5061011b6102be565b005b34801561012957600080fd5b50610132610334565b604080519115158252519081900360200190f35b34801561015257600080fd5b5061011b610344565b34801561016757600080fd5b506100f4610399565b34801561017c57600080fd5b5061011b610436565b34801561019157600080fd5b5061011b600160a060020a036004351661ffff602435166104a2565b3480156101b957600080fd5b5061011b6104cb565b3480156101ce57600080fd5b506101d7610546565b60408051600160a060020a039092168252519081900360200190f35b3480156101ff57600080fd5b5061011b63ffffffff6004351667ffffffffffffffff60243516610555565b34801561022a57600080fd5b5061011b600160a060020a0360043516610592565b34801561024b57600080fd5b5061011b6105d8565b34801561026057600080fd5b506100f463ffffffff6004351661099f565b61011b61ffff60043516600160a060020a0360243516610a51565b34801561029957600080fd5b5061011b600160a060020a0360043516610ced565b60035467ffffffffffffffff1690565b600054600160a060020a031633146102d557600080fd5b60005460a060020a900460ff1615156102ed57600080fd5b6000805474ff0000000000000000000000000000000000000000191681556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b339190a1565b60005460a060020a900460ff1681565b600054600160a060020a0316331461035b57600080fd5b60008054604051600160a060020a0390911691303180156108fc02929091818181858888f19350505050158015610396573d6000803e3d6000fd5b50565b600080805b60035467ffffffffffffffff168110156104305760035467ffffffffffffffff68010000000000000000909104168101600090815260026020526040902054600160a060020a03163314156104285760035468010000000000000000900467ffffffffffffffff16810160009081526002602052604090205460a060020a900461ffff1691909101905b60010161039e565b50919050565b600054600160a060020a0316331461044d57600080fd5b60008054604051600160a060020a03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600054600160a060020a031633146104b957600080fd5b6104c7826001836000610d0d565b5050565b600054600160a060020a031633146104e257600080fd5b60005460a060020a900460ff16156104f957600080fd5b6000805474ff0000000000000000000000000000000000000000191660a060020a1781556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff6259190a1565b600054600160a060020a031681565b600054600160a060020a0316331461056c57600080fd5b63ffffffff909116600090815260046020526040902067ffffffffffffffff9091169055565b600054600160a060020a031633146105a957600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6105e061121d565b600080600080600080600060149054906101000a900460ff1615151561060557600080fd5b600354600067ffffffffffffffff9091161161066b576040805160e560020a62461bcd02815260206004820152601060248201527f6e6f7468696e6720746f20686174636800000000000000000000000000000000604482015290519081900360640190fd5b610673610ec1565b965043876080015165ffffffffffff161015156106da576040805160e560020a62461bcd02815260206004820152601e60248201527f43616e2774206861746368206f6e207468652073616d6520626c6f636b2e0000604482015290519081900360640190fd5b600360109054906101000a900467ffffffffffffffff1667ffffffffffffffff16610710886080015165ffffffffffff16610f95565b019550600094505b866020015161ffff168510156108f05785604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106107775780518252601f199092019160209182019101610758565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206001900495508593506107b684610fa9565b604088015162010000909504949093506107d590859061ffff16610fb6565b60608801516001548951604080517f6b3559e1000000000000000000000000000000000000000000000000000000008152600160a060020a039283166004820152631000000060ff8a16026201518042041760100286176101000261ffff909516949094177a0100000000000000000000000000000000000000000000000000000264010000000090990479ffffffffffffffffffffffffffffffffffff000000000000000081169990991760248501819052905194965094501691636b3559e1916044808201926020929091908290030181600087803b1580156108b957600080fd5b505af11580156108cd573d6000803e3d6000fd5b505050506040513d60208110156108e357600080fd5b5050600190940193610718565b6108f86110c0565b60038054600167ffffffffffffffff700100000000000000000000000000000000808404821692909201160277ffffffffffffffff0000000000000000000000000000000019909116179055865160208089015160408051600160a060020a03909416845261ffff9091169183019190915280517f226357a480bcab31fbd8f2663fe2a14c625d8bab5c1cc23f15afe0b914732cdf9281900390910190a150505050505050565b6000808080635c097fc0421015610a00576040805160e560020a62461bcd02815260206004820152601b60248201527f5468652073616c65206861736e27742073746172746564207965740000000000604482015290519081900360640190fd5b63ffffffff851660009081526004602052604081205493508311610a2357600080fd5b50506202a30042635c097fbf190104604681016064811015610a485760648382020492505b50909392505050565b6000805460a060020a900460ff1615610a6957600080fd5b610a768361ffff1661099f565b905034811115610ad0576040805160e560020a62461bcd02815260206004820152601660248201527f416d6f756e74207061696420697320746f6f206c6f7700000000000000000000604482015290519081900360640190fd5b8261ffff1660011415610af057610aeb336001600086610d0d565b610c45565b8261ffff1660021415610b0b57610aeb336005600086610d0d565b8261ffff1660031415610b3457610b2633600a600086610d0d565b610aeb33600a600086610d0d565b8261ffff1660041415610b4f57610aeb33600a600186610d0d565b8261ffff1660051415610b9457610b6a33600a600186610d0d565b610b7833600a600086610d0d565b610b8633600a600086610d0d565b610b2633600a600086610d0d565b8261ffff1660061415610bf557610baf336003600286610d0d565b610bbd33600a600186610d0d565b610bcb33600a600186610d0d565b610bd933600a600186610d0d565b610be733600a600186610d0d565b610aeb336007600186610d0d565b6040805160e560020a62461bcd02815260206004820152600b60248201527f496e76616c696420736b75000000000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a03821615801590610c665750600160a060020a0382163314155b15610ca557604051600160a060020a038316906014830480156108fc02916000818181858888f19350505050158015610ca3573d6000803e3d6000fd5b505b6040805133815261ffff8516602082015280820183905290517fbac9694ac0daa55169abd117086fe32c89401d9a3b15dd1d34e55e0aa4e47a9d9181900360600190a1505050565b600054600160a060020a03163314610d0457600080fd5b610396816111a0565b6040805160a081018252600160a060020a03958616815261ffff9485166020808301918252948616828401908152938616606083019081524363ffffffff16608084019081526003805467ffffffffffffffff808216680100000000000000009092048116919091018116600090815260029099529590972093518454935196519251915173ffffffffffffffffffffffffffffffffffffffff1990941699169890981775ffff0000000000000000000000000000000000000000191660a060020a958816959095029490941777ffff000000000000000000000000000000000000000000001916760100000000000000000000000000000000000000000000948716949094029390931779ffff0000000000000000000000000000000000000000000000001916780100000000000000000000000000000000000000000000000096909516959095029390931779ffffffffffffffffffffffffffffffffffffffffffffffffffff167a01000000000000000000000000000000000000000000000000000065ffffffffffff9092169190910217909255815467ffffffffffffffff198116908216600101909116179055565b610ec961121d565b5060035468010000000000000000900467ffffffffffffffff16600090815260026020908152604091829020825160a0810184529054600160a060020a038116825260a060020a810461ffff9081169383019390935276010000000000000000000000000000000000000000000081048316938201939093527801000000000000000000000000000000000000000000000000830490911660608201527a01000000000000000000000000000000000000000000000000000090910465ffffffffffff16608082015290565b610100600019438390030181900402014090565b601e61ffff919091160690565b600080821515610fd757606463ffffffff85160663ffffffff16905061107e565b8260011415610ffa57601463ffffffff85160660500163ffffffff16905061107e565b826002141561101d57600563ffffffff851606605f0163ffffffff16905061107e565b826003141561102e5750606361107e565b6040805160e560020a62461bcd02815260206004820152601560248201527f496e76616c6964206d696e696d756d5261726974790000000000000000000000604482015290519081900360640190fd5b605081101561109057600091506110b9565b605f8110156110a257600191506110b9565b60638110156110b457600291506110b9565b600391505b5092915050565b600354600067ffffffffffffffff9091161161114c576040805160e560020a62461bcd02815260206004820152602360248201527f747279696e6720746f20706f704861746368282920616e20656d70747920737460448201527f61636b0000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600380546fffffffffffffffff00000000000000001967ffffffffffffffff19821667ffffffffffffffff928316600019018316179081166001680100000000000000009283900484160190921602179055565b600160a060020a03811615156111b557600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152905600a165627a7a723058205e05bf5cad345f31f0014e4d18815fec6dc38e92d01f24037c39a31b5d6589620029


   Swarm Source:
bzzr://5e05bf5cad345f31f0014e4d18815fec6dc38e92d01f24037c39a31b5d658962
Block Age transaction Difficulty GasUsed Reward
Block Age Uncle Number Difficulty GasUsed Reward
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.