Реклама вашего контракта Кабинет инвестора
Меню
Появились вопросы или есть предложения?
Напишите нам в 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 От кого Кому Сумма
Вчера 19:56 7245341 0xad1e79600e5bbba31c3f0d501d4557491718ffce1f8cbf7c7ef34f938fbf6550 0x55f74949a15ce98c9e9d8ebbdd774d5d7a25b473 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 19:56 7245341 0x2194f55cbc78cf205408dd57d3821a8866fd9a0295d63a54b6463dec436323c5 0x1e849ad655f7f364c4022bd8129f51083570d95f 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 19:56 7245341 0x2eeefb5bbb7b2c4df1c51ba9d67c1e3f0473fa18555c58613ab055dbb39c4303 0x03014be565459aa0829f2641935949d7be8b1ed9 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 19:56 7245340 0xbb03dc9f5ae7bd681fd81c1e2100e305e55048ec110527ff90ce275b061035f4 0x7f4d43c46073f656ff231a3a6bf3170043f731f3 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 19:56 7245337 0x9f6892195d7649d58d965171989e2459793bc7f86dd0cb08b652ea436b7492a8 0xa6c58da995d30a3562d2e81eb06c42cfb5ffefd7 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 19:51 7245323 0xbb672cb8b097f2dad4f270d69cec86e70b7e14f65d368f9fc9a0a32b769fd5ce 0x9aca21d4c170c80610593640ca3f1afd23a19562 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 1.2 Ether
Вчера 19:21 7245229 0xb0e1b9004ce636f5dabbba8be5326bcb5a9ffc511c5aea887b52678e24c4400c 0xf921f632516c5805720204eacef0a6d525b8f724 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 19:18 7245221 0x83d4833b97a43dcce803fe8fe361da359345ef7f7b6620ccc39b61f313b84eab 0xbbdb96af04f1c3ef1e804812149f2f3512b4a130 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.017 Ether
Вчера 11:09 7243811 0x444c64858ad4888a6603a1a92303ee08e5bf687531ad7695718712c865f3df8c 0x6ba5835665a95462c414b5fad64782444402951e 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 11:09 7243811 0x684b36c36e423aa5ebd11379bbfda1a44bca0f59f4123d9bb00bd0851cd31bd7 0xc92d7f1fa2938c74b590f4495e53cb35b98c2d2a 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 11:08 7243807 0x6c47ac51525e980ce3fa77008cac4ae085b31e50013bf9742cf1d6a2eea70f48 0xf862c9413f2cc21ebfda534ecfa6df4f59f0b197 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.33 Ether
Вчера 05:19 7242791 0xb3d43a871f170c849282aeb2400a14d8e2665ffd8e033518fb960a0af4838814 0x555c6cdd6f1a4b6c3db8018b8e9c4ca9ed2018ae 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 05:19 7242791 0x4565fcebdcd5df265ff2ebbd3007bc20903472fd58f44cec51d88a0a32399942 0x0d518269cfd6044b839927192ed35502055785e9 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 05:18 7242786 0x206c7f87aa81a191641fb1d53eaf1808863c5f05c420f830b5f59a63ae7cbd7c 0x03014be565459aa0829f2641935949d7be8b1ed9 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 05:18 7242785 0x0dd507124d0b6733e18af2cd9e2805208bb40e51c97469865d360399969e788e 0x13fb97da9d2407da6dbc2d6c175b51d0f5d9d903 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.017 Ether
Вчера 05:18 7242785 0x3d5c91124c8e79b63db19f58567e065eb4da0ff12dc4da9091488e45e4013ccf 0x13fb97da9d2407da6dbc2d6c175b51d0f5d9d903 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.017 Ether
Вчера 05:17 7242783 0x26e6cf4ef23816c1a51e458b8399386d3112d1918a4d033850135ab1af88e882 0x13fb97da9d2407da6dbc2d6c175b51d0f5d9d903 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.017 Ether
Вчера 04:56 7242721 0xb4d180a0f608f64cf26dcd1ee5359e692ceb4c885af278c7b895b66463c3431e 0x1e849ad655f7f364c4022bd8129f51083570d95f 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 04:52 7242709 0x62f1d2ecacf23c7eb92cc2a64d2f62b4402d3cddc177eb3589c6bfd35a3287ad 0xc8a974a97f6a7f57b6ce09aed5905d5547039f11 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.085 Ether
Вчера 04:29 7242648 0xc2bf5044ec3e7158133265910cf4b3edfb59f69bfe082c21e6f1ad1dc1cdf0ab 0x55f74949a15ce98c9e9d8ebbdd774d5d7a25b473 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 04:29 7242644 0x0677293475bf17bd4ae214e680d0d273d9f95254a4dc973fd3753d460dc5935a 0x6eac7d87a9f2ad5c8c03c79e71b9038468043780 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.017 Ether
Вчера 04:17 7242610 0x32152628bac02e3458cbb83d93f8dc4a9947fd1840c4020414ba837d59311f35 0xa6c58da995d30a3562d2e81eb06c42cfb5ffefd7 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 04:07 7242573 0x8d18b933fcba55ee330633c3295ffdeaf464a6cdcc62d517698581b30901eacd 0x6eac7d87a9f2ad5c8c03c79e71b9038468043780 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.017 Ether
Вчера 02:43 7242310 0xb76fd4ca3c25c7b27570eed63f185e8be130500327dd089e2497bc7a3b96a192 0x7f4d43c46073f656ff231a3a6bf3170043f731f3 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0 Ether
Вчера 02:41 7242305 0xf22f4dac2e1f3ff7cc0f7b7ccb44fd9b9cd245b1603c95fa1f9eb797ce4198fe 0x0bca2e181430c180de7ba43b6099fca311fa99b3 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0.085 Ether
Дата Блок parentTxHash От кого Кому Сумма
13 фев. 00:52 7212614 0x6409a22fe407f68701266472c7dc60974d4ab90647f241ac70b75e6bfef7ecb9 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x5d7f92c45c2b6a1711a0a1a7b7f6608437d17e76 0.0165 Ether
13 фев. 00:50 7212611 0x11ec6fbb2cbfbb6bcba93d5ec755235538869c9e9ca88f639022da77d7e7a53a 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x5d7f92c45c2b6a1711a0a1a7b7f6608437d17e76 0.0165 Ether
13 фев. 00:46 7212601 0x2a76ce4a1989f159f90d8a91154d488e7f2b7741f6510307f5d596e4abb09a22 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x3622af90ab6234d8c4fa802fe69f29d54f49f95b 0.0165 Ether
13 фев. 00:38 7212578 0xd94c822f46cee7e951b9fd7c395b36c88923843fdc38394055dfe473c82ad968 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x3622af90ab6234d8c4fa802fe69f29d54f49f95b 0.0165 Ether
13 фев. 00:37 7212576 0xb87e261702ae5485fed1ea8e5e906d01c3161864ba63ec87a0ec862f917c1cdd 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x3622af90ab6234d8c4fa802fe69f29d54f49f95b 0.0165 Ether
12 фев. 06:47 7209402 0x491f2f8c7e7ae6696fd9cf4a548d62def125121418bdb720bbcb72e2e045e1e8 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0xab7c859ba9c82d6120e48fb8c6194c724408e244 0.0165 Ether
10 фев. 16:37 7202737 0x18bdd24a7975bd662e3ccb1bd677a46155a0e47e3557be02df75c3b926e98f47 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00085 Ether
10 фев. 09:40 7201502 0x160cedc07c9d18b05d8f21c6126495c27995b87be56ee438b54ff28c90a94039 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.0165 Ether
10 фев. 09:29 7201463 0x1e1dfdc1be32cfc87597e2c994407ea6eaee6c961ea5a55c229dbf9f869e4cf1 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.0165 Ether
10 фев. 09:27 7201461 0x302f13f203d7ed6930d34306ce2d28a7f69adc605a4dff4ea3cc293ee683cc81 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.0165 Ether
10 фев. 09:05 7201397 0xd717d4a63bc4feda70cec5ef490997fefad7bde4a878d4551719c0db537a3a16 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.0165 Ether
10 фев. 09:05 7201395 0xf052341a1c072a531574a9abbcabb9028094c752462a563918e9051a617de749 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.0165 Ether
9 фев. 21:02 7199035 0xb01f158332c0060f8ed0c6b8810896969cdccd3c6cade986fa0fe932f6d96995 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00425 Ether
9 фев. 20:57 7199016 0xea2f530f75a3088ab8b0e34b6dd4c97ca23e18a8896e80be442d8f2cb397511d 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00425 Ether
7 фев. 21:59 7189379 0xd8d65e6deca7d26aa58302e65a2a5f88e4315cfff2c0ad708179e12fa95c5757 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00425 Ether
7 фев. 21:59 7189377 0x29af9e117e1d878d80e6025c2b2072307d6a364a3608b5997b76d74426acf2aa 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00425 Ether
7 фев. 21:57 7189375 0xb3e9ba2c2b78a123e31b6f297b7eea9f0f90e861bae05413a98b027d81b7278e 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00425 Ether
7 фев. 21:50 7189351 0x2aa1362e273f9edbef47e6dcbe22877a013d5ca28003e3998242042e74700792 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.00425 Ether
7 фев. 20:44 7189134 0x63ba621e805d8015557d3869f2016c24a7607f2f985950b4bdef89b40d081b85 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.02935 Ether
7 фев. 16:34 7188265 0xf53e9a9c5b25a2a01aae6a06688233d72b58b5cf01037147db664929147a1431 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.02935 Ether
7 фев. 14:43 7187897 0x4ab9f8d9a748aa6f7e4d3fa2d42fe0a34067fb0e3ca90ef0aee873faf270d5b0 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.02935 Ether
6 фев. 19:51 7184041 0xef10350fa30d6b111ea0fdd93acaf214844e717f284842a2892958eebd09fe8e 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x3622af90ab6234d8c4fa802fe69f29d54f49f95b 0.1495 Ether
6 фев. 06:51 7181420 0xd8b575be30ff6a32f059ce10871d7dccefb4235f8a5fcdf964ddf1dcc6072dba 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.0165 Ether
6 фев. 06:28 7181350 0x857eeeaa597f0ec1e9734bb7e91e1a84f8da223d47e91f2b908abb2c3a957894 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.0165 Ether
6 фев. 06:21 7181320 0x0f716fca7f11c3124eb43adb016d2921ebbbbd40ea3723274f66116f9de548f5 0x75d745eaea0ab0a8c9542959311c1c3166f6567d 0x9e6033fb9bc60653266d35275e764a0b1e0dca4b 0.0165 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);
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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