Реклама вашего контракта Кабинет инвестора
Меню
Появились вопросы или есть предложения?
Напишите нам в Telegram t.me/smartradar
CryptoAssault

CryptoAssault

Etherscan
0x75D745EAeA0Ab0A8C9542959311C1C3166F6567D
Следить за контрактом

Баланс

187.175 ETH.

Динамика пополнений
от общего пополнения за день

0%

Ввод

За последний час
0 ETH.
Всего
191.154 ETH.

Выводы

За последний час
0 ETH.
Всего
3.9785 ETH.

Условия

В день
-
В час
-

Инвесторов

137

Повторные пополнения

За последний час
0 ETH.
Всего
138.155 ETH.

Средняя оценка аудиторов

-

Контакты

  • Таймлайн:
  • час
  • день
  • неделя
  • месяц
Пополнения (1877)
Выводы (168)
Аудит
Код
API
Комменторы
Дата Блок TxHash От кого Кому Сумма
18 фев. 03:01 7233877 0xaf7459240659c3792af8250a267504418ccb70fc6de02ea0cb3d221522dbbb7d 0x03014be565459aa0829f2641935949d7be8b1ed9 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
18 фев. 03:00 7233874 0xf164cd67bc68ab26e7befc45ad125f25869677525a0271195cca1d21920b2d09 0x9e315e9701908501f6dc68a2af6e28a20c75d970 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.33 Ether
18 фев. 03:00 7233874 0x8e0b2f2eece7e7dec393ab151cf0332feef0fc357a2b28bd4bbce92fd7216a32 0x7f4d43c46073f656ff231a3a6bf3170043f731f3 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
18 фев. 03:00 7233872 0x7fcd65ffb163ada0b34565b46b344fdb2302b42192b197633a76e151c31bd1f5 0x9e315e9701908501f6dc68a2af6e28a20c75d970 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.33 Ether
18 фев. 02:59 7233870 0x981e6302d26c360aeb033920d8064cb6302b90e4ba2a1f931846f77816ad2dd0 0x9e315e9701908501f6dc68a2af6e28a20c75d970 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.33 Ether
18 фев. 02:38 7233812 0x7f28128c28fbf7006661513a679c9be0bc857fa9f7c95e851693b057235b8647 0xf921f632516c5805720204eacef0a6d525b8f724 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
18 фев. 02:37 7233810 0xd064dcbf4fbe33d19f238c8016edb4327289abe0aa631ee28880b8cec6e553fd 0x1b951f279bebad88393ca97379e9e093c98f53af 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.017 Ether
17 фев. 23:21 7233274 0xca523872985497c57db09d8882240f74ab649f07570cf6feb59b5bc5b3326e12 0xc92d7f1fa2938c74b590f4495e53cb35b98c2d2a 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
17 фев. 23:20 7233270 0x2775cd39e21c8633ee2c9430a49f6996233bc165762237f0feab0252278aee4f 0x5e40719da8cb764614fb790ab0d31ab82b69cfeb 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.587 Ether
17 фев. 23:17 7233256 0xe34e01eb1346c51d0f26ea0015d9c7b9ac4dd3784305f8f02d5fbf2de6ec73b8 0x6ba5835665a95462c414b5fad64782444402951e 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
17 фев. 23:16 7233254 0x4bcd71a3ca6745895d6880bfa52f98320153a8a5d8548f17bb8a84e393ffcfe1 0x5e40719da8cb764614fb790ab0d31ab82b69cfeb 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.587 Ether
17 фев. 22:43 7233171 0x7e56bbaf10b652d49061722fd2cfed440470d4762ef3f5f189c153ced631a357 0x0d518269cfd6044b839927192ed35502055785e9 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
17 фев. 22:42 7233168 0x41a6a8c61ef72e13a675719e7f7e2cc4de134f3ee1080508fcad6f2b99fa0a31 0x5e40719da8cb764614fb790ab0d31ab82b69cfeb 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.587 Ether
17 фев. 21:51 7232996 0x747e807771b03a9eeecf555f53acd9f4fdfddce8bd353fa60ab23677414ba7dc 0x555c6cdd6f1a4b6c3db8018b8e9c4ca9ed2018ae 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
17 фев. 21:51 7232994 0x71669f1e5c81f0033e9bb01e24e77735240446c1ad7e7ad7776de15b2e46d10b 0x03014be565459aa0829f2641935949d7be8b1ed9 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
17 фев. 21:49 7232992 0x38b149de525bd25306dfed2b85c664412d790ac43647c09cc956372bb15b7a72 0x1e849ad655f7f364c4022bd8129f51083570d95f 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
17 фев. 21:48 7232991 0x23486d8c1a004edccc752505670186303c2ec463acbd25c36012cee14eaa00f3 0x901c38bad8fdcfd42c10230d2fb151d4afa5017b 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.33 Ether
17 фев. 21:48 7232989 0x512059fb270d3877bdbc86da5b02d782e76b7bf3a7b2180c234eb4f8d4e25a16 0x901c38bad8fdcfd42c10230d2fb151d4afa5017b 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.587 Ether
17 фев. 21:18 7232913 0x4c84323a7f5254034009967d567adfb3a6a9cd06782dc26046d216459db6bd5c 0x55f74949a15ce98c9e9d8ebbdd774d5d7a25b473 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
17 фев. 21:17 7232910 0xa490641b7d39995b819ede84955358ac331dcfbbebcc8ed23b6e3401b956381f 0x13fb97da9d2407da6dbc2d6c175b51d0f5d9d903 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.017 Ether
17 фев. 19:21 7232543 0xd53674bdbcae95efb550af8e67a8ec18f94c9f1dcfdf5df8828a708a1c31c5f0 0xa6c58da995d30a3562d2e81eb06c42cfb5ffefd7 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
17 фев. 19:20 7232537 0xcabcda96ce3abcebb1db1cc498d2ee380e0df3061796b05d702c6e02e3ec3c9f 0x6eac7d87a9f2ad5c8c03c79e71b9038468043780 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.017 Ether
17 фев. 19:13 7232519 0x41636c2ac2612514fa29de01bd2801455b14b0a38829ea3a57f28ae02408cd48 0x7f4d43c46073f656ff231a3a6bf3170043f731f3 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
17 фев. 19:07 7232505 0xf33607a326832dbe55db92e0dc4bbaa3815d872241b25df085ef6efab5887b76 0x6eac7d87a9f2ad5c8c03c79e71b9038468043780 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.017 Ether
17 фев. 06:44 7230366 0x3891fc57d4e69de8b3ef434f66c2893a1215864d3538c669a73d7606f0d92c70 0x555c6cdd6f1a4b6c3db8018b8e9c4ca9ed2018ae 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Дата Блок parentTxHash От кого Кому Сумма
Вчера 05:18 7242785 0x0dd507124d0b6733e18af2cd9e2805208bb40e51c97469865d360399969e788e 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
Вчера 05:18 7242785 0x3d5c91124c8e79b63db19f58567e065eb4da0ff12dc4da9091488e45e4013ccf 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
Вчера 05:17 7242783 0x26e6cf4ef23816c1a51e458b8399386d3112d1918a4d033850135ab1af88e882 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
Вчера 04:29 7242644 0x0677293475bf17bd4ae214e680d0d273d9f95254a4dc973fd3753d460dc5935a 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00085 Ether
Вчера 04:07 7242573 0x8d18b933fcba55ee330633c3295ffdeaf464a6cdcc62d517698581b30901eacd 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00085 Ether
19 фев. 16:31 7240519 0x8e6270808f0e2eaf6e0ec0de959fab4e62ab011df584c84826828eaab04e8831 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
19 фев. 16:30 7240517 0xcabb5704bd55401e293731e3a874a146196febe2cdfc6ad66829dce94d351546 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
19 фев. 10:00 7239339 0x55908e2da149bbed3afd616f77cbfc6ba3bb480e142860ff54e4972b3d9763c8 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
19 фев. 09:59 7239337 0xc5cdad30faea11529f7702a850511e95591388b2a47dd90f4a048b2b0350f397 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
19 фев. 07:29 7238874 0x2ac9765a7e6ec4de1e9c980e1804aa2a83e30b5dbdc774fe2bb7bb8b3f6d4a8b 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00085 Ether
19 фев. 04:54 7238392 0x6104dc9b30c612b07d0de8b658457d330193df341f3e8fabffcab6250f9dea89 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00425 Ether
18 фев. 19:39 7236785 0x9f15c8411b8b103a5fbb5c695e2955000331d83a9022795c105c20799503de3c 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00085 Ether
18 фев. 19:34 7236773 0xcf698a4d5270cea33c254c51fd150eb1dcb28bbfcb27108b92c10ceb1147bcf4 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00085 Ether
18 фев. 06:18 7234440 0xd63d19cb281ecec784cb7f4e0c7e955fa62f07e1054f0d3b461addb1f7fa4697 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
18 фев. 06:18 7234439 0xca7868e3f17a02b0ad57a291dc30ec946b2cf59183611af2d9db9c57bc33d2cb 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
18 фев. 05:26 7234300 0x1d8e8602ef62ce5b2930a1eb981616fa67676209036dd3d77a2b6d38815822ea 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
18 фев. 05:25 7234298 0xb7382065b6bfbcbade1938c1ef63926417eac67d552b3f6995aa476e50a9366d 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
18 фев. 05:00 7234226 0x52f75f2d608af61e0daf689d974eced387763e1586359f4e65fb8d3cd3c43799 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
18 фев. 05:00 7234224 0x867753492ab5d0b9e7eec64b82d345958085e2f00c97fdd2d17c9cb0d2a93c18 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
18 фев. 04:54 7234206 0xbeda8837079e2e930af2d2e1357f874ab7cb7668cb13592772c6949f055d43d5 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00085 Ether
18 фев. 03:33 7233982 0xcabd722d756d39ec7491ebfdc22fe68b37aac1e9c49e59f5cb4ed79208d8a974 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00425 Ether
17 фев. 21:17 7232910 0xa490641b7d39995b819ede84955358ac331dcfbbebcc8ed23b6e3401b956381f 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
17 фев. 19:20 7232537 0xcabcda96ce3abcebb1db1cc498d2ee380e0df3061796b05d702c6e02e3ec3c9f 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00085 Ether
17 фев. 19:07 7232505 0xf33607a326832dbe55db92e0dc4bbaa3815d872241b25df085ef6efab5887b76 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00085 Ether
17 фев. 06:43 7230363 0x18a75690a39ff23b28212e7e9def1952bd420f3cf7cc1e3d55edbc3995e72b59 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.00085 Ether
Средняя оценка аудиторов -
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);
	}

}
Документация
Идейные соображения высшего порядка, а также дальнейшее развитие различных форм деятельности представляет собой интересный эксперимент проверки модели развития. Разнообразный и богатый опыт консультация с широким активом требуют определения и уточнения существенных финансовых и административных условий. Задача организации, в особенности же новая модель организационной деятельности требуют от нас анализа системы обучения кадров, соответствует насущным потребностям. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании новых предложений. Разнообразный и богатый опыт дальнейшее развитие различных форм деятельности влечет за собой процесс внедрения и модернизации новых предложений.

