Contract Overview |  MCH_Presale
Balance: 0 Ether
Ether Value: $0
Transactions: 5085 txns
Misc:
Address Watch: Add To Watch List
Contract Creator: 0xe7af11370c3bab51230d8307454350bdf6d68f4aat txn 0x8681b619d42200b2cc5e0ac5169b033b1d28fd352f7597fac1521651ac24941f
 Latest 25 transactions from a total of 5085 transactions

TxHash Age From To Value [TxFee]
0x259ed178b35e4e096d532cda7c9e3188dcb585c3831eda903127720aeb92b6332 days 21 hrs ago0xe7af11370c3bab51230d8307454350bdf6d68f4a  IN   MCH_Presale0 Ether0.000196995
0x399c40125bdb14958ff49a56dd3db72ad7beb49b04ae553cf2238f765c3b3acf14 days 5 hrs ago0x05f3ba3a53be572a07cc5d54013810aa6da3cffe  IN   MCH_Presale0 Ether0.000084184
0x9fbe0b8debabc1d7e5ab9de81ee91c58e0478a1504ada88a60d01fa3dd2bc61a19 days 11 hrs ago0x416a2bdc3479d0e0bad1ff4e926d4401e7c941c8  IN   MCH_Presale0 Ether0.000185752
0x97a5fcce0e52fd4de7f8cb69811ff22ea0de02c71c41c5fc324bd16ffa763dc719 days 11 hrs ago0x416a2bdc3479d0e0bad1ff4e926d4401e7c941c8  IN   MCH_Presale0 Ether0.000185752
0x33ae72f85d3af02744b52612aea914649e3c6c231324023fad15143b8ca64c6e19 days 11 hrs ago0x416a2bdc3479d0e0bad1ff4e926d4401e7c941c8  IN   MCH_Presale0 Ether0.000185752
0x555e9aeef23fdc7dbd6009af432d1c8b6d57a4a38fba6f831a38737e5ba7e45142 days 7 hrs ago0x3f2360806442a4d7dc643a9e235a93a6ab1c5000  IN   MCH_Presale0 Ether0.000006354814
0xf1ffa3308793905784a76176fa544b3bf9ec429224dbc25820c471714b95ac3843 days 5 hrs ago0x793e193a27744025f8f60736eda8a863aca5b699  IN   MCH_Presale0 Ether0.000532668
0x26df5d3935e802996faa20b2d656d999f738f1fd6e7795e76b24f45cfe572f3b43 days 10 hrs ago0x573b23dad4741a6c746322eb5416abd51a4c7ecb  IN   MCH_Presale0 Ether0.0011319195
0x134dd365ccbd27893474a764738cf68a39a62e492e7b588c1db6dafadf35ebd743 days 11 hrs ago0xb08237d62eca2bc1e336ccf22dcc88e8a3214e8c  IN   MCH_Presale0 Ether0.0011319195
0xf3689f8ac24244671a57ac4963426e7e5c9683f199ad75e783be6952789058c843 days 11 hrs ago0xc474471670ad3680ec739d342e72d35355403c69  IN   MCH_Presale0 Ether0.0011319195
0xc1d0b7d98c88e4c652aa10aca772bcf4880a862a9ba2dfafbc8c4ae83c4fc13e43 days 11 hrs ago0x93340f248036e07dcf47c96f964a9a201c1d5383  IN   MCH_Presale0 Ether0.0011319195
0xec6202c4e618c90452ceb9ceac1df2b7a51d58a77f7bccdcbe150a7b27f8903643 days 11 hrs ago0xec94cb51585c7783a9104481dba8761422133838  IN   MCH_Presale0 Ether0.0011319195
0xb523242a64fdf7618e93147a1d5f2fea621d5489781be8e897a4e0efea47618643 days 11 hrs ago0x573b23dad4741a6c746322eb5416abd51a4c7ecb  IN   MCH_Presale0 Ether0.0009176073
0xbcd130ce06c67078d39ae79538509399b94764280fd20cae667a041c9da1ad1d43 days 11 hrs ago0x573b23dad4741a6c746322eb5416abd51a4c7ecb  IN   MCH_Presale0 Ether0.0012084195
0x0eb60b973fc869ff16bf630431c918e24063da7ffab892d897598be30102a7d443 days 11 hrs ago0xb08237d62eca2bc1e336ccf22dcc88e8a3214e8c  IN   MCH_Presale0 Ether0.0009176073
0xc27170ca4e029d905484470d686f09061baf9e51477f1bd467a4f61e7df73ab443 days 11 hrs ago0xb08237d62eca2bc1e336ccf22dcc88e8a3214e8c  IN   MCH_Presale0 Ether0.0012084195
0x41c279b9a1535d0392ecfaef1ddcb52be31f078134116915827475b4a86fe83d43 days 11 hrs ago0xc474471670ad3680ec739d342e72d35355403c69  IN   MCH_Presale0 Ether0.0009176073
0xca99ff21659cf6e9efa8d96193530c593012790e1540ae4aca4364070ef56b5643 days 11 hrs ago0xc474471670ad3680ec739d342e72d35355403c69  IN   MCH_Presale0 Ether0.0012084195
0x12c80249a330facf5007c785661ca4b5e5b3210130f4bbe8e82392a58c994a6643 days 11 hrs ago0x70e68fc54cf52215e875a667edef0cec30b5eb2e  IN   MCH_Presale0 Ether0.0011319195
0xe30268e5ae2d1f44c697faa18655fc76ec44ff21c32b4a46e17e3cb2bf9cc95843 days 11 hrs ago0x42232d71109bd15b226f06b99ee92125b72eaa2c  IN   MCH_Presale0 Ether0.0011319195
0x04eae7a4e567907d298858949255cfae1fcefd8d4db0010aa6903b7b9aff858943 days 11 hrs ago0xec94cb51585c7783a9104481dba8761422133838  IN   MCH_Presale0 Ether0.0009176073
0x5356339bb64acbbd368d5265c7d4eded929966f2405d104d3807dd143623040a43 days 11 hrs ago0xec94cb51585c7783a9104481dba8761422133838  IN   MCH_Presale0 Ether0.0012084195
0x03fd9567ba370b2bfb2012343286b27ce88d6c5cf88aed07971ff5408eec43d643 days 11 hrs ago0x70e68fc54cf52215e875a667edef0cec30b5eb2e  IN   MCH_Presale0 Ether0.0009176073
0xf9dc7f8d716912367ccd2e0c6ab0afa2d65a92aa41f92afb4bef63e614d9b82743 days 11 hrs ago0x70e68fc54cf52215e875a667edef0cec30b5eb2e  IN   MCH_Presale0 Ether0.0012084195
0x393ea2c6420d26d770e3720d71dd7b3716abddb3f343c2db1d3f3b3b20ecc14b43 days 12 hrs ago0x42232d71109bd15b226f06b99ee92125b72eaa2c  IN   MCH_Presale0 Ether0.0012080931
[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
 Latest 25 Internal Txns, Click here To View More View All
ParentTxHash Block Age From To Value
0x80f9da22c0b5fa47a63d0884e9a6a21ccb334df29a09785507cda6e259d07a9a643279072 days 17 hrs ago0x946048a75af11c300a274344887ec39452218b3d0xe7af11370c3bab51230d8307454350bdf6d68f4a35.704222117672495829 Ether
0xab256c924e4160e0c105cd4d0ac46018e536046183fb77122080c8479dae2f03642999873 days 4 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x40c9afd96646df172b6fa31211fb51bf5144081e0.000031221261836837 Ether
0xa949c413deb06677dad32a738cce5d73a5fec2a993538c9d9311e428c1fe4f8a642997773 days 4 hrs ago0x946048a75af11c300a274344887ec39452218b3d0xfa45c6991a2c3d74ada3a279e21135133ce3da8a0.00235377005848806 Ether
0xf6e434f01a654605913d5a7d385f9eaaf701c07b7391acf45c827313e8d768dd642959073 days 6 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x6c5f503e290bba6a659972da78715694797fbac40.000117520883268269 Ether
0x670b31985a62e8eed3becf6bc9930dd56b854743492777a58adaa485f1dbefe9642796273 days 12 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x5ad8f1fb5c25f2ac83bf26ca2b6d857037d6ba840.000767529163824232 Ether
0xc4f2fcbbf0448fb335a44459a78bb2e15d24ff6f0742d6463d54ac1de6e31120642689673 days 16 hrs ago0x946048a75af11c300a274344887ec39452218b3d0xcaff49b031e5099a54f5959dc931c27e366273690.00027635849798034 Ether
0x83e4c45e9f8bde79125dfa22167bd9a16861a47893a923e979d18970bb9106c3642673473 days 17 hrs ago0x946048a75af11c300a274344887ec39452218b3d0xf96c878bb8d36d8203fa2a358d770f1ae85a1d470.000056706459629636 Ether
0xdc20e02fed068677404eabf608d31f9b5f8d7c709765ebd07292cc802dca57e2642628173 days 19 hrs ago0x946048a75af11c300a274344887ec39452218b3d0xfa45c6991a2c3d74ada3a279e21135133ce3da8a0.000042947044652632 Ether
0xb10f69d2de12cc6f5c07ff081959d3c04c3c564fc63effc84407c67ac7044d15642206074 days 11 hrs ago0x946048a75af11c300a274344887ec39452218b3d0xfa7b07b6de964d022c832f20ced2dac16384b7aa0.000589297430622244 Ether
0x30eae0b46e72097c6aa5a3b702ebc6bdfc7aaefded07d540600f7a1a7b26f63b642196874 days 12 hrs ago0x946048a75af11c300a274344887ec39452218b3d0xfa7b07b6de964d022c832f20ced2dac16384b7aa0.000047119936254208 Ether
0x1cec5086ed2f1538d8524b3a2b69765c15fc838ec5a0e862f33021db8d781316642194374 days 12 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x431434d43cea4131650520cb105b90fe204fa39d0.000063161054912408 Ether
0x8990af91a3ae9aec187283b2c3add147f3cda60c13ecabb607b036be291fa785641835075 days 2 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x12f561c77e1e542b8d6f9de5f3e2faf03d87b3b80.00003725965242613 Ether
0x1588d281cfacec2e4195fdaa5cb3a5ac4d559f7af72b99f41370d13a427daff2641833375 days 2 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x6c5f503e290bba6a659972da78715694797fbac40.000262467736842824 Ether
0x650e955e98a51a24c17d0e38c57499824018418372312983807146a0f2bd888e641831575 days 2 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x6c5f503e290bba6a659972da78715694797fbac40.000054190227769198 Ether
0x506bf9db530d66a23af6b4cfb4ef9669a8c24544b0209bfae02fcbf2603a5463641615875 days 11 hrs ago0x946048a75af11c300a274344887ec39452218b3d0xaa24875b7bfd15364af1063f8c1330c53146b81f0.000070680592497302 Ether
0xd1113b96af97a3cc6d750c6d073f81035045ba8f8bdda41c9e880c531390b6bd641605275 days 11 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x2e1bc1abc2e86e3405766f6b39ed8fe388b344970.000058564601634346 Ether
0x70a9954c196321e4dafd5f0541279934b9350d38278185654966d152e39daba1641601875 days 11 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x2a3d897cd8cc82f310b53f4511ebdefca7f0232c0.000040742434896311 Ether
0x49583b65cd655393484b39d94a34b214bd9439eb9618c78ba977a2f5363a6f6a641591075 days 12 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x5ba3e11abf8c93186637847ec590fcd3aa588bd20.000033388657128154 Ether
0x54750d35119882b4e9a8f522f8ffbdb835ce7c83fd8203546cd2abd52bf8545a641588575 days 12 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x5ba3e11abf8c93186637847ec590fcd3aa588bd20.000022920115099777 Ether
0xcb5c94fdb955255fcf9fed3ddf4cd259fff3592663880f90d89a77a3523ec06c641582275 days 12 hrs ago0x946048a75af11c300a274344887ec39452218b3d0xaa764d0f94b0ebcf6eb0a29bc2fb19b48edd23350.011795271321073031 Ether
0xda4c5ea6476906133207132b6e06129e19ddd47f453d57fb96901bc61cb1fbb4641528375 days 14 hrs ago0x946048a75af11c300a274344887ec39452218b3d0xbcd2c48e447a45244ccefdb232b2f7b5f86f43bd0.000056682034275433 Ether
0x2bee68c508bfce829c2dc3bf52443ff62fad6c99c4e7159c5be12a799a8203ed641441275 days 18 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x8ddd99328f94489460ed8387a9bd6577a42fb3aa0.000026907286942602 Ether
0x075e9814ff52d118a66319984104e2d797ebe46a18fb7c7b18e3c4c7c1d55527641440775 days 18 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x8ddd99328f94489460ed8387a9bd6577a42fb3aa0.000157887577158355 Ether
0x1e3c2b4139eb22add1955ae9ddc4ed5dc112f133c9b95c719c9053d138461802641428175 days 18 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x3d3a8ce65e3595f60be146f5f05b42ad63c4be7c0.000013004904153729 Ether
0x9b2cf63a1bc252afb7e40472415548424ed7cfd21fb5bf9620e327f49a7229b0641424975 days 18 hrs ago0x946048a75af11c300a274344887ec39452218b3d0x3d3a8ce65e3595f60be146f5f05b42ad63c4be7c0.000014352468616973 Ether
[ Download CSV Export  ] 
Warning: The Compiled Contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity) SolidityCompiler Bugs.

