ETH Price: $1,850.60 (+1.14%)
Gas: 20 Gwei
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multi Chain

Multichain Addresses

0 address found via
Transaction Hash
Method
Block
From
To
Value
Buy Tokens80024232019-06-21 16:05:551448 days 6 hrs ago1561133155IN
0x4668E1...52472aF3
0.02 ETH0.00084083
Buy Tokens71602552019-02-01 20:20:231588 days 2 hrs ago1549052423IN
0x4668E1...52472aF3
0.02 ETH0.000560532
Buy Tokens71599912019-02-01 19:06:201588 days 3 hrs ago1549047980IN
0x4668E1...52472aF3
0.02 ETH0.00084083
Buy Tokens71376502019-01-28 5:28:011592 days 17 hrs ago1548653281IN
0x4668E1...52472aF3
0.02 ETH0.000560532
Buy Tokens70441902019-01-10 20:08:361610 days 2 hrs ago1547150916IN
0x4668E1...52472aF3
0.1 ETH0.002465762
Buy Tokens70388912019-01-09 21:14:501611 days 1 hr ago1547068490IN
0x4668E1...52472aF3
0.1 ETH0.002465762
Buy Tokens69502472018-12-25 12:30:081626 days 10 hrs ago1545741008IN
0x4668E1...52472aF3
0.2 ETH0.009696114
Buy Tokens69488692018-12-25 7:02:381626 days 15 hrs ago1545721358IN
0x4668E1...52472aF3
0.02 ETH0.0028026710
Buy Tokens69488682018-12-25 7:02:301626 days 15 hrs ago1545721350IN
0x4668E1...52472aF3
0.02 ETH0.0028026710
Buy Tokens69488662018-12-25 7:02:181626 days 15 hrs ago1545721338IN
0x4668E1...52472aF3
0.02 ETH0.0028026710
Buy Tokens69488612018-12-25 7:01:221626 days 15 hrs ago1545721282IN
0x4668E1...52472aF3
0.02 ETH0.0028026710
Buy Tokens69488562018-12-25 7:00:101626 days 15 hrs ago1545721210IN
0x4668E1...52472aF3
0.1 ETH0.0135617211
Buy Tokens69488412018-12-25 6:56:361626 days 15 hrs ago1545720996IN
0x4668E1...52472aF3
0.2 ETH0.0290883312
Buy Tokens69429972018-12-24 7:20:491627 days 15 hrs ago1545636049IN
0x4668E1...52472aF3
0.1 ETH0.004931534
Buy Tokens69429972018-12-24 7:20:491627 days 15 hrs ago1545636049IN
0x4668E1...52472aF3
0.1 ETH0.004931534
Buy Tokens69429972018-12-24 7:20:491627 days 15 hrs ago1545636049IN
0x4668E1...52472aF3
0.1 ETH0.004931534
Buy Tokens69429892018-12-24 7:18:161627 days 15 hrs ago1545635896IN
0x4668E1...52472aF3
0.1 ETH0.004931534
Buy Tokens69429892018-12-24 7:18:161627 days 15 hrs ago1545635896IN
0x4668E1...52472aF3
0.1 ETH0.004931534
Buy Tokens69429832018-12-24 7:16:201627 days 15 hrs ago1545635780IN
0x4668E1...52472aF3
0.1 ETH0.004931534
Buy Tokens69429832018-12-24 7:16:201627 days 15 hrs ago1545635780IN
0x4668E1...52472aF3
0.2 ETH0.009696114
Buy Tokens69429652018-12-24 7:12:511627 days 15 hrs ago1545635571IN
0x4668E1...52472aF3
0.2 ETH0.009696114
Buy Tokens69424292018-12-24 4:57:261627 days 17 hrs ago1545627446IN
0x4668E1...52472aF3
0.02 ETH0.001961867
Buy Tokens69424132018-12-24 4:52:031627 days 17 hrs ago1545627123IN
0x4668E1...52472aF3
0.02 ETH0.002242138
Buy Tokens69424082018-12-24 4:51:301627 days 17 hrs ago1545627090IN
0x4668E1...52472aF3
0.02 ETH0.002242138
Buy Tokens69422562018-12-24 4:13:521627 days 18 hrs ago1545624832IN
0x4668E1...52472aF3
0.2 ETH0.014544166
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Advanced Filter
Parent Txn Hash Block From To Value
80024232019-06-21 16:05:551448 days 6 hrs ago1561133155
0x4668E1...52472aF3
0.02 ETH
71602552019-02-01 20:20:231588 days 2 hrs ago1549052423
0x4668E1...52472aF3
0.02 ETH
71599912019-02-01 19:06:201588 days 3 hrs ago1549047980
0x4668E1...52472aF3
0.02 ETH
71376502019-01-28 5:28:011592 days 17 hrs ago1548653281
0x4668E1...52472aF3
0.02 ETH
70441902019-01-10 20:08:361610 days 2 hrs ago1547150916
0x4668E1...52472aF3
0.1 ETH
70388912019-01-09 21:14:501611 days 1 hr ago1547068490
0x4668E1...52472aF3
0.1 ETH
69502472018-12-25 12:30:081626 days 10 hrs ago1545741008
0x4668E1...52472aF3
0.2 ETH
69488692018-12-25 7:02:381626 days 15 hrs ago1545721358
0x4668E1...52472aF3
0.02 ETH
69488682018-12-25 7:02:301626 days 15 hrs ago1545721350
0x4668E1...52472aF3
0.02 ETH
69488662018-12-25 7:02:181626 days 15 hrs ago1545721338
0x4668E1...52472aF3
0.02 ETH
69488612018-12-25 7:01:221626 days 15 hrs ago1545721282
0x4668E1...52472aF3
0.02 ETH
69488562018-12-25 7:00:101626 days 15 hrs ago1545721210
0x4668E1...52472aF3
0.1 ETH
69488412018-12-25 6:56:361626 days 15 hrs ago1545720996
0x4668E1...52472aF3
0.2 ETH
69429972018-12-24 7:20:491627 days 15 hrs ago1545636049
0x4668E1...52472aF3
0.1 ETH
69429972018-12-24 7:20:491627 days 15 hrs ago1545636049
0x4668E1...52472aF3
0.1 ETH
69429972018-12-24 7:20:491627 days 15 hrs ago1545636049
0x4668E1...52472aF3
0.1 ETH
69429892018-12-24 7:18:161627 days 15 hrs ago1545635896
0x4668E1...52472aF3
0.1 ETH
69429892018-12-24 7:18:161627 days 15 hrs ago1545635896
0x4668E1...52472aF3
0.1 ETH
69429832018-12-24 7:16:201627 days 15 hrs ago1545635780
0x4668E1...52472aF3
0.1 ETH
69429832018-12-24 7:16:201627 days 15 hrs ago1545635780
0x4668E1...52472aF3
0.2 ETH
69429652018-12-24 7:12:511627 days 15 hrs ago1545635571
0x4668E1...52472aF3
0.2 ETH
69424292018-12-24 4:57:261627 days 17 hrs ago1545627446
0x4668E1...52472aF3
0.02 ETH
69424132018-12-24 4:52:031627 days 17 hrs ago1545627123
0x4668E1...52472aF3
0.02 ETH
69424082018-12-24 4:51:301627 days 17 hrs ago1545627090
0x4668E1...52472aF3
0.02 ETH
69422562018-12-24 4:13:521627 days 18 hrs ago1545624832
0x4668E1...52472aF3
0.2 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Presale

Compiler Version
v0.4.24+commit.e67f0147

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2018-08-28
*/

pragma solidity ^0.4.11;


interface CommonWallet {
    function receive() external payable;
}

library StringUtils {
    function concat(string _a, string _b)
        internal
        pure
        returns (string)
    {
        bytes memory _ba = bytes(_a);
        bytes memory _bb = bytes(_b);

        bytes memory bab = new bytes(_ba.length + _bb.length);
        uint k = 0;
        for (uint i = 0; i < _ba.length; i++) bab[k++] = _ba[i];
        for (i = 0; i < _bb.length; i++) bab[k++] = _bb[i];
        return string(bab);
    }
}

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

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

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

  // @dev Multiplies two numbers, throws on overflow.
  function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
    if (a == 0) {
      return 0;
    }
    c = a * b;
    assert(c / a == b);
    return c;
  }

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


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


  // @dev Adds two numbers, throws on overflow.
  function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
    c = a + b;
    assert(c >= a);
    return c;
  }
}