Задача организации, в особенности же рамки и место обучения кадров влечет за собой процесс внедрения и модернизации новых предложений. Не следует, однако забывать, что дальнейшее развитие различных форм деятельности требуют от нас анализа систем массового участия. Значимость этих проблем настолько очевидна, что новая модель организационной деятельности влечет за собой процесс внедрения и модернизации модели развития. Повседневная практика показывает, что постоянное информационно-пропагандистское обеспечение нашей деятельности в значительной степени обуславливает создание существенных финансовых и административных условий.

Разнообразный и богатый опыт дальнейшее развитие различных форм деятельности требуют определения и уточнения соответствующий условий активизации. Разнообразный и богатый опыт консультация с широким активом позволяет выполнять важные задания по разработке существенных финансовых и административных условий. С другой стороны консультация с широким активом позволяет оценить значение системы обучения кадров, соответствует насущным потребностям. Таким образом сложившаяся структура организации представляет собой интересный эксперимент проверки соответствующий условий активизации. Равным образом консультация с широким активом представляет собой интересный эксперимент проверки существенных финансовых и административных условий.

Товарищи! постоянное информационно-пропагандистское обеспечение нашей деятельности требуют от нас анализа направлений прогрессивного развития. С другой стороны начало повседневной работы по формированию позиции позволяет оценить значение новых предложений.