Contract Source Code Verified (Exact Match)
Contract Name: HeroPresale
Compiler Text: v0.4.24+commit.e67f0147
Optimization Enabled: Yes
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

pragma solidity 0.4.24;

// File: contracts/lib/openzeppelin-solidity/contracts/access/Roles.sol

/**
 * @title Roles
 * @dev Library for managing addresses assigned to a Role.
 */
library Roles {
  struct Role {
    mapping (address => bool) bearer;
  }

  /**
   * @dev give an account access to this role
   */
  function add(Role storage role, address account) internal {
    require(account != address(0));
    role.bearer[account] = true;
  }

  /**
   * @dev remove an account's access to this role
   */
  function remove(Role storage role, address account) internal {
    require(account != address(0));
    role.bearer[account] = false;
  }

  /**
   * @dev check if an account has this role
   * @return bool
   */
  function has(Role storage role, address account)
    internal
    view
    returns (bool)
  {
    require(account != address(0));
    return role.bearer[account];
  }
}

// File: contracts/lib/openzeppelin-solidity/contracts/access/roles/MinterRole.sol

contract MinterRole {
  using Roles for Roles.Role;

  event MinterAdded(address indexed account);
  event MinterRemoved(address indexed account);

  Roles.Role private minters;

  constructor() public {
    minters.add(msg.sender);
  }

  modifier onlyMinter() {
    require(isMinter(msg.sender));
    _;
  }

  function isMinter(address account) public view returns (bool) {
    return minters.has(account);
  }

  function addMinter(address account) public onlyMinter {
    minters.add(account);
    emit MinterAdded(account);
  }

  function renounceMinter() public {
    minters.remove(msg.sender);
  }

  function _removeMinter(address account) internal {
    minters.remove(account);
    emit MinterRemoved(account);
  }
}

// File: contracts/lib/openzeppelin-solidity/contracts/introspection/IERC165.sol

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

  /**
   * @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/lib/openzeppelin-solidity/contracts/introspection/ERC165.sol

/**
 * @title ERC165
 * @author Matt Condon (@shrugs)
 * @dev Implements ERC165 using a lookup table.
 */
contract ERC165 is IERC165 {

  bytes4 private 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/lib/openzeppelin-solidity/contracts/math/SafeMath.sol

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

  /**
  * @dev Multiplies two numbers, reverts on overflow.
  */
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    // Gas optimization: this is cheaper than requiring '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;
    }

    uint256 c = a * b;
    require(c / a == b);

    return c;
  }

  /**
  * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
  */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b > 0); // Solidity only automatically asserts when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }

  /**
  * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b <= a);
    uint256 c = a - b;

    return c;
  }

  /**
  * @dev Adds two numbers, reverts on overflow.
  */
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a);

    return c;
  }

  /**
  * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
  * reverts when dividing by zero.
  */
  function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b != 0);
    return a % b;
  }
}

// File: contracts/lib/openzeppelin-solidity/contracts/utils/Address.sol

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

  /**
   * 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 account address of the account to check
   * @return whether the target address is a contract
   */
  function isContract(address account) 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(account) }
    return size > 0;
  }

}

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