library SafeMath32 {
  // @dev Multiplies two numbers, throws on overflow.
  function mul(uint32 a, uint32 b) internal pure returns (uint32 c) {
    if (a == 0) {
      return 0;
    }
    c = a * b;
    assert(c / a == b);
    return c;
  }


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


  // @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  function sub(uint32 a, uint32 b) internal pure returns (uint32) {
    assert(b <= a);
    return a - b;
  }


  // @dev Adds two numbers, throws on overflow.
  function add(uint32 a, uint32 b) internal pure returns (uint32 c) {
    c = a + b;
    assert(c >= a);
    return c;
  }
}

library SafeMath8 {
  // @dev Multiplies two numbers, throws on overflow.
  function mul(uint8 a, uint8 b) internal pure returns (uint8 c) {
    if (a == 0) {
      return 0;
    }
    c = a * b;
    assert(c / a == b);
    return c;
  }


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


  // @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  function sub(uint8 a, uint8 b) internal pure returns (uint8) {
    assert(b <= a);
    return a - b;
  }


  // @dev Adds two numbers, throws on overflow.
  function add(uint8 a, uint8 b) internal pure returns (uint8 c) {
    c = a + b;
    assert(c >= a);
    return c;
  }
}

/// @title A facet of DragonCore that manages special access privileges.
contract DragonAccessControl 
{
    // @dev Non Assigned address.
    address constant NA = address(0);

    /// @dev Contract owner
    address internal controller_;

    /// @dev Contract modes
    enum Mode {TEST, PRESALE, OPERATE}

    /// @dev Contract state
    Mode internal mode_ = Mode.TEST;

    /// @dev OffChain Server accounts ('minions') addresses
    /// It's used for money withdrawal and export of tokens 
    mapping(address => bool) internal minions_;
    
    /// @dev Presale contract address. Can call `presale` method.
    address internal presale_;

    // Modifiers ---------------------------------------------------------------
    /// @dev Limit execution to controller account only.
    modifier controllerOnly() {
        require(controller_ == msg.sender, "controller_only");
        _;
    }

    /// @dev Limit execution to minion account only.
    modifier minionOnly() {
        require(minions_[msg.sender], "minion_only");
        _;
    }

    /// @dev Limit execution to test time only.
    modifier testModeOnly {
        require(mode_ == Mode.TEST, "test_mode_only");
        _;
    }

    /// @dev Limit execution to presale time only.
    modifier presaleModeOnly {
        require(mode_ == Mode.PRESALE, "presale_mode_only");
        _;
    }

    /// @dev Limit execution to operate time only.
    modifier operateModeOnly {
        require(mode_ == Mode.OPERATE, "operate_mode_only");
        _;
    }

     /// @dev Limit execution to presale account only.
    modifier presaleOnly() {
        require(msg.sender == presale_, "presale_only");
        _;
    }

    /// @dev set state to Mode.OPERATE.
    function setOperateMode()
        external 
        controllerOnly
        presaleModeOnly
    {
        mode_ = Mode.OPERATE;
    }

    /// @dev Set presale contract address. Becomes useless when presale is over.
    /// @param _presale Presale contract address.
    function setPresale(address _presale)
        external
        controllerOnly
    {
        presale_ = _presale;
    }

    /// @dev set state to Mode.PRESALE.
    function setPresaleMode()
        external
        controllerOnly
        testModeOnly
    {
        mode_ = Mode.PRESALE;
    }    

        /// @dev Get controller address.
    /// @return Address of contract's controller.
    function controller()
        external
        view
        returns(address)
    {
        return controller_;
    }

    /// @dev Transfer control to new address. Set controller an approvee for
    /// tokens that managed by contract itself. Remove previous controller value
    /// from contract's approvees.
    /// @param _to New controller address.
    function setController(address _to)
        external
        controllerOnly
    {
        require(_to != NA, "_to");
        require(controller_ != _to, "already_controller");

        controller_ = _to;
    }

    /// @dev Check if address is a minion.
    /// @param _addr Address to check.
    /// @return True if address is a minion.
    function isMinion(address _addr)
        public view returns(bool)
    {
        return minions_[_addr];
    }   

    function getCurrentMode() 
        public view returns (Mode) 
    {
        return mode_;
    }    
}

/// @dev token description, storage and transfer functions
contract DragonBase is DragonAccessControl
{
    using SafeMath8 for uint8;
    using SafeMath32 for uint32;
    using SafeMath256 for uint256;
    using StringUtils for string;
    using UintStringUtils for uint;    

    /// @dev The Birth event is fired whenever a new dragon comes into existence. 
    event Birth(address owner, uint256 petId, uint256 tokenId, uint256 parentA, uint256 parentB, string genes, string params);

    /// @dev Token name
    string internal name_;
    /// @dev Token symbol
    string internal symbol_;
    /// @dev Token resolving url
    string internal url_;

    struct DragonToken {
        // Constant Token params
        uint8   genNum;  // generation number. uses for dragon view
        string  genome;  // genome description
        uint256 petId;   // offchain dragon identifier

        // Parents
        uint256 parentA;
        uint256 parentB;

        // Game-depening Token params
        string  params;  // can change in export operation

        // State
        address owner; 
    }

    /// @dev Count of minted tokens
    uint256 internal mintCount_;
    /// @dev Maximum token supply
    uint256 internal maxSupply_;
     /// @dev Count of burn tokens
    uint256 internal burnCount_;

    // Tokens state
    /// @dev Token approvals values
    mapping(uint256 => address) internal approvals_;
    /// @dev Operator approvals
    mapping(address => mapping(address => bool)) internal operatorApprovals_;
    /// @dev Index of token in owner's token list
    mapping(uint256 => uint256) internal ownerIndex_;
    /// @dev Owner's tokens list
    mapping(address => uint256[]) internal ownTokens_;
    /// @dev Tokens
    mapping(uint256 => DragonToken) internal tokens_;

    // @dev Non Assigned address.
    address constant NA = address(0);

    /// @dev Add token to new owner. Increase owner's balance.
    /// @param _to Token receiver.
    /// @param _tokenId New token id.
    function _addTo(address _to, uint256 _tokenId)
        internal
    {
        DragonToken storage token = tokens_[_tokenId];
        require(token.owner == NA, "taken");

        uint256 lastIndex = ownTokens_[_to].length;
        ownTokens_[_to].push(_tokenId);
        ownerIndex_[_tokenId] = lastIndex;

        token.owner = _to;
    }

    /// @dev Create new token and increase mintCount.
    /// @param _genome New token's genome.
    /// @param _params Token params string. 
    /// @param _parentA Token A parent.
    /// @param _parentB Token B parent.
    /// @return New token id.
    function _createToken(
        address _to,
        
        // Constant Token params
        uint8   _genNum,
        string   _genome,
        uint256 _parentA,
        uint256 _parentB,
        
        // Game-depening Token params
        uint256 _petId,
        string   _params        
    )
        internal returns(uint256)
    {
        uint256 tokenId = mintCount_.add(1);
        mintCount_ = tokenId;

        DragonToken memory token = DragonToken(
            _genNum,
            _genome,
            _petId,

            _parentA,
            _parentB,

            _params,
            NA
        );
        
        tokens_[tokenId] = token;
        
        _addTo(_to, tokenId);
        
        emit Birth(_to, _petId, tokenId, _parentA, _parentB, _genome, _params);
        
        return tokenId;
    }    
 
    /// @dev Get token genome.
    /// @param _tokenId Token id.
    /// @return Token's genome.
    function getGenome(uint256 _tokenId)
        external view returns(string)
    {
        return tokens_[_tokenId].genome;
    }

    /// @dev Get token params.
    /// @param _tokenId Token id.
    /// @return Token's params.
    function getParams(uint256 _tokenId)
        external view returns(string)
    {
        return tokens_[_tokenId].params;
    }

    /// @dev Get token parentA.
    /// @param _tokenId Token id.
    /// @return Parent token id.
    function getParentA(uint256 _tokenId)
        external view returns(uint256)
    {
        return tokens_[_tokenId].parentA;
    }   

    /// @dev Get token parentB.
    /// @param _tokenId Token id.
    /// @return Parent token id.
    function getParentB(uint256 _tokenId)
        external view returns(uint256)
    {
        return tokens_[_tokenId].parentB;
    }

    /// @dev Check if `_tokenId` exists. Check if owner is not addres(0).
    /// @param _tokenId Token id
    /// @return Return true if token owner is real.
    function isExisting(uint256 _tokenId)
        public view returns(bool)
    {
        return tokens_[_tokenId].owner != NA;
    }    

    /// @dev Receive maxium token supply value.
    /// @return Contracts `maxSupply_` variable.
    function maxSupply()
        external view returns(uint256)
    {
        return maxSupply_;
    }

    /// @dev Set url prefix for tokenURI generation.
    /// @param _url Url prefix value.
    function setUrl(string _url)
        external controllerOnly
    {
        url_ = _url;
    }

    /// @dev Get token symbol.
    /// @return Token symbol name.
    function symbol()
        external view returns(string)
    {
        return symbol_;
    }

    /// @dev Get token URI to receive offchain information by it's id.
    /// @param _tokenId Token id.
    /// @return URL string. For example "http://erc721.tld/tokens/1".
    function tokenURI(uint256 _tokenId)
        external view returns(string)
    {
        return url_.concat(_tokenId.toString());
    }

     /// @dev Get token name.
    /// @return Token name string.
    function name()
        external view returns(string)
    {
        return name_;
    }

    /// @dev return information about _owner tokens
    function getTokens(address _owner)
        external view  returns (uint256[], uint256[], byte[]) 
    {
        uint256[] memory tokens = ownTokens_[_owner];
        uint256[] memory tokenIds = new uint256[](tokens.length);
        uint256[] memory petIds = new uint256[](tokens.length);

        byte[] memory genomes = new byte[](tokens.length * 77);
        uint index = 0;

        for(uint i = 0; i < tokens.length; i++) {
            uint256 tokenId = tokens[i];
            
            DragonToken storage token = tokens_[tokenId];

            tokenIds[i] = tokenId;
            petIds[i] = token.petId;
            
            bytes storage genome = bytes(token.genome);
            
            for(uint j = 0; j < genome.length; j++) {
                genomes[index++] = genome[j];
            }
        }
        return (tokenIds, petIds, genomes);
    }
    
}