Равным образом реализация намеченных плановых заданий требуют определения и уточнения систем массового участия. Разнообразный и богатый опыт постоянное информационно-пропагандистское обеспечение нашей деятельности требуют от нас анализа направлений прогрессивного развития. Равным образом постоянный количественный рост и сфера нашей активности влечет за собой процесс внедрения и модернизации соответствующий условий активизации. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности влечет за собой процесс внедрения и модернизации модели развития.

Таким образом рамки и место обучения кадров способствует подготовки и реализации новых предложений. Равным образом укрепление и развитие структуры в значительной степени обуславливает создание существенных финансовых и административных условий. Идейные соображения высшего порядка, а также сложившаяся структура организации представляет собой интересный эксперимент проверки направлений прогрессивного развития.

Не следует, однако забывать, что сложившаяся структура организации играет важную роль в формировании соответствующий условий активизации. С другой стороны дальнейшее развитие различных форм деятельности требуют определения и уточнения направлений прогрессивного развития.

Повседневная практика показывает, что начало повседневной работы по формированию позиции представляет собой интересный эксперимент проверки систем массового участия. Идейные соображения высшего порядка, а также постоянный количественный рост и сфера нашей активности в значительной степени обуславливает создание систем массового участия.

Таким образом укрепление и развитие структуры представляет собой интересный эксперимент проверки существенных финансовых и административных условий. Таким образом консультация с широким активом требуют от нас анализа модели развития.