/**
 * @title ERC721 Non-Fungible Token Standard basic interface
 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract IERC721 is IERC165 {

  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 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/lib/openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
contract IERC721Receiver {
  /**
   * @notice Handle the receipt of an NFT
   * @dev The ERC721 smart contract calls this function on the recipient
   * after a `safeTransfer`. This function MUST return the function selector,
   * otherwise the caller will revert the transaction. The selector to be
   * returned can be obtained as `this.onERC721Received.selector`. This
   * function MAY throw to revert and reject the transfer.
   * Note: the ERC721 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 transferred
   * @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/lib/openzeppelin-solidity/contracts/token/ERC721/ERC721.sol

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

  using SafeMath for uint256;
  using Address for address;

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

  // Mapping from token ID to owner
  mapping (uint256 => address) private _tokenOwner;

  // Mapping from token ID to approved address
  mapping (uint256 => address) private _tokenApprovals;

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

  // Mapping from owner to operator approvals
  mapping (address => mapping (address => bool)) private _operatorApprovals;

  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)'))
   */

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

  /**
   * @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 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
   * Reverts if the token ID does not exist.
   * @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) {
    require(_exists(tokenId));
    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
  {
    require(_isApprovedOrOwner(msg.sender, tokenId));
    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
  {
    // 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
  {
    transferFrom(from, to, tokenId);
    // solium-disable-next-line arg-overflow
    require(_checkAndCallSafeTransfer(from, to, tokenId, _data));
  }

  /**
   * @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) internal view returns (bool) {
    address owner = _tokenOwner[tokenId];
    return owner != address(0);
  }

  /**
   * @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 = IERC721Receiver(to).onERC721Received(
      msg.sender, from, tokenId, _data);
    return (retval == _ERC721_RECEIVED);
  }
}

// File: contracts/lib/openzeppelin-solidity/contracts/token/ERC721/IERC721Enumerable.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 IERC721Enumerable is IERC721 {
  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);
}

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

contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable {
  // Mapping from owner to list of owned token IDs
  mapping(address => uint256[]) private _ownedTokens;

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

  // Array with all token ids, used for enumeration
  uint256[] private _allTokens;

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

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

  /**
   * @dev Constructor function
   */
  constructor() public {
    // register the supported interface to conform to ERC721 via ERC165
    _registerInterface(_InterfaceId_ERC721Enumerable);
  }

  /**
   * @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 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);

    // To prevent a gap in the array, we store the last token in the index of the token to delete, and
    // then delete the last slot.
    uint256 tokenIndex = _ownedTokensIndex[tokenId];
    uint256 lastTokenIndex = _ownedTokens[from].length.sub(1);
    uint256 lastToken = _ownedTokens[from][lastTokenIndex];

    _ownedTokens[from][tokenIndex] = lastToken;
    // This also deletes the contents at the last position of the array
    _ownedTokens[from].length--;

    // 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

    _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);

    // 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/lib/openzeppelin-solidity/contracts/token/ERC721/IERC721Metadata.sol

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

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

contract ERC721Metadata is ERC165, ERC721, IERC721Metadata {
  // Token name
  string internal _name;

  // Token symbol
  string internal _symbol;

  // Optional mapping for token URIs
  mapping(uint256 => string) private _tokenURIs;

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

  /**
   * @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_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 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 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];
    }
  }
}

// File: contracts/lib/openzeppelin-solidity/contracts/token/ERC721/ERC721Full.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 ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata {
  constructor(string name, string symbol) ERC721Metadata(name, symbol)
    public
  {
  }
}

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

/**
 * @title ERC721Mintable
 * @dev ERC721 minting logic
 */
contract ERC721Mintable is ERC721Full, MinterRole {
  event MintingFinished();

  bool private _mintingFinished = false;

  modifier onlyBeforeMintingFinished() {
    require(!_mintingFinished);
    _;
  }

  /**
   * @return true if the minting is finished.
   */
  function mintingFinished() public view returns(bool) {
    return _mintingFinished;
  }

  /**
   * @dev Function to mint tokens
   * @param to The address that will receive the minted tokens.
   * @param tokenId The token id to mint.
   * @return A boolean that indicates if the operation was successful.
   */
  function mint(
    address to,
    uint256 tokenId
  )
    public
    onlyMinter
    onlyBeforeMintingFinished
    returns (bool)
  {
    _mint(to, tokenId);
    return true;
  }

  function mintWithTokenURI(
    address to,
    uint256 tokenId,
    string tokenURI
  )
    public
    onlyMinter
    onlyBeforeMintingFinished
    returns (bool)
  {
    mint(to, tokenId);
    _setTokenURI(tokenId, tokenURI);
    return true;
  }

  /**
   * @dev Function to stop minting new tokens.
   * @return True if the operation was successful.
   */
  function finishMinting()
    public
    onlyMinter
    onlyBeforeMintingFinished
    returns (bool)
  {
    _mintingFinished = true;
    emit MintingFinished();
    return true;
  }
}

// File: contracts/lib/openzeppelin-solidity/contracts/access/roles/PauserRole.sol

contract PauserRole {
  using Roles for Roles.Role;

  event PauserAdded(address indexed account);
  event PauserRemoved(address indexed account);

  Roles.Role private pausers;

  constructor() public {
    pausers.add(msg.sender);
  }

  modifier onlyPauser() {
    require(isPauser(msg.sender));
    _;
  }

  function isPauser(address account) public view returns (bool) {
    return pausers.has(account);
  }

  function addPauser(address account) public onlyPauser {
    pausers.add(account);
    emit PauserAdded(account);
  }

  function renouncePauser() public {
    pausers.remove(msg.sender);
  }

  function _removePauser(address account) internal {
    pausers.remove(account);
    emit PauserRemoved(account);
  }
}

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

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

  bool private _paused = false;


  /**
   * @return true if the contract is paused, false otherwise.
   */
  function paused() public view returns(bool) {
    return _paused;
  }

  /**
   * @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() public onlyPauser whenNotPaused {
    _paused = true;
    emit Paused();
  }

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

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

/**
 * @title ERC721 Non-Fungible Pausable token
 * @dev ERC721 modified with pausable transfers.
 **/
contract ERC721Pausable is ERC721, Pausable {
  function approve(
    address to,
    uint256 tokenId
  )
    public
    whenNotPaused
  {
    super.approve(to, tokenId);
  }

  function setApprovalForAll(
    address to,
    bool approved
  )
    public
    whenNotPaused
  {
    super.setApprovalForAll(to, approved);
  }

  function transferFrom(
    address from,
    address to,
    uint256 tokenId
  )
    public
    whenNotPaused
  {
    super.transferFrom(from, to, tokenId);
  }
}

// File: contracts/HeroAsset.sol

contract HeroAsset is ERC721Mintable, ERC721Pausable {

    uint16 public constant HERO_TYPE_OFFSET = 10000;

    string public tokenURIPrefix = "https://www.mycryptoheroes.net/metadata/hero/";
    mapping(uint16 => uint16) private heroTypeToSupplyLimit;

    constructor() public ERC721Full("MyCryptoHeroes:Hero", "MCHH") {}

    function setSupplyLimit(uint16 _heroType, uint16 _supplyLimit) external onlyMinter {
        require(heroTypeToSupplyLimit[_heroType] == 0 || _supplyLimit < heroTypeToSupplyLimit[_heroType],
            "_supplyLimit is bigger");
        heroTypeToSupplyLimit[_heroType] = _supplyLimit;
    }

    function setTokenURIPrefix(string _tokenURIPrefix) external onlyMinter {
        tokenURIPrefix = _tokenURIPrefix;
    }

    function getSupplyLimit(uint16 _heroType) public view returns (uint16) {
        return heroTypeToSupplyLimit[_heroType];
    }

    function mintHeroAsset(address _owner, uint256 _tokenId) public onlyMinter {
        uint16 _heroType = uint16(_tokenId / HERO_TYPE_OFFSET);
        uint16 _heroTypeIndex = uint16(_tokenId % HERO_TYPE_OFFSET) - 1;
        require(_heroTypeIndex < heroTypeToSupplyLimit[_heroType], "supply over");
        _mint(_owner, _tokenId);
    }

    function tokenURI(uint256 tokenId) public view returns (string) {
        bytes32 tokenIdBytes;
        if (tokenId == 0) {
            tokenIdBytes = "0";
        } else {
            uint256 value = tokenId;
            while (value > 0) {
                tokenIdBytes = bytes32(uint256(tokenIdBytes) / (2 ** 8));
                tokenIdBytes |= bytes32(((value % 10) + 48) * 2 ** (8 * 31));
                value /= 10;
            }
        }

        bytes memory prefixBytes = bytes(tokenURIPrefix);
        bytes memory tokenURIBytes = new bytes(prefixBytes.length + tokenIdBytes.length);

        uint8 i;
        uint8 index = 0;
        
        for (i = 0; i < prefixBytes.length; i++) {
            tokenURIBytes[index] = prefixBytes[i];
            index++;
        }
        
        for (i = 0; i < tokenIdBytes.length; i++) {
            tokenURIBytes[index] = tokenIdBytes[i];
            index++;
        }
        
        return string(tokenURIBytes);
    }

}