/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens
/// @dev See https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/ERC721.sol

contract ERC721Basic 
{
    /// @dev Emitted when token approvee is set
    event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
    /// @dev Emitted when owner approve all own tokens to operator.
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
    /// @dev Emitted when user deposit some funds.
    event Deposit(address indexed _sender, uint256 _value);
    /// @dev Emitted when user deposit some funds.
    event Withdraw(address indexed _sender, uint256 _value);
    /// @dev Emitted when token transferred to new owner
    event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);

    // Required methods
    function balanceOf(address _owner) external view returns (uint256 _balance);
    function ownerOf(uint256 _tokenId) public view returns (address _owner);
    function exists(uint256 _tokenId) public view returns (bool _exists);
    
    function approve(address _to, uint256 _tokenId) external;
    function getApproved(uint256 _tokenId) public view returns (address _to);

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

    function totalSupply() public view returns (uint256 total);

    // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165)
    function supportsInterface(bytes4 _interfaceID) external view returns (bool);
}

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


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

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

/**
 * @title ERC-721 Non-Fungible Token Standard, full implementation interface
 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract ERC721 is ERC721Basic, ERC721Metadata, ERC721Receiver 
{
    /// @dev Interface signature 721 for interface detection.
    bytes4 constant ERC721_RECEIVED = 0xf0b9e5ba;

    bytes4 constant InterfaceSignature_ERC165 = 0x01ffc9a7;
    /*
    bytes4(keccak256('supportsInterface(bytes4)'));
    */

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

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

    bytes4 constant InterfaceSignature_ERC721 = 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)'));
    */

    function supportsInterface(bytes4 _interfaceID) external view returns (bool)
    {
        return ((_interfaceID == InterfaceSignature_ERC165)
            || (_interfaceID == InterfaceSignature_ERC721)
            || (_interfaceID == InterfaceSignature_ERC721Enumerable)
            || (_interfaceID == InterfaceSignature_ERC721Metadata));
    }    
}