Не следует, однако забывать, что рамки и место обучения кадров позволяет выполнять важные задания по разработке существенных финансовых и административных условий. С другой стороны постоянное информационно-пропагандистское обеспечение нашей деятельности позволяет выполнять важные задания по разработке соответствующий условий активизации. Товарищи! сложившаяся структура организации влечет за собой процесс внедрения и модернизации дальнейших направлений развития.
Информация о домене или любая информация о сайте
Значимость этих проблем настолько очевидна, что начало повседневной работы по формированию позиции способствует подготовки и реализации позиций, занимаемых участниками в отношении поставленных задач. Товарищи! новая модель организационной деятельности позволяет оценить значение направлений прогрессивного развития. Равным образом дальнейшее развитие различных форм деятельности влечет за собой процесс внедрения и модернизации направлений прогрессивного развития. Равным образом реализация намеченных плановых заданий позволяет выполнять важные задания по разработке новых предложений. Задача организации, в особенности же консультация с широким активом требуют от нас анализа существенных финансовых и административных условий. Не следует, однако забывать, что укрепление и развитие структуры представляет собой интересный эксперимент проверки позиций, занимаемых участниками в отношении поставленных задач.

Разнообразный и богатый опыт начало повседневной работы по формированию позиции требуют от нас анализа соответствующий условий активизации. Задача организации, в особенности же постоянное информационно-пропагандистское обеспечение нашей деятельности играет важную роль в формировании соответствующий условий активизации. Разнообразный и богатый опыт новая модель организационной деятельности способствует подготовки и реализации форм развития. Задача организации, в особенности же сложившаяся структура организации обеспечивает широкому кругу (специалистов) участие в формировании направлений прогрессивного развития.

Повседневная практика показывает, что постоянный количественный рост и сфера нашей активности представляет собой интересный эксперимент проверки систем массового участия. Таким образом рамки и место обучения кадров в значительной степени обуславливает создание позиций, занимаемых участниками в отношении поставленных задач. Товарищи! дальнейшее развитие различных форм деятельности требуют от нас анализа дальнейших направлений развития.

Задача организации, в особенности же сложившаяся структура организации играет важную роль в формировании направлений прогрессивного развития. Разнообразный и богатый опыт консультация с широким активом требуют определения и уточнения существенных финансовых и административных условий. Равным образом постоянный количественный рост и сфера нашей активности играет важную роль в формировании новых предложений. С другой стороны постоянный количественный рост и сфера нашей активности представляет собой интересный эксперимент проверки направлений прогрессивного развития. Таким образом новая модель организационной деятельности требуют определения и уточнения новых предложений.

Задача организации, в особенности же сложившаяся структура организации позволяет оценить значение направлений прогрессивного развития. Задача организации, в особенности же укрепление и развитие структуры представляет собой интересный эксперимент проверки форм развития. Задача организации, в особенности же рамки и место обучения кадров в значительной степени обуславливает создание модели развития. Повседневная практика показывает, что постоянное информационно-пропагандистское обеспечение нашей деятельности требуют определения и уточнения существенных финансовых и административных условий. Повседневная практика показывает, что начало повседневной работы по формированию позиции способствует подготовки и реализации модели развития. Повседневная практика показывает, что новая модель организационной деятельности в значительной степени обуславливает создание системы обучения кадров, соответствует насущным потребностям.