// File: contracts/lib/openzeppelin-solidity/contracts/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 private _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;
  }

  /**
   * @return the address of the owner.
   */
  function owner() public view returns(address) {
    return _owner;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(isOwner());
    _;
  }

  /**
   * @return true if `msg.sender` is the owner of the contract.
   */
  function isOwner() public view returns(bool) {
    return 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/lib/openzeppelin-solidity/contracts/token/ERC20/IERC20.sol

/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
interface IERC20 {
  function totalSupply() external view returns (uint256);

  function balanceOf(address who) external view returns (uint256);

  function allowance(address owner, address spender)
    external view returns (uint256);

  function transfer(address to, uint256 value) external returns (bool);

  function approve(address spender, uint256 value)
    external returns (bool);

  function transferFrom(address from, address to, uint256 value)
    external returns (bool);

  event Transfer(
    address indexed from,
    address indexed to,
    uint256 value
  );

  event Approval(
    address indexed owner,
    address indexed spender,
    uint256 value
  );
}

// File: contracts/lib/openzeppelin-solidity/contracts/token/ERC20/ERC20.sol

/**
 * @title Standard ERC20 token
 *
 * @dev Implementation of the basic standard token.
 * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
 * Originally based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
 */
contract ERC20 is IERC20 {
  using SafeMath for uint256;

  mapping (address => uint256) private _balances;

  mapping (address => mapping (address => uint256)) private _allowed;

  uint256 private _totalSupply;

  /**
  * @dev Total number of tokens in existence
  */
  function totalSupply() public view returns (uint256) {
    return _totalSupply;
  }

  /**
  * @dev Gets the balance of the specified address.
  * @param owner The address to query the the balance of.
  * @return An uint256 representing the amount owned by the passed address.
  */
  function balanceOf(address owner) public view returns (uint256) {
    return _balances[owner];
  }

  /**
   * @dev Function to check the amount of tokens that an owner allowed to a spender.
   * @param owner address The address which owns the funds.
   * @param spender address The address which will spend the funds.
   * @return A uint256 specifying the amount of tokens still available for the spender.
   */
  function allowance(
    address owner,
    address spender
   )
    public
    view
    returns (uint256)
  {
    return _allowed[owner][spender];
  }

  /**
  * @dev Transfer token for a specified address
  * @param to The address to transfer to.
  * @param value The amount to be transferred.
  */
  function transfer(address to, uint256 value) public returns (bool) {
    require(value <= _balances[msg.sender]);
    require(to != address(0));

    _balances[msg.sender] = _balances[msg.sender].sub(value);
    _balances[to] = _balances[to].add(value);
    emit Transfer(msg.sender, to, value);
    return true;
  }

  /**
   * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
   * Beware that changing an allowance with this method brings the risk that someone may use both the old
   * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
   * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
   * @param spender The address which will spend the funds.
   * @param value The amount of tokens to be spent.
   */
  function approve(address spender, uint256 value) public returns (bool) {
    require(spender != address(0));

    _allowed[msg.sender][spender] = value;
    emit Approval(msg.sender, spender, value);
    return true;
  }

  /**
   * @dev Transfer tokens from one address to another
   * @param from address The address which you want to send tokens from
   * @param to address The address which you want to transfer to
   * @param value uint256 the amount of tokens to be transferred
   */
  function transferFrom(
    address from,
    address to,
    uint256 value
  )
    public
    returns (bool)
  {
    require(value <= _balances[from]);
    require(value <= _allowed[from][msg.sender]);
    require(to != address(0));

    _balances[from] = _balances[from].sub(value);
    _balances[to] = _balances[to].add(value);
    _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
    emit Transfer(from, to, value);
    return true;
  }

  /**
   * @dev Increase the amount of tokens that an owner allowed to a spender.
   * approve should be called when allowed_[_spender] == 0. To increment
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param spender The address which will spend the funds.
   * @param addedValue The amount of tokens to increase the allowance by.
   */
  function increaseAllowance(
    address spender,
    uint256 addedValue
  )
    public
    returns (bool)
  {
    require(spender != address(0));

    _allowed[msg.sender][spender] = (
      _allowed[msg.sender][spender].add(addedValue));
    emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
    return true;
  }

  /**
   * @dev Decrease the amount of tokens that an owner allowed to a spender.
   * approve should be called when allowed_[_spender] == 0. To decrement
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param spender The address which will spend the funds.
   * @param subtractedValue The amount of tokens to decrease the allowance by.
   */
  function decreaseAllowance(
    address spender,
    uint256 subtractedValue
  )
    public
    returns (bool)
  {
    require(spender != address(0));

    _allowed[msg.sender][spender] = (
      _allowed[msg.sender][spender].sub(subtractedValue));
    emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
    return true;
  }

  /**
   * @dev Internal function that mints an amount of the token and assigns it to
   * an account. This encapsulates the modification of balances such that the
   * proper events are emitted.
   * @param account The account that will receive the created tokens.
   * @param amount The amount that will be created.
   */
  function _mint(address account, uint256 amount) internal {
    require(account != 0);
    _totalSupply = _totalSupply.add(amount);
    _balances[account] = _balances[account].add(amount);
    emit Transfer(address(0), account, amount);
  }

  /**
   * @dev Internal function that burns an amount of the token of a given
   * account.
   * @param account The account whose tokens will be burnt.
   * @param amount The amount that will be burnt.
   */
  function _burn(address account, uint256 amount) internal {
    require(account != 0);
    require(amount <= _balances[account]);

    _totalSupply = _totalSupply.sub(amount);
    _balances[account] = _balances[account].sub(amount);
    emit Transfer(account, address(0), amount);
  }

  /**
   * @dev Internal function that burns an amount of the token of a given
   * account, deducting from the sender's allowance for said account. Uses the
   * internal burn function.
   * @param account The account whose tokens will be burnt.
   * @param amount The amount that will be burnt.
   */
  function _burnFrom(address account, uint256 amount) internal {
    require(amount <= _allowed[account][msg.sender]);

    // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted,
    // this function needs to emit an event with the updated approval.
    _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(
      amount);
    _burn(account, amount);
  }
}

// File: contracts/lib/openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol

/**
 * @title Helps contracts guard against reentrancy attacks.
 * @author Remco Bloemen <[email protected]π.com>, Eenae <[email protected]>
 * @dev If you mark a function `nonReentrant`, you should also
 * mark it `external`.
 */
contract ReentrancyGuard {

  /// @dev counter to allow mutex lock with only one SSTORE operation
  uint256 private _guardCounter = 1;

  /**
   * @dev Prevents a contract from calling itself, directly or indirectly.
   * If you mark a function `nonReentrant`, you should also
   * mark it `external`. Calling one `nonReentrant` function from
   * another is not supported. Instead, you can implement a
   * `private` function doing the actual work, and an `external`
   * wrapper marked as `nonReentrant`.
   */
  modifier nonReentrant() {
    _guardCounter += 1;
    uint256 localCounter = _guardCounter;
    _;
    require(localCounter == _guardCounter);
  }

}

// File: contracts/HeroPresale.sol

contract HeroPresale is Ownable, Pausable, ReentrancyGuard {
    using SafeMath for uint256;

    struct HeroSale {
        uint128 highestPrice;
        uint128 previousPrice;
        uint128 priceIncreaseTo;
        uint64  since;
        uint64  until;
        uint64  previousSaleAt;
        uint16  lowestPriceRate;
        uint16  decreaseRate;
        uint16  supplyLimit;
        uint16  suppliedCounts;
        uint8   currency;
        bool    exists;
    }
    
    mapping(uint16 => HeroSale) public heroTypeToHeroSales;
    mapping(uint16 => uint256[]) public heroTypeIds;
    mapping(uint16 => mapping(address => bool)) public hasAirDropHero;

    ERC20 public coin;
    HeroAsset public heroAsset;
    uint16 constant internal SUPPLY_LIMIT_MAX = 10000;

    event AddSalesEvent(
        uint16 indexed heroType,
        uint128 startPrice,
        uint256 lowestPrice,
        uint256 becomeLowestAt
    );

    event SoldHeroEvent(
        uint16 indexed heroType,
        uint256 soldPrice,
        uint64  soldAt,
        uint256 priceIncreaseTo,
        uint256 lowestPrice,
        uint256 becomeLowestAt,
        address purchasedBy,
        address indexed code,
        uint8   currency
    );

    function setHeroAssetAddress(address _heroAssetAddress) external onlyOwner() {
        heroAsset = HeroAsset(_heroAssetAddress);
    }

    function setCoinAddress(ERC20 _coinAddress) external onlyOwner() {
        coin = _coinAddress;
    }

    function withdrawEther() external onlyOwner() {
        owner().transfer(address(this).balance);
    }

    function withdrawEMONT() external onlyOwner() {
        uint256 emontBalance = coin.balanceOf(this);
        coin.approve(address(this), emontBalance);
        coin.transferFrom(address(this), msg.sender, emontBalance);
    }

    function addSales(
        uint16 _heroType,
        uint128 _startPrice,
        uint16 _lowestPriceRate,
        uint16 _decreaseRate,
        uint64 _since,
        uint64 _until,
        uint16 _supplyLimit,
        uint8  _currency
    ) external onlyOwner() {
        require(!heroTypeToHeroSales[_heroType].exists, "this heroType is already added sales");
        require(0 <= _lowestPriceRate && _lowestPriceRate <= 100, "lowestPriceRate should be between 0 and 100");
        require(1 <= _decreaseRate && _decreaseRate <= 100, "decreaseRate should be should be between 1 and 100");
        require (_until > _since, "until should be later than since");

        HeroSale memory _herosale = HeroSale({
            highestPrice: _startPrice,
            previousPrice: _startPrice,
            priceIncreaseTo: _startPrice,
            since:_since,
            until:_until,
            previousSaleAt: _since,
            lowestPriceRate: _lowestPriceRate,
            decreaseRate: _decreaseRate,
            supplyLimit:_supplyLimit,
            suppliedCounts: 0,
            currency: _currency,
            exists: true
        });

        heroTypeToHeroSales[_heroType] = _herosale;
        heroAsset.setSupplyLimit(_heroType, _supplyLimit);

        uint256 _lowestPrice = uint256(_startPrice).mul(_lowestPriceRate).div(100);
        uint256 _becomeLowestAt = uint256(86400).mul(uint256(100).sub(_lowestPriceRate)).div(_decreaseRate).add(_since);

        emit AddSalesEvent(
            _heroType,
            _startPrice,
            _lowestPrice,
            _becomeLowestAt
        );
    }

    function purchase(uint16 _heroType, address _code) external whenNotPaused() nonReentrant() payable {
    // solium-disable-next-line security/no-block-members
        return purchaseImpl(_heroType, uint64(block.timestamp), _code);
    }

    function purchaseByEMONT(uint16 _heroType, uint256 _price, address _code) external whenNotPaused() {
      // solium-disable-next-line security/no-block-members
        return purchaseByEMONTImpl(_heroType, _price, uint64(block.timestamp), _code);
    }

    function airDrop(uint16 _heroType) external whenNotPaused() {
        HeroSale storage heroSales = heroTypeToHeroSales[_heroType];
        require(airDropHero(_heroType), "currency is not 2 (airdrop)");
        require(!hasAirDropHero[_heroType][msg.sender]);
        uint64 _at = uint64(block.timestamp);
        require(isOnSale(_heroType, _at), "out of sales period");

        createHero(_heroType, msg.sender);
        hasAirDropHero[_heroType][msg.sender] = true;
        heroSales.suppliedCounts++;
        heroSales.previousSaleAt = _at;

        emit SoldHeroEvent(
            _heroType,
            1,
            _at,
            1,
            1,
            1,
            msg.sender,
            0x0000000000000000000000000000000000000000,
            2
        );
    }


    function computeCurrentPrice(uint16 _heroType) external view returns (uint8, uint256){
        // solium-disable-next-line security/no-block-members
        return computeCurrentPriceImpl(_heroType, uint64(block.timestamp));
    }

    function canBePurchasedByETH(uint16 _heroType) internal view returns (bool){
        return (heroTypeToHeroSales[_heroType].currency == 0);
    }

    function canBePurchasedByEMONT(uint16 _heroType) internal view returns (bool){
        return (heroTypeToHeroSales[_heroType].currency == 1);
    }

    function airDropHero(uint16 _heroType) internal view returns (bool){
        return (heroTypeToHeroSales[_heroType].currency == 2);
    }

    function isOnSale(uint16 _heroType, uint64 _now) internal view returns (bool){
        HeroSale storage heroSales = heroTypeToHeroSales[_heroType];
        require(heroSales.exists, "not exist sales of this heroType");

        if (heroSales.since <= _now && _now <= heroSales.until) {
            return true;
        } else {
            return false;
        }
    }

    function computeCurrentPriceImpl(uint16 _heroType, uint64 _at) internal view returns (uint8, uint256) {
        HeroSale storage heroSales = heroTypeToHeroSales[_heroType];
        require(heroSales.exists, "not exist sales of this heroType");
        require(heroSales.previousSaleAt < _at, "current timestamp should be later than previousSaleAt");

        uint256 _lowestPrice = uint256(heroSales.highestPrice).mul(heroSales.lowestPriceRate).div(100);
        uint256 _secondsPassed = uint256(_at).sub(heroSales.previousSaleAt);
        uint256 _decreasedPrice = uint256(heroSales.priceIncreaseTo).mul(_secondsPassed).mul(heroSales.decreaseRate).div(100).div(86400);
        uint256 currentPrice;

        if (uint256(heroSales.priceIncreaseTo).sub(_lowestPrice) > _decreasedPrice){
            currentPrice = uint256(heroSales.priceIncreaseTo).sub(_decreasedPrice);
        } else {
            currentPrice = _lowestPrice;
        }

        return (1, currentPrice);
    }

    function purchaseImpl(uint16 _heroType, uint64 _at, address code)
        internal
    {
        HeroSale storage heroSales = heroTypeToHeroSales[_heroType];
        require(canBePurchasedByETH(_heroType), "currency is not 0 (eth)");
        require(isOnSale(_heroType, _at), "out of sales period");
        (,uint256 _price)  = computeCurrentPriceImpl(_heroType, _at);
        require(msg.value >= _price, "value is less than the price");

        createHero(_heroType, msg.sender);

        if (msg.value > _price){
            msg.sender.transfer(msg.value.sub(_price));
        }

        heroSales.previousPrice = uint128(_price);
        heroSales.suppliedCounts++;
        heroSales.previousSaleAt = _at;

        if (heroSales.previousPrice > heroSales.highestPrice){
            heroSales.highestPrice = heroSales.previousPrice;
        }

        uint256 _priceIncreaseTo;
        uint256 _lowestPrice;
        uint256 _becomeLowestAt;

        if(heroSales.supplyLimit > heroSales.suppliedCounts){
            _priceIncreaseTo = SafeMath.add(_price, _price.div((uint256(heroSales.supplyLimit).sub(heroSales.suppliedCounts))));
            heroSales.priceIncreaseTo = uint128(_priceIncreaseTo);
            _lowestPrice = uint256(heroSales.lowestPriceRate).mul(heroSales.highestPrice).div(100);
            _becomeLowestAt = uint256(86400).mul(100).mul((_priceIncreaseTo.sub(_lowestPrice))).div(_priceIncreaseTo).div(heroSales.decreaseRate).add(_at);
        } else {
            _priceIncreaseTo = heroSales.previousPrice;
            heroSales.priceIncreaseTo = uint128(_priceIncreaseTo);
            _lowestPrice = heroSales.previousPrice;
            _becomeLowestAt = _at;
        }

        address Invitees;

        if (code == msg.sender){
            Invitees = address(0x0);
        } else {
            Invitees = code;
        }

        emit SoldHeroEvent(
            _heroType,
            _price,
            _at,
            _priceIncreaseTo,
            _lowestPrice,
            _becomeLowestAt,
            msg.sender,
            Invitees,
            0
        );

    }

    function purchaseByEMONTImpl(uint16 _heroType, uint256 _inputPrice, uint64 _at, address _code)
        internal
    {
        HeroSale storage heroSales = heroTypeToHeroSales[_heroType];
        require(canBePurchasedByEMONT(_heroType), "currency is not 1 (EMONT)");
        require(isOnSale(_heroType, _at), "out of sales period");
        (,uint256 _price)  = computeCurrentPriceImpl(_heroType, _at);
        require(_inputPrice > _price, "input price is not more than actual price");

        createHero(_heroType, msg.sender);
        coin.transferFrom(msg.sender, address(this), _price);

        heroSales.previousPrice = uint128(_price);
        heroSales.suppliedCounts++;
        heroSales.previousSaleAt = _at;

        if (heroSales.previousPrice > heroSales.highestPrice){
            heroSales.highestPrice = heroSales.previousPrice;
        }

        uint256 _priceIncreaseTo;
        uint256 _lowestPrice;
        uint256 _becomeLowestAt;

        if(heroSales.supplyLimit > heroSales.suppliedCounts){
            _priceIncreaseTo = SafeMath.add(_price, _price.div((uint256(heroSales.supplyLimit).sub(heroSales.suppliedCounts))));
            heroSales.priceIncreaseTo = uint128(_priceIncreaseTo);
            _lowestPrice = uint256(heroSales.lowestPriceRate).mul(heroSales.highestPrice).div(100);
            _becomeLowestAt = uint256(86400).mul(100).mul((_priceIncreaseTo.sub(_lowestPrice))).div(_priceIncreaseTo).div(heroSales.decreaseRate).add(_at);
        } else {
            _priceIncreaseTo = heroSales.previousPrice;
            heroSales.priceIncreaseTo = uint128(_priceIncreaseTo);
            _lowestPrice = heroSales.previousPrice;
            _becomeLowestAt = _at;
        }

        address Invitees;

        if (_code == msg.sender){
            Invitees = address(0x0);
        } else {
            Invitees = _code;
        }

        emit SoldHeroEvent(
            _heroType,
            _price,
            _at,
            _priceIncreaseTo,
            _lowestPrice,
            _becomeLowestAt,
            msg.sender,
            Invitees,
            1
        );

    }

    function createHero(uint16 _heroType, address _owner) internal {
        require(heroTypeToHeroSales[_heroType].exists, "not exist sales of this heroType");
        require(heroTypeIds[_heroType].length < heroTypeToHeroSales[_heroType].supplyLimit, "Heroes cant be created more than supplyLimit");

        uint256 _heroId = uint256(_heroType).mul(SUPPLY_LIMIT_MAX).add(heroTypeIds[_heroType].length).add(1);
        heroTypeIds[_heroType].push(_heroId);
        heroAsset.mintHeroAsset(_owner, _heroId);
    }
}

    Contract ABI  
[{"constant":false,"inputs":[{"name":"_heroType","type":"uint16"},{"name":"_price","type":"uint256"},{"name":"_code","type":"address"}],"name":"purchaseByEMONT","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_heroType","type":"uint16"},{"name":"_startPrice","type":"uint128"},{"name":"_lowestPriceRate","type":"uint16"},{"name":"_decreaseRate","type":"uint16"},{"name":"_since","type":"uint64"},{"name":"_until","type":"uint64"},{"name":"_supplyLimit","type":"uint16"},{"name":"_currency","type":"uint8"}],"name":"addSales","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"coin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdrawEMONT","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"heroAsset","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint16"}],"name":"heroTypeToHeroSales","outputs":[{"name":"highestPrice","type":"uint128"},{"name":"previousPrice","type":"uint128"},{"name":"priceIncreaseTo","type":"uint128"},{"name":"since","type":"uint64"},{"name":"until","type":"uint64"},{"name":"previousSaleAt","type":"uint64"},{"name":"lowestPriceRate","type":"uint16"},{"name":"decreaseRate","type":"uint16"},{"name":"supplyLimit","type":"uint16"},{"name":"suppliedCounts","type":"uint16"},{"name":"currency","type":"uint8"},{"name":"exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_heroType","type":"uint16"},{"name":"_code","type":"address"}],"name":"purchase","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isPauser","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint16"},{"name":"","type":"uint256"}],"name":"heroTypeIds","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renouncePauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdrawEther","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addPauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_heroAssetAddress","type":"address"}],"name":"setHeroAssetAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_coinAddress","type":"address"}],"name":"setCoinAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_heroType","type":"uint16"}],"name":"airDrop","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint16"},{"name":"","type":"address"}],"name":"hasAirDropHero","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_heroType","type":"uint16"}],"name":"computeCurrentPrice","outputs":[{"name":"","type":"uint8"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"heroType","type":"uint16"},{"indexed":false,"name":"startPrice","type":"uint128"},{"indexed":false,"name":"lowestPrice","type":"uint256"},{"indexed":false,"name":"becomeLowestAt","type":"uint256"}],"name":"AddSalesEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"heroType","type":"uint16"},{"indexed":false,"name":"soldPrice","type":"uint256"},{"indexed":false,"name":"soldAt","type":"uint64"},{"indexed":false,"name":"priceIncreaseTo","type":"uint256"},{"indexed":false,"name":"lowestPrice","type":"uint256"},{"indexed":false,"name":"becomeLowestAt","type":"uint256"},{"indexed":false,"name":"purchasedBy","type":"address"},{"indexed":true,"name":"code","type":"address"},{"indexed":false,"name":"currency","type":"uint8"}],"name":"SoldHeroEvent","type":"event"},{"anonymous":false,"inputs":[],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"PauserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"PauserRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]

  Contract Creation Code Switch To Opcodes View