/// @dev ERC721 methods
contract DragonOwnership is ERC721, DragonBase
{
    using StringUtils for string;
    using UintStringUtils for uint;    
    using AddressUtils for address;

    /// @dev Emitted when token transferred to new owner. Additional fields is petId, genes, params
    /// it uses for client-side indication
    event TransferInfo(address indexed _from, address indexed _to, uint256 _tokenId, uint256 petId, string genes, string params);

    /// @dev Specify if _addr is token owner or approvee. Also check if `_addr`
    /// is operator for token owner.
    /// @param _tokenId Token to check ownership of.
    /// @param _addr Address to check if it's an owner or an aprovee of `_tokenId`.
    /// @return True if token can be managed by provided `_addr`.
    function isOwnerOrApproved(uint256 _tokenId, address _addr)
        public view returns(bool)
    {
        DragonToken memory token = tokens_[_tokenId];

        if (token.owner == _addr) {
            return true;
        }
        else if (isApprovedFor(_tokenId, _addr)) {
            return true;
        }
        else if (isApprovedForAll(token.owner, _addr)) {
            return true;
        }

        return false;
    }

    /// @dev Limit execution to token owner or approvee only.
    /// @param _tokenId Token to check ownership of.
    modifier ownerOrApprovedOnly(uint256 _tokenId) {
        require(isOwnerOrApproved(_tokenId, msg.sender), "tokenOwnerOrApproved_only");
        _;
    }

    /// @dev Contract's own token only acceptable.
    /// @param _tokenId Contract's token id.
    modifier ownOnly(uint256 _tokenId) {
        require(tokens_[_tokenId].owner == address(this), "own_only");
        _;
    }

    /// @dev Determine if token is approved for specified approvee.
    /// @param _tokenId Target token id.
    /// @param _approvee Approvee address.
    /// @return True if so.
    function isApprovedFor(uint256 _tokenId, address _approvee)
        public view returns(bool)
    {
        return approvals_[_tokenId] == _approvee;
    }

    /// @dev Specify is given address set as operator with setApprovalForAll.
    /// @param _owner Token owner.
    /// @param _operator Address to check if it an operator.
    /// @return True if operator is set.
    function isApprovedForAll(address _owner, address _operator)
        public view returns(bool)
    {
        return operatorApprovals_[_owner][_operator];
    }

    /// @dev Check if `_tokenId` exists. Check if owner is not addres(0).
    /// @param _tokenId Token id
    /// @return Return true if token owner is real.
    function exists(uint256 _tokenId)
        public view returns(bool)
    {
        return tokens_[_tokenId].owner != NA;
    }

    /// @dev Get owner of a token.
    /// @param _tokenId Token owner id.
    /// @return Token owner address.
    function ownerOf(uint256 _tokenId)
        public view returns(address)
    {
        return tokens_[_tokenId].owner;
    }

    /// @dev Get approvee address. If there is not approvee returns 0x0.
    /// @param _tokenId Token id to get approvee of.
    /// @return Approvee address or 0x0.
    function getApproved(uint256 _tokenId)
        public view returns(address)
    {
        return approvals_[_tokenId];
    }

    /// @dev Grant owner alike controll permissions to third party.
    /// @param _to Permission receiver.
    /// @param _tokenId Granted token id.
    function approve(address _to, uint256 _tokenId)
        external ownerOrApprovedOnly(_tokenId)
    {
        address owner = ownerOf(_tokenId);
        require(_to != owner);

        if (getApproved(_tokenId) != NA || _to != NA) {
            approvals_[_tokenId] = _to;

            emit Approval(owner, _to, _tokenId);
        }
    }

    /// @dev Current total tokens supply. Always less then maxSupply.
    /// @return Difference between minted and burned tokens.
    function totalSupply()
        public view returns(uint256)
    {
        return mintCount_;
    }    

    /// @dev Get number of tokens which `_owner` owns.
    /// @param _owner Address to count own tokens.
    /// @return Count of owned tokens.
    function balanceOf(address _owner)
        external view returns(uint256)
    {
        return ownTokens_[_owner].length;
    }    

    /// @dev Internal set approval for all without _owner check.
    /// @param _owner Granting user.
    /// @param _to New account approvee.
    /// @param _approved Set new approvee status.
    function _setApprovalForAll(address _owner, address _to, bool _approved)
        internal
    {
        operatorApprovals_[_owner][_to] = _approved;

        emit ApprovalForAll(_owner, _to, _approved);
    }

    /// @dev Set approval for all account tokens.
    /// @param _to Approvee address.
    /// @param _approved Value true or false.
    function setApprovalForAll(address _to, bool _approved)
        external
    {
        require(_to != msg.sender);

        _setApprovalForAll(msg.sender, _to, _approved);
    }

    /// @dev Remove approval bindings for token. Do nothing if no approval
    /// exists.
    /// @param _from Address of token owner.
    /// @param _tokenId Target token id.
    function _clearApproval(address _from, uint256 _tokenId)
        internal
    {
        if (approvals_[_tokenId] == NA) {
            return;
        }

        approvals_[_tokenId] = NA;
        emit Approval(_from, NA, _tokenId);
    }

    /// @dev Check if contract was received by other side properly if receiver
    /// is a ctontract.
    /// @param _from Current token owner.
    /// @param _to New token owner.
    /// @param _tokenId token Id.
    /// @param _data Transaction data.
    /// @return True on success.
    function _checkAndCallSafeTransfer(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes _data
    )
        internal returns(bool)
    {
        if (! _to.isContract()) {
            return true;
        }

        bytes4 retval = ERC721Receiver(_to).onERC721Received(
            _from, _tokenId, _data
        );

        return (retval == ERC721_RECEIVED);
    }

    /// @dev Remove token from owner. Unrecoverable.
    /// @param _tokenId Removing token id.
    function _remove(uint256 _tokenId)
        internal
    {
        address owner = tokens_[_tokenId].owner;
        _removeFrom(owner, _tokenId);
    }

    /// @dev Completely remove token from the contract. Unrecoverable.
    /// @param _owner Owner of removing token.
    /// @param _tokenId Removing token id.
    function _removeFrom(address _owner, uint256 _tokenId)
        internal
    {
        uint256 lastIndex = ownTokens_[_owner].length.sub(1);
        uint256 lastToken = ownTokens_[_owner][lastIndex];

        // Swap users token
        ownTokens_[_owner][ownerIndex_[_tokenId]] = lastToken;
        ownTokens_[_owner].length--;

        // Swap token indexes
        ownerIndex_[lastToken] = ownerIndex_[_tokenId];
        ownerIndex_[_tokenId] = 0;

        DragonToken storage token = tokens_[_tokenId];
        token.owner = NA;
    }

    /// @dev Transfer token from owner `_from` to another address or contract
    /// `_to` by it's `_tokenId`.
    /// @param _from Current token owner.
    /// @param _to New token owner.
    /// @param _tokenId token Id.
    function transferFrom( address _from, address _to, uint256 _tokenId )
        public ownerOrApprovedOnly(_tokenId)
    {
        require(_from != NA);
        require(_to != NA);

        _clearApproval(_from, _tokenId);
        _removeFrom(_from, _tokenId);
        _addTo(_to, _tokenId);

        emit Transfer(_from, _to, _tokenId);

        DragonToken storage token = tokens_[_tokenId];
        emit TransferInfo(_from, _to, _tokenId, token.petId, token.genome, token.params);
    }

    /// @dev Update token params and transfer to new owner. Only contract's own
    /// tokens could be updated. Also notifies receiver of the token.
    /// @param _to Address to transfer token to.
    /// @param _tokenId Id of token that should be transferred.
    /// @param _params New token params.
    function updateAndSafeTransferFrom(
        address _to,
        uint256 _tokenId,
        string _params
    )
        public
    {
        updateAndSafeTransferFrom(_to, _tokenId, _params, "");
    }

    /// @dev Update token params and transfer to new owner. Only contract's own
    /// tokens could be updated. Also notifies receiver of the token and send
    /// protion of _data to it.
    /// @param _to Address to transfer token to.
    /// @param _tokenId Id of token that should be transferred.
    /// @param _params New token params.
    /// @param _data Notification data.
    function updateAndSafeTransferFrom(
        address _to,
        uint256 _tokenId,
        string _params,
        bytes _data
    )
        public
    {
        // Safe transfer from
        updateAndTransferFrom(_to, _tokenId, _params, 0, 0);
        require(_checkAndCallSafeTransfer(address(this), _to, _tokenId, _data));
    }

    /// @dev Update token params and transfer to new owner. Only contract's own
    /// tokens could be updated.
    /// @param _to Address to transfer token to.
    /// @param _tokenId Id of token that should be transferred.
    /// @param _params New token params.
    function updateAndTransferFrom(
        address _to,
        uint256 _tokenId,
        string _params,
        uint256 _petId, 
        uint256 _transferCost
    )
        public
        ownOnly(_tokenId)
        minionOnly
    {
        require(bytes(_params).length > 0, "params_length");

        // Update
        tokens_[_tokenId].params = _params;
        if (tokens_[_tokenId].petId == 0 ) {
            tokens_[_tokenId].petId = _petId;
        }

        address from = tokens_[_tokenId].owner;

        // Transfer from
        transferFrom(from, _to, _tokenId);

        // send to the server's wallet the transaction cost
        // withdraw it from the balance of the contract. this amount must be withdrawn from the player
        // on the side of the game server        
        if (_transferCost > 0) {
            msg.sender.transfer(_transferCost);
        }
    }

    /// @dev Transfer token from one owner to new one and check if it was
    /// properly received if receiver is a contact.
    /// @param _from Current token owner.
    /// @param _to New token owner.
    /// @param _tokenId token Id.
    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    )
        public
    {
        safeTransferFrom(_from, _to, _tokenId, "");
    }

    /// @dev Transfer token from one owner to new one and check if it was
    /// properly received if receiver is a contact.
    /// @param _from Current token owner.
    /// @param _to New token owner.
    /// @param _tokenId token Id.
    /// @param _data Transaction data.
    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes _data
    )
        public
    {
        transferFrom(_from, _to, _tokenId);
        require(_checkAndCallSafeTransfer(_from, _to, _tokenId, _data));
    }

    /// @dev Burn owned token. Increases `burnCount_` and decrease `totalSupply`
    /// value.
    /// @param _tokenId Id of burning token.
    function burn(uint256 _tokenId)
        public
        ownerOrApprovedOnly(_tokenId)
    {
        address owner = tokens_[_tokenId].owner;
        _remove(_tokenId);

        burnCount_ += 1;

        emit Transfer(owner, NA, _tokenId);
    }

    /// @dev Receive count of burned tokens. Should be greater than `totalSupply`
    /// but less than `mintCount`.
    /// @return Number of burned tokens
    function burnCount()
        external
        view
        returns(uint256)
    {
        return burnCount_;
    }

    function onERC721Received(address, uint256, bytes)
        public returns(bytes4) 
    {
        return ERC721_RECEIVED;
    }
}