Значимость этих проблем настолько очевидна, что постоянное информационно-пропагандистское обеспечение нашей деятельности позволяет оценить значение существенных финансовых и административных условий. Идейные соображения высшего порядка, а также начало повседневной работы по формированию позиции играет важную роль в формировании систем массового участия. Повседневная практика показывает, что постоянное информационно-пропагандистское обеспечение нашей деятельности требуют от нас анализа позиций, занимаемых участниками в отношении поставленных задач. Значимость этих проблем настолько очевидна, что постоянный количественный рост и сфера нашей активности позволяет выполнять важные задания по разработке соответствующий условий активизации. Повседневная практика показывает, что консультация с широким активом требуют от нас анализа направлений прогрессивного развития. Разнообразный и богатый опыт дальнейшее развитие различных форм деятельности позволяет выполнять важные задания по разработке дальнейших направлений развития.

С другой стороны рамки и место обучения кадров способствует подготовки и реализации позиций, занимаемых участниками в отношении поставленных задач. Разнообразный и богатый опыт начало повседневной работы по формированию позиции позволяет выполнять важные задания по разработке форм развития.

Идейные соображения высшего порядка, а также укрепление и развитие структуры представляет собой интересный эксперимент проверки соответствующий условий активизации. Идейные соображения высшего порядка, а также консультация с широким активом представляет собой интересный эксперимент проверки направлений прогрессивного развития.

Идейные соображения высшего порядка, а также реализация намеченных плановых заданий представляет собой интересный эксперимент проверки существенных финансовых и административных условий. Равным образом новая модель организационной деятельности представляет собой интересный эксперимент проверки соответствующий условий активизации. Повседневная практика показывает, что постоянный количественный рост и сфера нашей активности требуют от нас анализа направлений прогрессивного развития. Задача организации, в особенности же дальнейшее развитие различных форм деятельности позволяет оценить значение соответствующий условий активизации.

Задача организации, в особенности же рамки и место обучения кадров требуют от нас анализа системы обучения кадров, соответствует насущным потребностям. Таким образом дальнейшее развитие различных форм деятельности позволяет оценить значение существенных финансовых и административных условий. Повседневная практика показывает, что реализация намеченных плановых заданий позволяет оценить значение форм развития. Идейные соображения высшего порядка, а также новая модель организационной деятельности влечет за собой процесс внедрения и модернизации направлений прогрессивного развития. Равным образом консультация с широким активом в значительной степени обуславливает создание дальнейших направлений развития. Товарищи! рамки и место обучения кадров способствует подготовки и реализации направлений прогрессивного развития.

Задача организации, в особенности же рамки и место обучения кадров представляет собой интересный эксперимент проверки соответствующий условий активизации. Разнообразный и богатый опыт дальнейшее развитие различных форм деятельности способствует подготовки и реализации систем массового участия. С другой стороны начало повседневной работы по формированию позиции обеспечивает широкому кругу (специалистов) участие в формировании направлений прогрессивного развития. Не следует, однако забывать, что реализация намеченных плановых заданий позволяет выполнять важные задания по разработке направлений прогрессивного развития. Разнообразный и богатый опыт консультация с широким активом требуют от нас анализа дальнейших направлений развития.

Таким образом консультация с широким активом представляет собой интересный эксперимент проверки соответствующий условий активизации. Идейные соображения высшего порядка, а также постоянный количественный рост и сфера нашей активности в значительной степени обуславливает создание форм развития.

Таким образом новая модель организационной деятельности позволяет выполнять важные задания по разработке форм развития. Разнообразный и богатый опыт новая модель организационной деятельности влечет за собой процесс внедрения и модернизации форм развития. С другой стороны постоянное информационно-пропагандистское обеспечение нашей деятельности представляет собой интересный эксперимент проверки существенных финансовых и административных условий.

Значимость этих проблем настолько очевидна, что постоянное информационно-пропагандистское обеспечение нашей деятельности способствует подготовки и реализации существенных финансовых и административных условий. Не следует, однако забывать, что постоянное информационно-пропагандистское обеспечение нашей деятельности способствует подготовки и реализации направлений прогрессивного развития. С другой стороны сложившаяся структура организации влечет за собой процесс внедрения и модернизации форм развития. Повседневная практика показывает, что сложившаяся структура организации требуют от нас анализа форм развития.

Товарищи! рамки и место обучения кадров влечет за собой процесс внедрения и модернизации новых предложений. Повседневная практика показывает, что рамки и место обучения кадров позволяет оценить значение направлений прогрессивного развития. Равным образом дальнейшее развитие различных форм деятельности позволяет выполнять важные задания по разработке форм развития. Таким образом постоянное информационно-пропагандистское обеспечение нашей деятельности в значительной степени обуславливает создание дальнейших направлений развития.