60806040526002805460ff191690556001600381905560008054600160a060020a031916339081179091556100419190640100000000611d7161004682021704565b610080565b600160a060020a038116151561005b57600080fd5b600160a060020a0316600090815260209190915260409020805460ff19166001179055565b6124528061008f6000396000f30060806040526004361061013d5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630396dcb0811461014257806304803c2a1461016f57806311df9995146101c657806315003368146101f757806316f38b631461020c57806328aa48b414610221578063396c8228146102c35780633f4ba83a146102de57806346fbf68e146102f35780635c975abb146103285780636980f4fb1461033d5780636ef8d66d1461036e578063715018a6146103835780637362377b1461039857806382dc1ec4146103ad5780638456cb59146103ce5780638da5cb5b146103e35780638f32d59b146103f8578063985df3a71461040d578063b0bdacc61461042e578063b27eb3e51461044f578063b673ddb71461046b578063e6d944a714610493578063f2fde38b146104cc575b600080fd5b34801561014e57600080fd5b5061016d61ffff60043516602435600160a060020a03604435166104ed565b005b34801561017b57600080fd5b5061016d61ffff6004358116906001608060020a03602435169060443581169060643581169067ffffffffffffffff60843581169160a4359091169060c4351660ff60e4351661050e565b3480156101d257600080fd5b506101db610b94565b60408051600160a060020a039092168252519081900360200190f35b34801561020357600080fd5b5061016d610ba3565b34801561021857600080fd5b506101db610d83565b34801561022d57600080fd5b5061023d61ffff60043516610d92565b604080516001608060020a039d8e1681529b8d1660208d015299909b168a8a015267ffffffffffffffff97881660608b015295871660808a01529390951660a088015261ffff91821660c0880152811660e087015292831661010086015290911661012084015260ff166101408301529115156101608201529051908190036101800190f35b61016d61ffff60043516600160a060020a0360243516610e5c565b3480156102ea57600080fd5b5061016d610e90565b3480156102ff57600080fd5b50610314600160a060020a0360043516610eea565b604080519115158252519081900360200190f35b34801561033457600080fd5b50610314610f03565b34801561034957600080fd5b5061035c61ffff60043516602435610f0c565b60408051918252519081900360200190f35b34801561037a57600080fd5b5061016d610f3c565b34801561038f57600080fd5b5061016d610f4f565b3480156103a457600080fd5b5061016d610fb7565b3480156103b957600080fd5b5061016d600160a060020a036004351661100d565b3480156103da57600080fd5b5061016d611069565b3480156103ef57600080fd5b506101db6110c5565b34801561040457600080fd5b506103146110d4565b34801561041957600080fd5b5061016d600160a060020a03600435166110e5565b34801561043a57600080fd5b5061016d600160a060020a0360043516611127565b34801561045b57600080fd5b5061016d61ffff60043516611169565b34801561047757600080fd5b5061031461ffff60043516600160a060020a0360243516611367565b34801561049f57600080fd5b506104af61ffff60043516611387565b6040805160ff909316835260208301919091528051918290030190f35b3480156104d857600080fd5b5061016d600160a060020a036004351661139d565b60025460ff16156104fd57600080fd5b610509838342846113b9565b505050565b6105166123c2565b6000806105216110d4565b151561052c57600080fd5b61ffff8b1660009081526004602052604090206002015471010000000000000000000000000000000000900460ff16156105d5576040805160e560020a62461bcd028152602060048201526024808201527f74686973206865726f5479706520697320616c7265616479206164646564207360448201527f616c657300000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b8861ffff166000111580156105ef575060648961ffff1611155b151561066b576040805160e560020a62461bcd02815260206004820152602b60248201527f6c6f776573745072696365526174652073686f756c642062652062657477656560448201527f6e203020616e6420313030000000000000000000000000000000000000000000606482015290519081900360840190fd5b8761ffff16600111158015610685575060648861ffff1611155b1515610701576040805160e560020a62461bcd02815260206004820152603260248201527f6465637265617365526174652073686f756c642062652073686f756c6420626560448201527f206265747765656e203120616e64203130300000000000000000000000000000606482015290519081900360840190fd5b67ffffffffffffffff80881690871611610765576040805160e560020a62461bcd02815260206004820181905260248201527f756e74696c2073686f756c64206265206c61746572207468616e2073696e6365604482015290519081900360640190fd5b610180604051908101604052808b6001608060020a031681526020018b6001608060020a031681526020018b6001608060020a031681526020018867ffffffffffffffff1681526020018767ffffffffffffffff1681526020018867ffffffffffffffff1681526020018a61ffff1681526020018961ffff1681526020018661ffff168152602001600061ffff1681526020018560ff16815260200160011515815250925082600460008d61ffff1661ffff16815260200190815260200160002060008201518160000160006101000a8154816001608060020a0302191690836001608060020a0316021790555060208201518160000160106101000a8154816001608060020a0302191690836001608060020a0316021790555060408201518160010160006101000a8154816001608060020a0302191690836001608060020a0316021790555060608201518160010160106101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060808201518160010160186101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060a08201518160020160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060c08201518160020160086101000a81548161ffff021916908361ffff16021790555060e082015181600201600a6101000a81548161ffff021916908361ffff16021790555061010082015181600201600c6101000a81548161ffff021916908361ffff16021790555061012082015181600201600e6101000a81548161ffff021916908361ffff1602179055506101408201518160020160106101000a81548160ff021916908360ff1602179055506101608201518160020160116101000a81548160ff021916908315150217905550905050600860009054906101000a9004600160a060020a0316600160a060020a0316636fa23f738c876040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808361ffff1661ffff1681526020018261ffff1661ffff16815260200192505050600060405180830381600087803b158015610a9d57600080fd5b505af1158015610ab1573d6000803e3d6000fd5b50505050610ae66064610ada8b61ffff168d6001608060020a031661187490919063ffffffff16565b9063ffffffff6118ad16565b9150610b358767ffffffffffffffff16610b298a61ffff16610ada610b198e61ffff1660646118d090919063ffffffff16565b620151809063ffffffff61187416565b9063ffffffff6118e716565b604080516001608060020a038d16815260208101859052808201839052905191925061ffff8d16917fbb9aad0aec529392a851fee029d68b1fe345568b44c44e3e4ea716375f4949529181900360600190a25050505050505050505050565b600754600160a060020a031681565b6000610bad6110d4565b1515610bb857600080fd5b600754604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600160a060020a03909216916370a08231916024808201926020929091908290030181600087803b158015610c1e57600080fd5b505af1158015610c32573d6000803e3d6000fd5b505050506040513d6020811015610c4857600080fd5b5051600754604080517f095ea7b3000000000000000000000000000000000000000000000000000000008152306004820152602481018490529051929350600160a060020a039091169163095ea7b3916044808201926020929091908290030181600087803b158015610cba57600080fd5b505af1158015610cce573d6000803e3d6000fd5b505050506040513d6020811015610ce457600080fd5b5050600754604080517f23b872dd000000000000000000000000000000000000000000000000000000008152306004820152336024820152604481018490529051600160a060020a03909216916323b872dd916064808201926020929091908290030181600087803b158015610d5957600080fd5b505af1158015610d6d573d6000803e3d6000fd5b505050506040513d602081101561050957600080fd5b600854600160a060020a031681565b6004602052600090815260409020805460018201546002909201546001608060020a0380831693608060020a938490048216939181169267ffffffffffffffff83830481169378010000000000000000000000000000000000000000000000009093048116929082169161ffff6801000000000000000082048116926a010000000000000000000083048216926c010000000000000000000000008104831692607060020a8204169160ff908204811691710100000000000000000000000000000000009004168c565b60025460ff1615610e6c57600080fd5b6003805460010190819055610e828342846118f9565b600354811461050957600080fd5b610e9933610eea565b1515610ea457600080fd5b60025460ff161515610eb557600080fd5b6002805460ff191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b6000610efd60018363ffffffff611d0316565b92915050565b60025460ff1690565b600560205281600052604060002081815481101515610f2757fe5b90600052602060002001600091509150505481565b610f4d60013363ffffffff611d3a16565b565b610f576110d4565b1515610f6257600080fd5b60008054604051600160a060020a03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b610fbf6110d4565b1515610fca57600080fd5b610fd26110c5565b604051600160a060020a039190911690303180156108fc02916000818181858888f1935050505015801561100a573d6000803e3d6000fd5b50565b61101633610eea565b151561102157600080fd5b61103260018263ffffffff611d7116565b604051600160a060020a038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b61107233610eea565b151561107d57600080fd5b60025460ff161561108d57600080fd5b6002805460ff191660011790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b600054600160a060020a031690565b600054600160a060020a0316331490565b6110ed6110d4565b15156110f857600080fd5b6008805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b61112f6110d4565b151561113a57600080fd5b6007805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600254600090819060ff161561117e57600080fd5b61ffff83166000908152600460205260409020915061119c83611dab565b15156111f2576040805160e560020a62461bcd02815260206004820152601b60248201527f63757272656e6379206973206e6f742032202861697264726f70290000000000604482015290519081900360640190fd5b61ffff8316600090815260066020908152604080832033845290915290205460ff161561121e57600080fd5b504261122a8382611dd1565b1515611280576040805160e560020a62461bcd02815260206004820152601360248201527f6f7574206f662073616c657320706572696f6400000000000000000000000000604482015290519081900360640190fd5b61128a8333611ec4565b61ffff808416600081815260066020908152604080832033808552908352818420805460ff191660019081179091556002808a01805467ffffffffffffffff8b1667ffffffffffffffff19607060020a8084048d168701909c16909b026fffff00000000000000000000000000001990921691909117999099168917905583518281529485019790975283830181905260608401819052608084015260a083015260c0820194909452925190927f3db18ae119a752978a5fdd210c2d8457748cafadf61769dde052bb15edb62e7f919081900360e00190a3505050565b600660209081526000928352604080842090915290825290205460ff1681565b60008061139483426120dd565b91509150915091565b6113a56110d4565b15156113b057600080fd5b61100a816122fb565b61ffff8416600090815260046020526040812090808080806113da8a612378565b1515611430576040805160e560020a62461bcd02815260206004820152601960248201527f63757272656e6379206973206e6f7420312028454d4f4e542900000000000000604482015290519081900360640190fd5b61143a8a89611dd1565b1515611490576040805160e560020a62461bcd02815260206004820152601360248201527f6f7574206f662073616c657320706572696f6400000000000000000000000000604482015290519081900360640190fd5b61149a8a896120dd565b95505084891161151a576040805160e560020a62461bcd02815260206004820152602960248201527f696e707574207072696365206973206e6f74206d6f7265207468616e2061637460448201527f75616c2070726963650000000000000000000000000000000000000000000000606482015290519081900360840190fd5b6115248a33611ec4565b600754604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018890529051600160a060020a03909216916323b872dd916064808201926020929091908290030181600087803b15801561159757600080fd5b505af11580156115ab573d6000803e3d6000fd5b505050506040513d60208110156115c157600080fd5b505085546001608060020a03908116608060020a8783168102919091178089556002890180546fffff0000000000000000000000000000198116607060020a9182900461ffff908116600101169091021767ffffffffffffffff191667ffffffffffffffff8d161790558083169190049091161115611665578554608060020a81046001608060020a03166fffffffffffffffffffffffffffffffff199091161786555b600286015461ffff607060020a820481166c010000000000000000000000009092041611156117925760028601546116d69086906116d1906116c49061ffff6c010000000000000000000000008204811691607060020a9004166118d0565b889063ffffffff6118ad16565b6118e7565b6001870180546fffffffffffffffffffffffffffffffff19166001608060020a03838116919091179091558754600289015492965061172e92606492610ada926801000000000000000090920461ffff169116611874565b600287015490935061178b9067ffffffffffffffff8a1690610b29906a0100000000000000000000900461ffff16610ada888161176b828b6118d0565b61177f62015180606463ffffffff61187416565b9063ffffffff61187416565b91506117d7565b8554600187018054608060020a9092046001608060020a03166fffffffffffffffffffffffffffffffff1990921682179055935083925067ffffffffffffffff881691505b600160a060020a0387163314156117f0575060006117f3565b50855b6040805186815267ffffffffffffffff8a16602082015280820186905260608101859052608081018490523360a0820152600160c08201529051600160a060020a0383169161ffff8d16917f3db18ae119a752978a5fdd210c2d8457748cafadf61769dde052bb15edb62e7f9181900360e00190a350505050505050505050565b60008083151561188757600091506118a6565b5082820282848281151561189757fe5b04146118a257600080fd5b8091505b5092915050565b6000808083116118bc57600080fd5b82848115156118c757fe5b04949350505050565b600080838311156118e057600080fd5b5050900390565b6000828201838110156118a257600080fd5b61ffff83166000908152600460205260408120908080808061191a8961239e565b1515611970576040805160e560020a62461bcd02815260206004820152601760248201527f63757272656e6379206973206e6f742030202865746829000000000000000000604482015290519081900360640190fd5b61197a8989611dd1565b15156119d0576040805160e560020a62461bcd02815260206004820152601360248201527f6f7574206f662073616c657320706572696f6400000000000000000000000000604482015290519081900360640190fd5b6119da89896120dd565b95505034851115611a35576040805160e560020a62461bcd02815260206004820152601c60248201527f76616c7565206973206c657373207468616e2074686520707269636500000000604482015290519081900360640190fd5b611a3f8933611ec4565b84341115611a8557336108fc611a5b348863ffffffff6118d016565b6040518115909202916000818181858888f19350505050158015611a83573d6000803e3d6000fd5b505b85546001608060020a03908116608060020a8783168102919091178089556002890180546fffff0000000000000000000000000000198116607060020a9182900461ffff908116600101169091021767ffffffffffffffff191667ffffffffffffffff8d161790558083169190049091161115611b27578554608060020a81046001608060020a03166fffffffffffffffffffffffffffffffff199091161786555b600286015461ffff607060020a820481166c01000000000000000000000000909204161115611c22576002860154611b869086906116d1906116c49061ffff6c010000000000000000000000008204811691607060020a9004166118d0565b6001870180546fffffffffffffffffffffffffffffffff19166001608060020a038381169190911790915587546002890154929650611bde92606492610ada926801000000000000000090920461ffff169116611874565b6002870154909350611c1b9067ffffffffffffffff8a1690610b29906a0100000000000000000000900461ffff16610ada888161176b828b6118d0565b9150611c67565b8554600187018054608060020a9092046001608060020a03166fffffffffffffffffffffffffffffffff1990921682179055935083925067ffffffffffffffff881691505b600160a060020a038716331415611c8057506000611c83565b50855b6040805186815267ffffffffffffffff8a16602082015280820186905260608101859052608081018490523360a0820152600060c08201529051600160a060020a0383169161ffff8c16917f3db18ae119a752978a5fdd210c2d8457748cafadf61769dde052bb15edb62e7f9181900360e00190a3505050505050505050565b6000600160a060020a0382161515611d1a57600080fd5b50600160a060020a03166000908152602091909152604090205460ff1690565b600160a060020a0381161515611d4f57600080fd5b600160a060020a0316600090815260209190915260409020805460ff19169055565b600160a060020a0381161515611d8657600080fd5b600160a060020a0316600090815260209190915260409020805460ff19166001179055565b61ffff166000908152600460205260409020600290810154608060020a900460ff161490565b61ffff82166000908152600460205260408120600281015471010000000000000000000000000000000000900460ff161515611e57576040805160e560020a62461bcd02815260206004820181905260248201527f6e6f742065786973742073616c6573206f662074686973206865726f54797065604482015290519081900360640190fd5b600181015467ffffffffffffffff808516608060020a9092041611801590611ead5750600181015467ffffffffffffffff7801000000000000000000000000000000000000000000000000909104811690841611155b15611ebb57600191506118a6565b600091506118a6565b61ffff821660009081526004602052604081206002015471010000000000000000000000000000000000900460ff161515611f49576040805160e560020a62461bcd02815260206004820181905260248201527f6e6f742065786973742073616c6573206f662074686973206865726f54797065604482015290519081900360640190fd5b61ffff8084166000908152600460209081526040808320600201546005909252909120546c0100000000000000000000000090910490911611611ffc576040805160e560020a62461bcd02815260206004820152602c60248201527f4865726f65732063616e742062652063726561746564206d6f7265207468616e60448201527f20737570706c794c696d69740000000000000000000000000000000000000000606482015290519081900360840190fd5b61ffff831660008181526005602052604090205461202b91600191610b2991829061271063ffffffff61187416565b61ffff84166000908152600560209081526040808320805460018101825590845291832090910183905560085481517f4d5b335d000000000000000000000000000000000000000000000000000000008152600160a060020a038781166004830152602482018690529251949550911692634d5b335d9260448084019391929182900301818387803b1580156120c057600080fd5b505af11580156120d4573d6000803e3d6000fd5b50505050505050565b61ffff821660009081526004602052604081206002810154829190829081908190819071010000000000000000000000000000000000900460ff16151561216e576040805160e560020a62461bcd02815260206004820181905260248201527f6e6f742065786973742073616c6573206f662074686973206865726f54797065604482015290519081900360640190fd5b600285015467ffffffffffffffff808a169116106121fc576040805160e560020a62461bcd02815260206004820152603560248201527f63757272656e742074696d657374616d702073686f756c64206265206c61746560448201527f72207468616e2070726576696f757353616c6541740000000000000000000000606482015290519081900360840190fd5b6002850154855461222f91606491610ada916001608060020a039091169068010000000000000000900461ffff16611874565b60028601549094506122549067ffffffffffffffff8a8116911663ffffffff6118d016565b6002860154600187015491945061229a916201518091610ada9160649183916a010000000000000000000090910461ffff169061177f906001608060020a03168a611874565b600186015490925082906122bd906001608060020a03168663ffffffff6118d016565b11156122e85760018501546122e1906001608060020a03168363ffffffff6118d016565b90506122eb565b50825b6001999098509650505050505050565b600160a060020a038116151561231057600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b61ffff16600090815260046020526040902060020154608060020a900460ff1660011490565b61ffff16600090815260046020526040902060020154608060020a900460ff161590565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810191909152905600a165627a7a72305820f98098e6ea4ba6a8b23a13c03df1115e245c511cb9ae500e5b4c64bc4af8f7d40029

   Swarm Source:
bzzr://f98098e6ea4ba6a8b23a13c03df1115e245c511cb9ae500e5b4c64bc4af8f7d4

 

View All
Block Age transaction Difficulty GasUsed Reward
View All
Block Age UncleNumber Difficulty GasUsed Reward
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.