/// @title Managing contract. implements the logic of buying tokens, depositing / withdrawing funds 
/// to the project account and importing / exporting tokens
contract EtherDragonsCore is DragonOwnership 
{
    using SafeMath8 for uint8;
    using SafeMath32 for uint32;
    using SafeMath256 for uint256;
    using AddressUtils for address;
    using StringUtils for string;
    using UintStringUtils for uint;

    // @dev Non Assigned address.
    address constant NA = address(0);

    /// @dev Bounty tokens count limit
    uint256 public constant BOUNTY_LIMIT = 2500;
    /// @dev Presale tokens count limit
    uint256 public constant PRESALE_LIMIT = 7500;
    ///@dev Total gen0tokens generation limit
    uint256 public constant GEN0_CREATION_LIMIT = 90000;
    
    /// @dev Number of tokens minted in presale stage
    uint256 internal presaleCount_;  
    /// @dev Number of tokens minted for bounty campaign
    uint256 internal bountyCount_;
   
    ///@dev Company bank address
    address internal bank_;

    // Extension ---------------------------------------------------------------

    /// @dev Contract is not payable. To fullfil balance method `depositTo`
    /// should be used.
    function ()
        public payable
    {
        revert();
    }

    /// @dev amount on the account of the contract. This amount consists of deposits  from players and the system reserve for payment of transactions
    /// the player at any time to withdraw the amount corresponding to his account in the game, minus the cost of the transaction 
    function getBalance() 
        public view returns (uint256)
    {
        return address(this).balance;
    }    

    /// @dev at the moment of creation of the contract we transfer the address of the bank
    /// presell contract address set later
    constructor(
        address _bank
    )
        public
    {
        require(_bank != NA);
        
        controller_ = msg.sender;
        bank_ = _bank;
        
        // Meta
        name_ = "EtherDragons";
        symbol_ = "ED";
        url_ = "https://game.etherdragons.world/token/";

        // Token mint limit
        maxSupply_ = GEN0_CREATION_LIMIT + BOUNTY_LIMIT + PRESALE_LIMIT;
    }

    /// Number of tokens minted in presale stage
    function totalPresaleCount()
        public view returns(uint256)
    {
        return presaleCount_;
    }    

    /// @dev Number of tokens minted for bounty campaign
    function totalBountyCount()
        public view returns(uint256)
    {
        return bountyCount_;
    }    
    
    /// @dev Check if new token could be minted. Return true if count of minted
    /// tokens less than could be minted through contract deploy.
    /// Also, tokens can not be created more often than once in mintDelay_ minutes
    /// @return True if current count is less then maximum tokens available for now.
    function canMint()
        public view returns(bool)
    {
        return (mintCount_ + presaleCount_ + bountyCount_) < maxSupply_;
    }

    /// @dev Here we write the addresses of the wallets of the server from which it is accessed
    /// to contract methods.
    /// @param _to New minion address
    function minionAdd(address _to)
        external controllerOnly
    {
        require(minions_[_to] == false, "already_minion");
        
        // разрешаем этому адресу пользоваться токенами контакта
        // allow the address to use contract tokens 
        _setApprovalForAll(address(this), _to, true);
        
        minions_[_to] = true;
    }

    /// @dev delete the address of the server wallet
    /// @param _to Minion address
    function minionRemove(address _to)
        external controllerOnly
    {
        require(minions_[_to], "not_a_minion");

        // and forbid this wallet to use tokens of the contract
        _setApprovalForAll(address(this), _to, false);
        minions_[_to] = false;
    }

    /// @dev Here the player can put funds to the account of the contract
    /// and get the same amount of in-game currency
    /// the game server understands who puts money at the wallet address
    function depositTo()
        public payable
    {
        emit Deposit(msg.sender, msg.value);
    }    
    
    /// @dev Transfer amount of Ethers to specified receiver. Only owner can
    // call this method.
    /// @param _to Transfer receiver.
    /// @param _amount Transfer value.
    /// @param _transferCost Transfer cost.
    function transferAmount(address _to, uint256 _amount, uint256 _transferCost)
        external minionOnly
    {
        require((_amount + _transferCost) <= address(this).balance, "not enough money!");
        _to.transfer(_amount);

        // send to the wallet of the server the transfer cost
        // withdraw  it from the balance of the contract. this amount must be withdrawn from the player
        // on the side of the game server
        if (_transferCost > 0) {
            msg.sender.transfer(_transferCost);
        }

        emit Withdraw(_to, _amount);
    }        

   /// @dev Mint new token with specified params. Transfer `_fee` to the
    /// `bank`. 
    /// @param _to New token owner.
    /// @param _fee Transaction fee.
    /// @param _genNum Generation number..
    /// @param _genome New genome unique value.
    /// @param _parentA Parent A.
    /// @param _parentB Parent B.
    /// @param _petId Pet identifier.
    /// @param _params List of parameters for pet.
    /// @param _transferCost Transfer cost.
    /// @return New token id.
    function mintRelease(
        address _to,
        uint256 _fee,
        
        // Constant Token params
        uint8   _genNum,
        string   _genome,
        uint256 _parentA,
        uint256 _parentB,
        
        // Game-depening Token params
        uint256 _petId,  //if petID = 0, then it was created outside of the server
        string   _params,
        uint256 _transferCost
    )
        external minionOnly operateModeOnly returns(uint256)
    {
        require(canMint(), "can_mint");
        require(_to != NA, "_to");
        require((_fee + _transferCost) <= address(this).balance, "_fee");
        require(bytes(_params).length != 0, "params_length");
        require(bytes(_genome).length == 77, "genome_length");
        
        // Parents should be both 0 or both not.
        if (_parentA != 0 && _parentB != 0) {
            require(_parentA != _parentB, "same_parent");
        }
        else if (_parentA == 0 && _parentB != 0) {
            revert("parentA_empty");
        }
        else if (_parentB == 0 && _parentA != 0) {
            revert("parentB_empty");
        }

        uint256 tokenId = _createToken(_to, _genNum, _genome, _parentA, _parentB, _petId, _params);

        require(_checkAndCallSafeTransfer(NA, _to, tokenId, ""), "safe_transfer");

        // Transfer mint fee to the fund
        CommonWallet(bank_).receive.value(_fee)();

        emit Transfer(NA, _to, tokenId);

        // send to the server wallet server the transfer cost,
        // withdraw it from the balance of the contract. this amount must be withdrawn from the player
        // on the side of the game server
        if (_transferCost > 0) {
            msg.sender.transfer(_transferCost);
        }

        return tokenId;
    }

    /// @dev Create new token via presale state
    /// @param _to New token owner.
    /// @param _genome New genome unique value.
    /// @return New token id.
    /// at the pre-sale stage we sell the zero-generation pets, which have only a genome.
    /// other attributes of such a token get when importing to the server
    function mintPresell(address _to, string _genome)
        external presaleOnly presaleModeOnly returns(uint256)
    {
        require(presaleCount_ < PRESALE_LIMIT, "presale_limit");

        // у пресейл пета нет параметров. Их он получит после ввода в игру.
        uint256 tokenId = _createToken(_to, 0, _genome, 0, 0, 0, "");
        presaleCount_ += 1;

        require(_checkAndCallSafeTransfer(NA, _to, tokenId, ""), "safe_transfer");

        emit Transfer(NA, _to, tokenId);
        
        return tokenId;
    }    
    
    /// @dev Create new token for bounty activity
    /// @param _to New token owner.
    /// @return New token id.
    function mintBounty(address _to, string _genome)
        external controllerOnly returns(uint256)
    {
        require(bountyCount_ < BOUNTY_LIMIT, "bounty_limit");

        // bounty pet has no parameters. They will receive them after importing to the game.
        uint256 tokenId = _createToken(_to, 0, _genome, 0, 0, 0, "");
    
        bountyCount_ += 1;
        require(_checkAndCallSafeTransfer(NA, _to, tokenId, ""), "safe_transfer");

        emit Transfer(NA, _to, tokenId);

        return tokenId;
    }        
}

contract Presale
{
    // Extension ---------------------------------------------------------------
    using AddressUtils for address;

    // Events ------------------------------------------------------------------
    ///the event is fired when starting a new wave presale stage
    event StageBegin(uint8 stage, uint256 timestamp);

    ///the event is fired when token sold
    event TokensBought(address buyerAddr, uint256[] tokenIds, bytes genomes);

    // Types -------------------------------------------------------------------
    struct Stage {
        // Predefined values
        uint256 price;      // token's price on the stage
        uint16 softcap;     // stage softCap
        uint16 hardcap;     // stage hardCap
        
        // Unknown values
        uint16 bought;      // sold on stage
        uint32 startDate;   // stage's beginDate
        uint32 endDate;     // stage's endDate
    }
    
    // Constants ---------------------------------------------------------------
    // 10 stages of 5 genocodes
    uint8 public constant STAGES = 10;
    uint8 internal constant TOKENS_PER_STAGE = 5;
    address constant NA = address(0);
    
    // State -------------------------------------------------------------------
    address internal CEOAddress;    // contract owner
    address internal bank_;         // profit wallet address (not a contract)
    address internal erc721_;       // main contract address
    
    /// @dev genomes for bounty stage
    string[TOKENS_PER_STAGE][STAGES] internal genomes_;

    /// stages data
    Stage[STAGES] internal stages_;
    
    // internal transaction counter, it uses for random generator
    uint32  internal counter_;
    
    /// stage is over
    bool    internal isOver_;

    /// stage number
    uint8   internal stageIndex_;

    ///  stage start Data
    uint32  internal stageStart_;

    // Lifetime ----------------------------------------------------------------
    constructor(
        address _bank,  
        address _erc721
    )
        public
    {
        require(_bank != NA, '_bank');
        require(_erc721.isContract(), '_erc721');

        CEOAddress = msg.sender;

        // Addresses should not be the same.
        require(_bank != CEOAddress, "bank = CEO");
        require(CEOAddress != _erc721, "CEO = erc721");
        require(_erc721 != _bank, "bank = erc721");

        // Update state
        bank_ = _bank;
        erc721_ = _erc721;
       
        // stages data 
        stages_[0].price = 10 finney;
        stages_[0].softcap = 100;
        stages_[0].hardcap = 300;
        
        stages_[1].price = 20 finney;
        stages_[1].softcap = 156;
        stages_[1].hardcap = 400;
    
        stages_[2].price = 32 finney;
        stages_[2].softcap = 212;
        stages_[2].hardcap = 500;
        
        stages_[3].price = 45 finney;
        stages_[3].softcap = 268;
        stages_[3].hardcap = 600;
        
        stages_[4].price = 58 finney;
        stages_[4].softcap = 324;
        stages_[4].hardcap = 700;
    
        stages_[5].price = 73 finney;
        stages_[5].softcap = 380;
        stages_[5].hardcap = 800;
    
        stages_[6].price = 87 finney;
        stages_[6].softcap = 436;
        stages_[6].hardcap = 900;
    
        stages_[7].price = 102 finney;
        stages_[7].softcap = 492;
        stages_[7].hardcap = 1000;
    
        stages_[8].price = 118 finney;
        stages_[8].softcap = 548;
        stages_[8].hardcap = 1100;
        
        stages_[9].price = 129 finney;
        stages_[9].softcap = 604;
        stages_[9].hardcap = 1200;
    }

    /// fill the genomes data
    function setStageGenomes(
        uint8 _stage,
        string _genome0, 
        string _genome1,
        string _genome2, 
        string _genome3, 
        string _genome4
    ) 
        external controllerOnly
    {
        genomes_[_stage][0] = _genome0;
        genomes_[_stage][1] = _genome1;
        genomes_[_stage][2] = _genome2;
        genomes_[_stage][3] = _genome3;
        genomes_[_stage][4] = _genome4;
    }

    /// @dev Contract itself is non payable
    function ()
        public payable
    {
        revert();
    }
    
    // Modifiers ---------------------------------------------------------------
    
    /// only from contract owner
    modifier controllerOnly() {
        require(msg.sender == CEOAddress, 'controller_only');
        _;
    }

    /// only for active stage
    modifier notOverOnly() {
        require(isOver_ == false, 'notOver_only');
        _;
    }

    // Getters -----------------------------------------------------------------
    /// owner address
    function getCEOAddress()
        public view returns(address)
    {
        return CEOAddress;
    }

    /// counter from random number generator
    function counter()
        internal view returns(uint32)
    {
        return counter_;
    }

    // tokens sold by stage ...
    function stageTokensBought(uint8 _stage)
        public view returns(uint16)
    {
        return stages_[_stage].bought;
    }

    // stage softcap
    function stageSoftcap(uint8 _stage)
        public view returns(uint16)
    {
        return stages_[_stage].softcap;
    }

    /// stage hardcap
    function stageHardcap(uint8 _stage)
        public view returns(uint16)
    {
        return stages_[_stage].hardcap;
    }

    /// stage Start Date    
    function stageStartDate(uint8 _stage)
        public view returns(uint)
    {
        return stages_[_stage].startDate;
    }
    
    /// stage Finish Date
    function stageEndDate(uint8 _stage)
        public view returns(uint)
    {
        return stages_[_stage].endDate;
    }

    /// stage token price
    function stagePrice(uint _stage)
        public view returns(uint)
    {
        return stages_[_stage].price;
    }
    
    // Genome Logic -----------------------------------------------------------------
    /// within the prelase , the dragons are generated, which are the ancestors of the destiny
    /// newborns have a high chance of mutation and are unlikely to be purebred
    /// the player will have to collect the breed, crossing a lot of pets
    /// In addition, you will need to pick up combat abilities
    /// these characteristics are assigned to the pet when the dragon is imported to the game server.    
    function nextGenome()
        internal returns(string)
    {
        uint8 n = getPseudoRandomNumber();

        counter_ += 1;
        
        return genomes_[stageIndex_][n];
    }

    function getPseudoRandomNumber()
        internal view returns(uint8 index)
    {
        uint8 n = uint8(
            keccak256(abi.encode(msg.sender, block.timestamp + counter_))
        );
        return n % TOKENS_PER_STAGE;
    }
    
    // PreSale Logic -----------------------------------------------------------------
    /// Presale stage0 begin date set
    /// presale start is possible only once    
    function setStartDate(uint32 _startDate)
        external controllerOnly
    {
        require(stages_[0].startDate == 0, 'already_set');
        
        stages_[0].startDate = _startDate;
        stageStart_ = _startDate;
        stageIndex_ = 0;
        
        emit StageBegin(stageIndex_, stageStart_); 
    }

    /// current stage number
    /// switches to the next stage if the time has come
    function stageIndex()
        external view returns(uint8)
    {
        Stage memory stage = stages_[stageIndex_];

        if (stage.endDate > 0 && stage.endDate <= now) {
            return stageIndex_ + 1;
        }
        else {
            return stageIndex_;
        }
    }
    
    /// check whether the phase started
    /// switch to the next stage, if necessary    
    function beforeBuy()
        internal
    {
        if (stageStart_ == 0) {
            revert('presale_not_started');
        }
        else if (stageStart_ > now) {
            revert('stage_not_started');
        }

        Stage memory stage = stages_[stageIndex_];
        if (stage.endDate > 0 && stage.endDate <= now) 
        {
            stageIndex_ += 1;
            stageStart_ = stages_[stageIndex_].startDate;

            if (stageStart_ > now) {
                revert('stage_not_started');
            }
        }
    }
    
    /// time to next midnight
    function midnight()
        public view returns(uint32)
    {
        uint32 tomorrow = uint32(now + 1 days);
        uint32 remain = uint32(tomorrow % 1 days);
        return tomorrow - remain;
    }
    
    /// buying a specified number of tokens
    function buyTokens(uint16 numToBuy)
        public payable notOverOnly returns(uint256[])
    {
        beforeBuy();
        
        require(numToBuy > 0 && numToBuy <= 10, "numToBuy error");

        Stage storage stage = stages_[stageIndex_];
        require((stage.price * numToBuy) <= msg.value, 'price');
        
        uint16 prevBought = stage.bought;
        require(prevBought + numToBuy <= stage.hardcap, "have required tokens");
        
        stage.bought += numToBuy;
        uint256[] memory tokenIds = new uint256[](numToBuy);
        
        bytes memory genomes = new bytes(numToBuy * 77);
        uint32 genomeByteIndex = 0;

        for(uint16 t = 0; t < numToBuy; t++) 
        {
            string memory genome = nextGenome();
            uint256 tokenId = EtherDragonsCore(erc721_).mintPresell(msg.sender, genome);

            bytes memory genomeBytes = bytes(genome);
            
            for(uint8 gi = 0; gi < genomeBytes.length; gi++) {
                genomes[genomeByteIndex++] = genomeBytes[gi];
            }

            tokenIds[t] = tokenId;
        }

        // Transfer mint fee to the fund
        bank_.transfer(address(this).balance);

        if (stage.bought == stage.hardcap) {
            stage.endDate = uint32(now);
            stageStart_ = midnight() + 1 days + 1 seconds;
            if (stageIndex_ < STAGES - 1) {
                stageIndex_ += 1;
            }
            else {
                isOver_ = true;
            }
        }
        else if (stage.bought >= stage.softcap && prevBought < stage.softcap) {
            stage.endDate = midnight() + 1 days;
            if (stageIndex_ < STAGES - 1) {
                stages_[stageIndex_ + 1].startDate = stage.endDate + 1 days;
            }
        }

        emit TokensBought(msg.sender, tokenIds, genomes);

        return tokenIds;
    }

    function currTime()
        public view returns(uint)
    {
        return now;
    }
    
    /// stages data
    function getStagesInfo() 
        public view returns (uint256[] prices, uint16[] softcaps, uint16[] hardcaps, uint16[] boughts) 
    {
            prices = new uint256[](STAGES);
            softcaps = new uint16[](STAGES);
            hardcaps = new uint16[](STAGES);
            boughts = new uint16[](STAGES);
            
            for(uint8 s = 0; s < STAGES; s++) {
                prices[s] = stages_[s].price;
                softcaps[s] = stages_[s].softcap;
                hardcaps[s] = stages_[s].hardcap;
                boughts[s] = stages_[s].bought;
            }
    }
    
    /// stages dates data
    function getStagesBeginEnd() 
        public view returns (uint32[] startDates, uint32[] endDates) 
    {
        startDates = new uint32[](STAGES);
        endDates = new uint32[](STAGES);
        
        for(uint8 s = 0; s < STAGES; s++) {
            startDates[s] = stages_[s].startDate;
            endDates[s] = stages_[s].endDate;
        }
    }

    /// returns data which genomes can be purchased at the stage
    function stageGenomes(uint8 _stage)
        public view returns(byte[])
    {
        byte[] memory genomes = new byte[](uint16(TOKENS_PER_STAGE) * 77);
        uint32 gbIndex = 0;

        for(uint8 tokenIndex = 0; tokenIndex < TOKENS_PER_STAGE; tokenIndex++) {
            
            bytes memory genomeBytes = bytes(genomes_[_stage][tokenIndex]);
            
            for(uint8 gi = 0; gi < genomeBytes.length; gi++) {
                genomes[gbIndex++] = genomeBytes[gi];
            }
        }

        return genomes;
    }
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[{"name":"_stage","type":"uint8"}],"name":"stageEndDate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"numToBuy","type":"uint16"}],"name":"buyTokens","outputs":[{"name":"","type":"uint256[]"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"currTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_stage","type":"uint8"},{"name":"_genome0","type":"string"},{"name":"_genome1","type":"string"},{"name":"_genome2","type":"string"},{"name":"_genome3","type":"string"},{"name":"_genome4","type":"string"}],"name":"setStageGenomes","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getStagesBeginEnd","outputs":[{"name":"startDates","type":"uint32[]"},{"name":"endDates","type":"uint32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_stage","type":"uint8"}],"name":"stageTokensBought","outputs":[{"name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"STAGES","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"midnight","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_stage","type":"uint8"}],"name":"stageHardcap","outputs":[{"name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStagesInfo","outputs":[{"name":"prices","type":"uint256[]"},{"name":"softcaps","type":"uint16[]"},{"name":"hardcaps","type":"uint16[]"},{"name":"boughts","type":"uint16[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_stage","type":"uint8"}],"name":"stageStartDate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_stage","type":"uint8"}],"name":"stageGenomes","outputs":[{"name":"","type":"bytes1[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_startDate","type":"uint32"}],"name":"setStartDate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_stage","type":"uint256"}],"name":"stagePrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_stage","type":"uint8"}],"name":"stageSoftcap","outputs":[{"name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCEOAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stageIndex","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_bank","type":"address"},{"name":"_erc721","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"stage","type":"uint8"},{"indexed":false,"name":"timestamp","type":"uint256"}],"name":"StageBegin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"buyerAddr","type":"address"},{"indexed":false,"name":"tokenIds","type":"uint256[]"},{"indexed":false,"name":"genomes","type":"bytes"}],"name":"TokensBought","type":"event"}]

60806040523480156200001157600080fd5b5060405160408062001f04833981016040528051602090910151600160a060020a0382161515620000a357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f5f62616e6b000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b620000c5600160a060020a03821664010000000062001a7e6200043a82021704565b15156200013357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f5f65726337323100000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60008054600160a060020a031916331790819055600160a060020a0383811691161415620001c257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f62616e6b203d2043454f00000000000000000000000000000000000000000000604482015290519081900360640190fd5b600054600160a060020a03828116911614156200024057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f43454f203d206572633732310000000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038181169083161415620002bc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f62616e6b203d2065726337323100000000000000000000000000000000000000604482015290519081900360640190fd5b60018054600160a060020a03938416600160a060020a03199182161790915560028054929093169116179055662386f26fc1000060355560368054606461ffff199182161763ffff00001990811663012c00001790925566470de4df820000603755603880548216609c17831663019000001790556671afd498d00000603955603a8054821660d41783166301f40000179055669fdf42f6e48000603b55603c8054630258000090831661010c17841617905566ce0eb154f90000603d55603e80546302bc0000908316610144178416179055670103591cfc9a8000603f5560408054630320000090831661017c1784161790556701351609ff7580006041556042805463038400009083166101b417841617905567016a6075a7170000604355604480546303e800009083166101ec1784161790556701a3385ff37f00006045556046805463044c00009083166102241784161790556701ca4cd108068000604755604880546304b00000921661025c1790921617905562000442565b6000903b1190565b611ab280620004526000396000f3006080604052600436106100ef5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416628fcc9481146100f45780630e662cf0146101215780631a6af7b7146101805780633fefdb011461019557806342d2c127146101ee5780634cd445191461029c5780635706d99a146102ce5780637372014e146102f95780637c79c167146103275780637dec22991461034257806384e64a1f1461047a5780639b3725e814610495578063c373c0ef146104b0578063c43b7934146104ce578063cfd129f8146104e6578063dc2af3de14610501578063dc97e36614610532575b600080fd5b34801561010057600080fd5b5061010f60ff60043516610547565b60408051918252519081900360200190f35b61013061ffff6004351661057e565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561016c578181015183820152602001610154565b505050509050019250505060405180910390f35b34801561018c57600080fd5b5061010f610d02565b3480156101a157600080fd5b506101ec6004803560ff16906024803580820192908101359160443580820192908101359160643580820192908101359160843580820192908101359160a435908101910135610d07565b005b3480156101fa57600080fd5b50610203610e2f565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561024757818101518382015260200161022f565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561028657818101518382015260200161026e565b5050505090500194505050505060405180910390f35b3480156102a857600080fd5b506102b760ff60043516610f34565b6040805161ffff9092168252519081900360200190f35b3480156102da57600080fd5b506102e3610f63565b6040805160ff9092168252519081900360200190f35b34801561030557600080fd5b5061030e610f68565b6040805163ffffffff9092168252519081900360200190f35b34801561033357600080fd5b506102b760ff60043516610f7f565b34801561034e57600080fd5b50610357610fae565b6040518080602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b838110156103a357818101518382015260200161038b565b50505050905001858103845288818151815260200191508051906020019060200280838360005b838110156103e25781810151838201526020016103ca565b50505050905001858103835287818151815260200191508051906020019060200280838360005b83811015610421578181015183820152602001610409565b50505050905001858103825286818151815260200191508051906020019060200280838360005b83811015610460578181015183820152602001610448565b505050509050019850505050505050505060405180910390f35b34801561048657600080fd5b5061010f60ff60043516611170565b3480156104a157600080fd5b5061013060ff600435166111a7565b3480156104bc57600080fd5b506101ec63ffffffff6004351661133b565b3480156104da57600080fd5b5061010f600435611494565b3480156104f257600080fd5b506102b760ff600435166114ae565b34801561050d57600080fd5b506105166114d2565b60408051600160a060020a039092168252519081900360200190f35b34801561053e57600080fd5b506102e36114e1565b6000603560ff8316600a811061055957fe5b60020201600101600a9054906101000a900463ffffffff1663ffffffff169050919050565b60606000806060806000806060600060606000604960049054906101000a900460ff161515600015151415156105fe576040805160e560020a62461bcd02815260206004820152600c60248201527f6e6f744f7665725f6f6e6c790000000000000000000000000000000000000000604482015290519081900360640190fd5b6106066115cd565b60008c61ffff1611801561061f5750600a8c61ffff1611155b1515610675576040805160e560020a62461bcd02815260206004820152600e60248201527f6e756d546f427579206572726f72000000000000000000000000000000000000604482015290519081900360640190fd5b60495460359065010000000000900460ff16600a811061069157fe5b600202019950348c61ffff168b6000015402111515156106fb576040805160e560020a62461bcd02815260206004820152600560248201527f7072696365000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60018a015461ffff640100000000820481169a506201000090910481168d8b019091161115610774576040805160e560020a62461bcd02815260206004820152601460248201527f6861766520726571756972656420746f6b656e73000000000000000000000000604482015290519081900360640190fd5b8b8a60010160048282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff1602179055508b61ffff166040519080825280602002602001820160405280156107d4578160200160208202803883390190505b5097508b604d0261ffff166040519080825280601f01601f19166020018201604052801561080c578160200160208202803883390190505b50965060009550600094505b8b61ffff168561ffff1610156109e35761083061182f565b600254604080517f2774d052000000000000000000000000000000000000000000000000000000008152336004820181815260248301938452855160448401528551959950600160a060020a0390941694632774d0529491938a939091606490910190602085019080838360005b838110156108b657818101518382015260200161089e565b50505050905090810190601f1680156108e35780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561090357600080fd5b505af1158015610917573d6000803e3d6000fd5b505050506040513d602081101561092d57600080fd5b50519250839150600090505b81518160ff1610156109bb57818160ff1681518110151561095657fe5b90602001015160f860020a900460f860020a02878780600101985063ffffffff1681518110151561098357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101610939565b82888661ffff168151811015156109ce57fe5b60209081029091010152600190940193610818565b600154604051600160a060020a0390911690303180156108fc02916000818181858888f19350505050158015610a1d573d6000803e3d6000fd5b5060018a0154640100000000810461ffff90811662010000909204161415610b055760018a0180546dffffffff0000000000000000000019166a01000000000000000000004263ffffffff1602179055610a75610f68565b6049805463ffffffff620151819093019290921666010000000000000269ffffffff00000000000019909216919091179081905560096501000000000090910460ff161015610aea576049805460ff6501000000000080830482166001019091160265ff000000000019909116179055610b00565b6049805464ff0000000019166401000000001790555b610bf9565b60018a015461ffff8082166401000000009092041610801590610b33575060018a015461ffff908116908a16105b15610bf957610b40610f68565b60018b01805463ffffffff6201518093909301929092166a0100000000000000000000026dffffffff000000000000000000001990921691909117905560495460096501000000000090910460ff161015610bf95789600101600a9054906101000a900463ffffffff1662015180016035604960059054906101000a900460ff1660010160ff16600a81101515610bd357fe5b6002020160010160066101000a81548163ffffffff021916908363ffffffff1602179055505b7ff9283f66e053ed95650ff2d732203a435bce1beb3c83a63fc07031fe6888e9633389896040518084600160a060020a0316600160a060020a031681526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610c79578181015183820152602001610c61565b50505050905001838103825284818151815260200191508051906020019080838360005b83811015610cb5578181015183820152602001610c9d565b50505050905090810190601f168015610ce25780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a150959a9950505050505050505050565b425b90565b600054600160a060020a03163314610d69576040805160e560020a62461bcd02815260206004820152600f60248201527f636f6e74726f6c6c65725f6f6e6c790000000000000000000000000000000000604482015290519081900360640190fd5b8989600360ff8e16600a8110610d7b57fe5b600502016000610d8d939101916119b5565b508787600360ff8e16600a8110610da057fe5b600502016001610db2939101916119b5565b508585600360ff8e16600a8110610dc557fe5b600502016002610dd7939101916119b5565b508383600360ff8e16600a8110610dea57fe5b600502016003610dfc939101916119b5565b508181600360ff8e16600a8110610e0f57fe5b600502016004610e21939101916119b5565b505050505050505050505050565b60408051600a808252610160820190925260609182916000916020820161014080388339505060408051600a808252610160820190925292955090506020820161014080388339019050509150600090505b600a60ff82161015610f2f57603560ff8216600a8110610e9d57fe5b6002020160010160069054906101000a900463ffffffff16838260ff16815181101515610ec657fe5b63ffffffff909216602092830290910190910152603560ff8216600a8110610eea57fe5b60020201600101600a9054906101000a900463ffffffff16828260ff16815181101515610f1357fe5b63ffffffff909216602092830290910190910152600101610e81565b509091565b6000603560ff8316600a8110610f4657fe5b6002020160010160049054906101000a900461ffff169050919050565b600a81565b620151804280820163ffffffff1682900690030190565b6000603560ff8316600a8110610f9157fe5b6002020160010160029054906101000a900461ffff169050919050565b60408051600a80825261016082019092526060918291829182916000916020820161014080388339505060408051600a808252610160820190925292975090506020820161014080388339505060408051600a808252610160820190925292965090506020820161014080388339505060408051600a808252610160820190925292955090506020820161014080388339019050509150600090505b600a60ff8216101561116957603560ff8216600a811061106657fe5b60020201548551869060ff841690811061107c57fe5b60209081029091010152603560ff8216600a811061109657fe5b6002020160010160009054906101000a900461ffff16848260ff168151811015156110bd57fe5b61ffff909216602092830290910190910152603560ff8216600a81106110df57fe5b6002020160010160029054906101000a900461ffff16838260ff1681518110151561110657fe5b61ffff909216602092830290910190910152603560ff8216600a811061112857fe5b6002020160010160049054906101000a900461ffff16828260ff1681518110151561114f57fe5b61ffff90921660209283029091019091015260010161104a565b5090919293565b6000603560ff8316600a811061118257fe5b6002020160010160069054906101000a900463ffffffff1663ffffffff169050919050565b604080516101818082526130408201909252606091829160009182918491839190602082016130208038833901905050945060009350600092505b600560ff8416101561133057600360ff8816600a81106111fe57fe5b600502018360ff1660058110151561121257fe5b01805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156112975780601f1061126c57610100808354040283529160200191611297565b820191906000526020600020905b81548152906001019060200180831161127a57829003601f168201915b50505050509150600090505b81518160ff16101561132557818160ff168151811015156112c057fe5b90602001015160f860020a900460f860020a02858580600101965063ffffffff168151811015156112ed57fe5b7fff000000000000000000000000000000000000000000000000000000000000009092166020928302909101909101526001016112a3565b6001909201916111e2565b509295945050505050565b600054600160a060020a0316331461139d576040805160e560020a62461bcd02815260206004820152600f60248201527f636f6e74726f6c6c65725f6f6e6c790000000000000000000000000000000000604482015290519081900360640190fd5b6036546601000000000000900463ffffffff1615611405576040805160e560020a62461bcd02815260206004820152600b60248201527f616c72656164795f736574000000000000000000000000000000000000000000604482015290519081900360640190fd5b6036805469ffffffff00000000000019908116660100000000000063ffffffff85811682029283179094556049805490931690911765ff00000000001916918290556040805160ff65010000000000850416815291909204909216602083015280517f46ce46adbcf66e5ccfb3981ba099c455f1b0d9cee3f1d54bbd37d3762c6a43a39281900390910190a150565b6000603582600a81106114a357fe5b600202015492915050565b6000603560ff8316600a81106114c057fe5b600202016001015461ffff1692915050565b600054600160a060020a031690565b60006114eb611a2f565b60495460359065010000000000900460ff16600a811061150757fe5b6040805160c08101825260029290920292909201805482526001015461ffff80821660208401526201000082048116938301939093526401000000008104909216606082015263ffffffff66010000000000008304811660808301526a010000000000000000000090920490911660a0820181905290915060001080156115985750428160a0015163ffffffff1611155b156115b757604960059054906101000a900460ff1660010191506115c9565b60495465010000000000900460ff1691505b5090565b6115d5611a2f565b6049546601000000000000900463ffffffff16151561163e576040805160e560020a62461bcd02815260206004820152601360248201527f70726573616c655f6e6f745f7374617274656400000000000000000000000000604482015290519081900360640190fd5b60495442660100000000000090910463ffffffff1611156116a9576040805160e560020a62461bcd02815260206004820152601160248201527f73746167655f6e6f745f73746172746564000000000000000000000000000000604482015290519081900360640190fd5b60495460359065010000000000900460ff16600a81106116c557fe5b6040805160c08101825260029290920292909201805482526001015461ffff80821660208401526201000082048116938301939093526401000000008104909216606082015263ffffffff66010000000000008304811660808301526a010000000000000000000090920490911660a0820181905290915060001080156117565750428160a0015163ffffffff1611155b1561182c576049805460ff6501000000000080830482166001018216810265ff00000000001990931692909217928390556035929190910416600a811061179957fe5b60020201600101546049805469ffffffff000000000000191666010000000000009283900463ffffffff90811684029190911791829055429290910416111561182c576040805160e560020a62461bcd02815260206004820152601160248201527f73746167655f6e6f745f73746172746564000000000000000000000000000000604482015290519081900360640190fd5b50565b6060600061183b61191a565b6049805463ffffffff8082166001011663ffffffff19909116179081905590915060039060ff6501000000000090910416600a811061187657fe5b600502018160ff1660058110151561188a57fe5b01805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561190f5780601f106118e45761010080835404028352916020019161190f565b820191906000526020600020905b8154815290600101906020018083116118f257829003601f168201915b505050505091505090565b604954604080513360208083019190915263ffffffff909316420181830152815180820383018152606090910191829052805160009384939182918401908083835b6020831061197b5780518252601f19909201916020918201910161195c565b5181516020939093036101000a60001901801990911692169190911790526040519201829003909120600560ff9091160695945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106119f65782800160ff19823516178555611a23565b82800160010185558215611a23579182015b82811115611a23578235825591602001919060010190611a08565b506115c9929150611a64565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b610d0491905b808211156115c95760008155600101611a6a565b6000903b11905600a165627a7a723058200929c159307ddb3761ae8bf080321af40e57372033ae728f7b972f2a3b21b7aa0029000000000000000000000000aa7b1425d5f79386235c84e180874da8b63dc2920000000000000000000000001680855238bf0dfb458dcf46ceb146b18ef65bd2

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000aa7b1425d5f79386235c84e180874da8b63dc2920000000000000000000000001680855238bf0dfb458dcf46ceb146b18ef65bd2

-----Decoded View---------------
Arg [0] : _bank (address): 0xaA7B1425d5f79386235c84E180874DA8B63dc292
Arg [1] : _erc721 (address): 0x1680855238bf0dfb458dcF46CEb146b18EF65BD2

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000aa7b1425d5f79386235c84e180874da8b63dc292
Arg [1] : 0000000000000000000000001680855238bf0dfb458dcf46ceb146b18ef65bd2


Swarm Source

bzzr://0929c159307ddb3761ae8bf080321af40e57372033ae728f7b972f2a3b21b7aa

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.