Contract Overview
Balance: 0 Ether
Ether Value: $0
Transactions: 32197 txns
Token Tracker: LucidSight-MLB-NFT (MLBCB)
 Latest 25 txns From a total of 32197 Transactions
(+3 PendingTxns)

TxHash Age From To Value [TxFee]
0x390ddf7508ef773ba5b32bc56257cc4b08345a8e16b74079ecbab348552d0012(pending)0xaaae46bfff7e94470d83e19249593d12b28a4319  IN  0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether(Pending)
0x36e4452b12227067300c2c7d86962cf7c1a2d6d991d50a78659dbeb1d29d61ca(pending)0xaaae46bfff7e94470d83e19249593d12b28a4319  IN  0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether(Pending)
0x80ecd17f1ee21c19f6c7580aec8e125505b6d7602e37e9ad5a7f1792d23b0c75(pending)0x7c981d8a87ff2f2850831ff954a05ec35d587c3c  IN  0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether(Pending)
0xa6848512affc7edaf2f7273b8fdcd7ece1e0a0278143839c1adfdecaec4c4d2a3 mins ago0x3b69b109c636e12728e0ca188869a199974b4630  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.00054065
0x672c8ee69de69ca867008bffeb28f87b279360fe4a00852b1059cc52157275824 mins ago0x3b69b109c636e12728e0ca188869a199974b4630  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.00054065
0xa764add1c9f1127cf68d4c987527214825ff317cacf10d499e9aab52d3fb3b5e4 mins ago0x3b69b109c636e12728e0ca188869a199974b4630  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.000432264
0x6d25da16bef8e56290d9f5f3cad5420eace3a6b2f23550bcfd67fbdaf1064be64 mins ago0xaaae46bfff7e94470d83e19249593d12b28a4319  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.00043252
0xc841b597c9945491e3095ac540418ff289b53b24ebd658961feab0873d052ba35 mins ago0x3b69b109c636e12728e0ca188869a199974b4630  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.00054065
0xe9a7b44b86473741d7c55219cd4021e6154fc21c42cd2cf7cc27823bc2b28b4d5 mins ago0x3b69b109c636e12728e0ca188869a199974b4630  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.00043252
0xc27092dc0eb57b46ac3e6babba6c55a9f1677622c74febb12197665522b675f55 mins ago0x3b69b109c636e12728e0ca188869a199974b4630  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.00043252
0xee116d07208ab03c7d37824116511bca4d2c41a58c9b17007cd1444246991e0a8 mins ago0xbe765522dde34573dad56b353a084ef60f4fa826  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.001532025
0xdb8f984f4302151269e192f3e88fced3275104ca63bf02f5f1b027682c4bad1817 mins ago0xd9691115ea01a9c066ee8e098e0370e2b35764fd  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.00122562
0x0a773e0429ec79bc3677d4ff1eaeb6bc9bf8289499f2c6c361127f5a825aabe920 mins ago0x5302d0b614947ec0b2c3607c838ceb0262027560  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.001531385
0x01e5ab405f102f86fdfdd0e09b530d26abd267cecf2c1f740a60bf85e70728fa23 mins ago0x5302d0b614947ec0b2c3607c838ceb0262027560  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.001225364
0x7f3be7ff62872e27c06b01de4efec22fefe13323d6c0d4d98cf2668c8ab8a6b823 mins ago0xd9691115ea01a9c066ee8e098e0370e2b35764fd  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.00122562
0x80d3636a98f8687dfdbf2d35ff6287701c23bd93e9a04b505e4b71adea437b4d23 mins ago0x0b4f222cb69554ee96bae54abbd5583d40539266  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.001531385
0xc834a57417892a8d4830666254384d82d0165485f835dc186ae5fbc44dddcb0e31 mins ago0xd9691115ea01a9c066ee8e098e0370e2b35764fd  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.001225364
0x065096ccc839a98891216b3576ba55209517f5ebd3f59ea3106d17397003b69e37 mins ago0xd9691115ea01a9c066ee8e098e0370e2b35764fd  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.001225108
0x74dc39d41c70eac24887d85ed787ae8415fa5bd9b035cb5d250f897322b479a142 mins ago0xcecbe670c11d4d28678955f23e0d2d708d79c893  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.000648396
0x3c0e4e07850e0078ae8d3d9b47145414872fb02569747c95d172b934f254388b43 mins ago0xd9691115ea01a9c066ee8e098e0370e2b35764fd  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.001225364
0x8a6b0b29193717df7fd695a523e49f63c382d1ad0c610dee260b4a35c9693a7843 mins ago0xcecbe670c11d4d28678955f23e0d2d708d79c893  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.000648396
0xd8702945faf7d89bd34cb9afa39d18494c9ab7bdc02ff0e66773082da904e85843 mins ago0xcecbe670c11d4d28678955f23e0d2d708d79c893  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.00054033
0xe222f7a82ae77337949a7bc270f66e668b7eb53cb8c82d80f390c097f3902e4445 mins ago0x762fba3875baf5dfa20bfc05588ed377dc739f9a  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.001225108
0x0081fbef228c7153890378226c0323c2b507b72a6325cb6f282763d40490e9ea49 mins ago0x762fba3875baf5dfa20bfc05588ed377dc739f9a  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.001225108
0x439f619b032344eb18b4c8f08560e9c70acd35ef37f86a588b74db04d87c73fd50 mins ago0x762fba3875baf5dfa20bfc05588ed377dc739f9a  IN   0x8c9b261faef3b3c2e64ab5e58e04615f8c7880990 Ether0.001225108
[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
View All
ParentTxHash Block Age From To Value
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: MLBNFT
Compiler Text: v0.4.24+commit.e67f0147
Optimization Enabled: Yes
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

/**
 * Created on 2018-06-05 16:37
 * @summary: Our NFT Minting Contract which inherits ERC721 capability from LSNFT
 * @author: Fazri Zubair & Farhan Khwaja
 */
pragma solidity ^0.4.23;

pragma solidity ^0.4.23;

/* NFT Metadata Schema 
{
    "title": "Asset Metadata",
    "type": "object",
    "properties": {
        "name": {
            "type": "string",
            "description": "Identifies the asset to which this NFT represents",
        },
        "description": {
            "type": "string",
            "description": "Describes the asset to which this NFT represents",
        },
        "image": {
            "type": "string",
            "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.",
        }
    }
}
*/

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

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

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

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

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

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

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

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

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

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

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

/**
 * @title ERC721 Non-Fungible Token Standard basic implementation
 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract ERC721BasicToken is ERC721Basic {
    using SafeMath for uint256;
    using AddressUtils for address;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        emit Transfer(_from, _to, _tokenId);
    }

    /**
    * @dev Safely transfers the ownership of a given token ID to another address
    * @dev 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.
    * @dev Requires the msg sender to be the owner, approved, or operator
    * @param _from current owner of the token
    * @param _to address to receive the ownership of the given token ID
    * @param _tokenId uint256 ID of the token to be transferred
    */
    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    )
        public
        canTransfer(_tokenId)
    {
        // solium-disable-next-line arg-overflow
        safeTransferFrom(_from, _to, _tokenId, "");
    }

    /**
    * @dev Safely transfers the ownership of a given token ID to another address
    * @dev 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.
    * @dev Requires the msg sender to be the owner, approved, or operator
    * @param _from current owner of the token
    * @param _to address to receive the ownership of the given token ID
    * @param _tokenId uint256 ID of the token to be transferred
    * @param _data bytes data to send along with a safe transfer check
    */
    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes _data
    )
        public
        canTransfer(_tokenId)
    {
        transferFrom(_from, _to, _tokenId);
        // solium-disable-next-line arg-overflow
        require (checkAndCallSafeTransfer(_from, _to, _tokenId, _data));
    }

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

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

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

    /**
    * @notice Handle the receipt of an NFT
    * @dev The ERC721 smart contract calls this function on the recipient
    *  after a `safetransfer`. This function MAY throw to revert and reject the
    *  transfer. 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,address,uint256,bytes)"))`
    */
    function onERC721Received(
        address _operator,
        address _from,
        uint256 _tokenId,
        bytes _data
    )
        public
        returns(bytes4);
}

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

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

    // Token name
    string internal name_;

    // Token symbol
    string internal symbol_;

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

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

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

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

    // Base Server Address for Token MetaData URI
    string internal tokenURIBase;

    /**
    * @dev Returns an URI for a given token ID
    * @dev Throws if the token ID does not exist. May return an empty string.
    * @notice The user/developper needs to add the tokenID, in the end of URL, to 
    * use the URI and get all details. Ex. www.<apiURL>.com/token/<tokenID>
    * @param _tokenId uint256 ID of the token to query
    */
    function tokenURI(uint256 _tokenId) public view returns (string) {
        require (exists(_tokenId));
        return tokenURIBase;
    }

    /**
    * @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
    * @dev Reverts if the index is greater or equal to the total number of tokens
    * @param _index uint256 representing the index to be accessed of the tokens list
    * @return uint256 token ID at the given index of the tokens list
    */
    function tokenByIndex(uint256 _index) public view returns (uint256) {
        require (_index < totalSupply());
        return allTokens[_index];
    }


    /**
    * @dev Internal function to set the token URI for a given token
    * @dev Reverts if the token ID does not exist
    * @param _uri string URI to assign
    */
    function _setTokenURIBase(string _uri) internal {
        tokenURIBase = _uri;
    }

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

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

        // 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 Gets the token name
    * @return string representing the token name
    */
    function name() public view returns (string) {
        return name_;
    }

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

    /**
    * @dev Internal function to mint a new token
    * @dev 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
    * @dev 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;
    }

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

    bytes4 public constant InterfaceSignature_ERC721Optional =- 0x4f558e79;
    /*
    bytes4(keccak256('exists(uint256)'));
    */

    /**
    * @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165).
    * @dev Returns true for any standardized interfaces implemented by this contract.
    * @param _interfaceID bytes4 the interface to check for
    * @return true for any standardized interfaces implemented by this contract.
    */
    function supportsInterface(bytes4 _interfaceID) external view returns (bool)
    {
        return ((_interfaceID == InterfaceSignature_ERC165)
        || (_interfaceID == InterfaceSignature_ERC721)
        || (_interfaceID == InterfaceSignature_ERC721Enumerable)
        || (_interfaceID == InterfaceSignature_ERC721Metadata));
    }

    function implementsERC721() public pure returns (bool) {
        return true;
    }

}
/* Lucid Sight, Inc. ERC-721 Collectibles. 
 * @title LSNFT - Lucid Sight, Inc. Non-Fungible Token
 * @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.)
 */
contract LSNFT is ERC721Token {
  
  /*** EVENTS ***/

  /// @dev The Created event is fired whenever a new collectible comes into existence.
  event Created(address owner, uint256 tokenId);
  
  /*** DATATYPES ***/
  
  struct NFT {
    // The sequence of potential attributes a Collectible has and can provide in creation events. Used in Creation logic to spwan new Cryptos
    uint256 attributes;

    // Current Game Card identifier
    uint256 currentGameCardId;

    // MLB Game Identifier (if asset generated as a game reward)
    uint256 mlbGameId;

    // player orverride identifier
    uint256 playerOverrideId;

    // official MLB Player ID
    uint256 mlbPlayerId;

    // earnedBy : In some instances we may want to retroactively write which MLB player triggered
    // the event that created a Legendary Trophy. This optional field should be able to be written
    // to after generation if we determine an event was newsworthy enough
    uint256 earnedBy;
    
    // asset metadata
    uint256 assetDetails;
    
    // Attach/Detach Flag
    uint256 isAttached;
  }

  NFT[] allNFTs;

  function isLSNFT() public view returns (bool) {
    return true;
  }

  /// For creating NFT
  function _createNFT (
    uint256[5] _nftData,
    address _owner,
    uint256 _isAttached)
    internal
    returns(uint256) {

    NFT memory _lsnftObj = NFT({
        attributes : _nftData[1],
        currentGameCardId : 0,
        mlbGameId : _nftData[2],
        playerOverrideId : _nftData[3],
        assetDetails: _nftData[0],
        isAttached: _isAttached,
        mlbPlayerId: _nftData[4],
        earnedBy: 0
    });

    uint256 newLSNFTId = allNFTs.push(_lsnftObj) - 1;

    _mint(_owner, newLSNFTId);
    
    // Created event
    emit Created(_owner, newLSNFTId);

    return newLSNFTId;
  }

  /// @dev Gets attributes of NFT  
  function _getAttributesOfToken(uint256 _tokenId) internal returns(NFT) {
    NFT storage lsnftObj = allNFTs[_tokenId];  
    return lsnftObj;
  }

  function _approveForSale(address _owner, address _to, uint256 _tokenId) internal {
    address owner = ownerOf(_tokenId);
    require (_to != owner);
    require (_owner == owner || isApprovedForAll(owner, _owner));

    if (getApproved(_tokenId) != address(0) || _to != address(0)) {
        tokenApprovals[_tokenId] = _to;
        emit Approval(_owner, _to, _tokenId);
    }
  }
}

/** Controls state and access rights for contract functions
 * @title Operational Control
 * @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.)
 * Inspired and adapted from contract created by OpenZeppelin 
 * Ref: https://github.com/OpenZeppelin/zeppelin-solidity/
 */
contract OperationalControl {
    /// Facilitates access & control for the game.
    /// Roles:
    ///  -The Managers (Primary/Secondary): Has universal control of all elements (No ability to withdraw)
    ///  -The Banker: The Bank can withdraw funds and adjust fees / prices.
    ///  -otherManagers: Contracts that need access to functions for gameplay

    /// @dev Emited when contract is upgraded
    event ContractUpgrade(address newContract);

    /// @dev The addresses of the accounts (or contracts) that can execute actions within each roles.
    address public managerPrimary;
    address public managerSecondary;
    address public bankManager;

    // Contracts that require access for gameplay
    mapping(address => uint8) public otherManagers;

    // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked
    bool public paused = false;

    // @dev Keeps track whether the contract erroredOut. When that is true, most actions are blocked & refund can be claimed
    bool public error = false;

    /**
     * @dev Operation modifiers for limiting access only to Managers
     */
    modifier onlyManager() {
        require (msg.sender == managerPrimary || msg.sender == managerSecondary);
        _;
    }

    /**
     * @dev Operation modifiers for limiting access to only Banker
     */
    modifier onlyBanker() {
        require (msg.sender == bankManager);
        _;
    }

    /**
     * @dev Operation modifiers for any Operators
     */
    modifier anyOperator() {
        require (
            msg.sender == managerPrimary ||
            msg.sender == managerSecondary ||
            msg.sender == bankManager ||
            otherManagers[msg.sender] == 1
        );
        _;
    }

    /**
     * @dev        Operation modifier for any Other Manager
     */
    modifier onlyOtherManagers() {
        require (otherManagers[msg.sender] == 1);
        _;
    }

    /**
     * @dev Assigns a new address to act as the Primary Manager.
     * @param _newGM    New primary manager address
     */
    function setPrimaryManager(address _newGM) external onlyManager {
        require (_newGM != address(0));

        managerPrimary = _newGM;
    }

    /**
     * @dev Assigns a new address to act as the Secondary Manager.
     * @param _newGM    New Secondary Manager Address
     */
    function setSecondaryManager(address _newGM) external onlyManager {
        require (_newGM != address(0));

        managerSecondary = _newGM;
    }

    /**
     * @dev Assigns a new address to act as the Banker.
     * @param _newBK    New Banker Address
     */
    function setBanker(address _newBK) external onlyManager {
        require (_newBK != address(0));

        bankManager = _newBK;
    }

    /// @dev Assigns a new address to act as the Other Manager. (State = 1 is active, 0 is disabled)
    function setOtherManager(address _newOp, uint8 _state) external onlyManager {
        require (_newOp != address(0));

        otherManagers[_newOp] = _state;
    }

    /*** Pausable functionality adapted from OpenZeppelin ***/

    /// @dev Modifier to allow actions only when the contract IS NOT paused
    modifier whenNotPaused() {
        require (!paused);
        _;
    }

    /// @dev Modifier to allow actions only when the contract IS paused
    modifier whenPaused {
        require (paused);
        _;
    }

    /// @dev Modifier to allow actions only when the contract has Error
    modifier whenError {
        require (error);
        _;
    }

    /**
     * @dev Called by any Operator role to pause the contract.
     * Used only if a bug or exploit is discovered (Here to limit losses / damage)
     */
    function pause() external onlyManager whenNotPaused {
        paused = true;
    }

    /**
     * @dev Unpauses the smart contract. Can only be called by the Game Master
     */
    function unpause() public onlyManager whenPaused {
        // can't unpause if contract was upgraded
        paused = false;
    }

    /**
     * @dev Errors out the contract thus mkaing the contract non-functionable
     */
    function hasError() public onlyManager whenPaused {
        error = true;
    }

    /**
     * @dev Removes the Error Hold from the contract and resumes it for working
     */
    function noError() public onlyManager whenPaused {
        error = false;
    }
}

/** Base contract for MLBNFT Collectibles. Holds all commons, events and base variables.
 * @title Lucid Sight MLB NFT 2018
 * @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.)
 */
contract CollectibleBase is LSNFT {

    /*** EVENTS ***/

    /// @dev Event emitted when an attribute of the player is updated
    event AssetUpdated(uint256 tokenId);

    /*** STORAGE ***/

    /// @dev A mapping of Team Id to Team Sequence Number to Collectible
    mapping (uint256 => mapping (uint32 => uint256) ) public nftTeamIdToSequenceIdToCollectible;

    /// @dev A mapping from Team IDs to the Sequqence Number .
    mapping (uint256 => uint32) public nftTeamIndexToCollectibleCount;

    /// @dev Array to hold details on attachment for each LS NFT Collectible
    mapping(uint256 => uint256[]) public nftCollectibleAttachments;

    /// @dev Mapping to control the asset generation per season.
    mapping(uint256 => uint256) public generationSeasonController;

    /// @dev Mapping for generation Season Dict.
    mapping(uint256 => uint256) public generationSeasonDict;

    /// @dev internal function to update player override id
    function _updatePlayerOverrideId(uint256 _tokenId, uint256 _newPlayerOverrideId) internal {

        // Get Token Obj
        NFT storage lsnftObj = allNFTs[_tokenId];
        lsnftObj.playerOverrideId = _newPlayerOverrideId;

        // Update Token Data with new updated attributes
        allNFTs[_tokenId] = lsnftObj;

        emit AssetUpdated(_tokenId);
    }

    /**
     * @dev An internal method that helps in generation of new NFT Collectibles
     * @param _teamId           teamId of the asset/token/collectible
     * @param _attributes       attributes of asset/token/collectible
     * @param _owner            owner of asset/token/collectible
     * @param _isAttached       State of the asset (attached or dettached)
     * @param _nftData          Array of data required for creation
     */
    function _createNFTCollectible(
        uint8 _teamId,
        uint256 _attributes,
        address _owner,
        uint256 _isAttached,
        uint256[5] _nftData
    )
        internal
        returns (uint256)
    {
        uint256 generationSeason = (_attributes % 1000000).div(1000);
        require (generationSeasonController[generationSeason] == 1);

        uint32 _sequenceId = getSequenceId(_teamId);

        uint256 newNFTCryptoId = _createNFT(_nftData, _owner, _isAttached);
        
        nftTeamIdToSequenceIdToCollectible[_teamId][_sequenceId] = newNFTCryptoId;
        nftTeamIndexToCollectibleCount[_teamId] = _sequenceId;

        return newNFTCryptoId;
    }
    
    function getSequenceId(uint256 _teamId) internal returns (uint32) {
        return (nftTeamIndexToCollectibleCount[_teamId] + 1);
    }

    /**
     * @dev Internal function, Helps in updating the Creation Stop Time
     * @param _season    Season UINT Code
     * @param _value    0 - Not allowed, 1 - Allowed
     */
    function _updateGenerationSeasonFlag(uint256 _season, uint8 _value) internal {
        generationSeasonController[_season] = _value;
    }

    /** @param _owner The owner whose ships tokens we are interested in.
      * @dev This method MUST NEVER be called by smart contract code. First, it's fairly
      *  expensive (it walks the entire Collectibles owners array looking for NFT belonging to owner)
    */      
    function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) {
        uint256 tokenCount = balanceOf(_owner);

        if (tokenCount == 0) {
            // Return an empty array
            return new uint256[](0);
        } else {
            uint256[] memory result = new uint256[](tokenCount);
            uint256 totalItems = balanceOf(_owner);
            uint256 resultIndex = 0;

            // We count on the fact that all Collectible have IDs starting at 0 and increasing
            // sequentially up to the total count.
            uint256 _assetId;

            for (_assetId = 0; _assetId < totalItems; _assetId++) {
                result[resultIndex] = tokenOfOwnerByIndex(_owner,_assetId);
                resultIndex++;
            }

            return result;
        }
    }

    /// @dev internal function to update MLB player id
    function _updateMLBPlayerId(uint256 _tokenId, uint256 _newMLBPlayerId) internal {

        // Get Token Obj
        NFT storage lsnftObj = allNFTs[_tokenId];
        
        lsnftObj.mlbPlayerId = _newMLBPlayerId;

        // Update Token Data with new updated attributes
        allNFTs[_tokenId] = lsnftObj;

        emit AssetUpdated(_tokenId);
    }

    /// @dev internal function to update asset earnedBy value for an asset/token
    function _updateEarnedBy(uint256 _tokenId, uint256 _earnedBy) internal {

        // Get Token Obj
        NFT storage lsnftObj = allNFTs[_tokenId];
        
        lsnftObj.earnedBy = _earnedBy;

        // Update Token Data with new updated attributes
        allNFTs[_tokenId] = lsnftObj;

        emit AssetUpdated(_tokenId);
    }
}

/* Handles creating new Collectibles for promo and seed.
 * @title CollectibleMinting Minting
 * @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.)
 * Inspired and adapted from KittyCore.sol created by Axiom Zen
 * Ref: ETH Contract - 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d
 */
contract CollectibleMinting is CollectibleBase, OperationalControl {

    uint256 public rewardsRedeemed = 0;

    /// @dev Counts the number of promo collectibles that can be made per-team
    uint256[31]  public promoCreatedCount;
    
    /// @dev Counts the number of seed collectibles that can be made in total
    uint256 public seedCreatedCount;

    /// @dev Bool to toggle batch support
    bool public isBatchSupported = true;
    
    /// @dev A mapping of contracts that can trigger functions
    mapping (address => bool) public contractsApprovedList;
    
    /**
     * @dev        Helps to toggle batch supported flag
     * @param      _flag  The flag
     */
    function updateBatchSupport(bool _flag) public onlyManager {
        isBatchSupported = _flag;
    }

    modifier canCreate() { 
        require (contractsApprovedList[msg.sender] || 
            msg.sender == managerPrimary ||
            msg.sender == managerSecondary); 
        _; 
    }
    
    /**
     * @dev Add an address to the Approved List
     * @param _newAddress   The new address to be approved for interaction with the contract
     */
    function addToApproveList(address _newAddress) public onlyManager {
        
        require (!contractsApprovedList[_newAddress]);
        contractsApprovedList[_newAddress] = true;
    }

    /**
     * @dev Remove an address from Approved List
     * @param _newAddress   The new address to be approved for interaction with the contract
     */
    function removeFromApproveList(address _newAddress) public onlyManager {
        require (contractsApprovedList[_newAddress]);
        delete contractsApprovedList[_newAddress];
    }

    
    /**
     * @dev Generates promo collectibles. Only callable by Game Master, with isAttached as 0.
     * @notice The generation of an asset if limited via the generationSeasonController
     * @param _teamId           teamId of the asset/token/collectible
     * @param _posId            position of the asset/token/collectible
     * @param _attributes       attributes of asset/token/collectible
     * @param _owner            owner of asset/token/collectible
     * @param _gameId          mlb game Identifier
     * @param _playerOverrideId player override identifier
     * @param _mlbPlayerId      official mlb player identifier
     */
    function createPromoCollectible(
        uint8 _teamId,
        uint8 _posId,
        uint256 _attributes,
        address _owner,
        uint256 _gameId,
        uint256 _playerOverrideId,
        uint256 _mlbPlayerId)
        external
        canCreate
        whenNotPaused
        returns (uint256)
        {

        address nftOwner = _owner;
        if (nftOwner == address(0)) {
             nftOwner = managerPrimary;
        }

        if(allNFTs.length > 0) {
            promoCreatedCount[_teamId]++;
        }
        
        uint32 _sequenceId = getSequenceId(_teamId);
        
        uint256 assetDetails = uint256(uint64(now));
        assetDetails |= uint256(_sequenceId)<<64;
        assetDetails |= uint256(_teamId)<<96;
        assetDetails |= uint256(_posId)<<104;

        uint256[5] memory _nftData = [assetDetails, _attributes, _gameId, _playerOverrideId, _mlbPlayerId];
        
        return _createNFTCollectible(_teamId, _attributes, nftOwner, 0, _nftData);
    }

    /**
     * @dev Generaes a new single seed Collectible, with isAttached as 0.
     * @notice Helps in creating seed collectible.The generation of an asset if limited via the generationSeasonController
     * @param _teamId           teamId of the asset/token/collectible
     * @param _posId            position of the asset/token/collectible
     * @param _attributes       attributes of asset/token/collectible
     * @param _owner            owner of asset/token/collectible
     * @param _gameId          mlb game Identifier
     * @param _playerOverrideId player override identifier
     * @param _mlbPlayerId      official mlb player identifier
     */
    function createSeedCollectible(
        uint8 _teamId,
        uint8 _posId,
        uint256 _attributes,
        address _owner,
        uint256 _gameId,
        uint256 _playerOverrideId,
        uint256 _mlbPlayerId)
        external
        canCreate
        whenNotPaused
        returns (uint256) {

        address nftOwner = _owner;
        
        if (nftOwner == address(0)) {
             nftOwner = managerPrimary;
        }
        
        seedCreatedCount++;
        uint32 _sequenceId = getSequenceId(_teamId);
        
        uint256 assetDetails = uint256(uint64(now));
        assetDetails |= uint256(_sequenceId)<<64;
        assetDetails |= uint256(_teamId)<<96;
        assetDetails |= uint256(_posId)<<104;

        uint256[5] memory _nftData = [assetDetails, _attributes, _gameId, _playerOverrideId, _mlbPlayerId];
        
        return _createNFTCollectible(_teamId, _attributes, nftOwner, 0, _nftData);
    }

    /**
     * @dev Generate new Reward Collectible and transfer it to the owner, with isAttached as 0.
     * @notice Helps in redeeming the Rewards using our Oracle. Creates & transfers the asset to the redeemer (_owner)
     * The generation of an asset if limited via the generationSeasonController
     * @param _teamId           teamId of the asset/token/collectible
     * @param _posId            position of the asset/token/collectible
     * @param _attributes       attributes of asset/token/collectible
     * @param _owner            owner (redeemer) of asset/token/collectible
     * @param _gameId           mlb game Identifier
     * @param _playerOverrideId player override identifier
     * @param _mlbPlayerId      official mlb player identifier
     */
    function createRewardCollectible (
        uint8 _teamId,
        uint8 _posId,
        uint256 _attributes,
        address _owner,
        uint256 _gameId,
        uint256 _playerOverrideId,
        uint256 _mlbPlayerId)
        external
        canCreate
        whenNotPaused
        returns (uint256) {

        address nftOwner = _owner;
        
        if (nftOwner == address(0)) {
             nftOwner = managerPrimary;
        }
        
        rewardsRedeemed++;
        uint32 _sequenceId = getSequenceId(_teamId);
        
        uint256 assetDetails = uint256(uint64(now));
        assetDetails |= uint256(_sequenceId)<<64;
        assetDetails |= uint256(_teamId)<<96;
        assetDetails |= uint256(_posId)<<104;

        uint256[5] memory _nftData = [assetDetails, _attributes, _gameId, _playerOverrideId, _mlbPlayerId];
        
        return _createNFTCollectible(_teamId, _attributes, nftOwner, 0, _nftData);
    }

    /**
     * @dev Generate new ETH Card Collectible, with isAttached as 2.
     * @notice Helps to generate Collectibles/Tokens/Asset and transfer to ETH Cards,
     * which can be redeemed using our web-app.The generation of an asset if limited via the generationSeasonController
     * @param _teamId           teamId of the asset/token/collectible
     * @param _posId            position of the asset/token/collectible
     * @param _attributes       attributes of asset/token/collectible
     * @param _owner            owner of asset/token/collectible
     * @param _gameId           mlb game Identifier
     * @param _playerOverrideId player override identifier
     * @param _mlbPlayerId      official mlb player identifier
     */
    function createETHCardCollectible (
        uint8 _teamId,
        uint8 _posId,
        uint256 _attributes,
        address _owner,
        uint256 _gameId,
        uint256 _playerOverrideId,
        uint256 _mlbPlayerId)
        external
        canCreate
        whenNotPaused
        returns (uint256) {

        address nftOwner = _owner;
        
        if (nftOwner == address(0)) {
             nftOwner = managerPrimary;
        }
        
        rewardsRedeemed++;
        uint32 _sequenceId = getSequenceId(_teamId);
        
        uint256 assetDetails = uint256(uint64(now));
        assetDetails |= uint256(_sequenceId)<<64;
        assetDetails |= uint256(_teamId)<<96;
        assetDetails |= uint256(_posId)<<104;

        uint256[5] memory _nftData = [assetDetails, _attributes, _gameId, _playerOverrideId, _mlbPlayerId];
        
        return _createNFTCollectible(_teamId, _attributes, nftOwner, 2, _nftData);
    }
}

/* @title Interface for MLBNFT Contract
 * @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.)
 */
contract SaleManager {
    function createSale(uint256 _tokenId, uint256 _startingPrice, uint256 _endingPrice, uint256 _duration, address _owner) external;
}

/**
 * MLBNFT manages all aspects of the Lucid Sight, Inc. CryptoBaseball.
 * @title MLBNFT
 * @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.)
 */
contract MLBNFT is CollectibleMinting {
    
    /// @dev Set in case the MLBNFT contract requires an upgrade
    address public newContractAddress;

    string public constant MLB_Legal = "Major League Baseball trademarks and copyrights are used with permission of the applicable MLB entity.  All rights reserved.";

    // Time LS Oracle has to respond to detach requests
    uint32 public detachmentTime = 0;

    // Indicates if attached system is Active (Transfers will be blocked if attached and active)
    bool public attachedSystemActive;

    // Sale Manager Contract
    SaleManager public saleManagerAddress;

    /**
     * @dev MLBNFT constructor.
     */
    constructor() public {
        // Starts paused.
        paused = true;
        managerPrimary = msg.sender;
        managerSecondary = msg.sender;
        bankManager = msg.sender;
        name_ = "LucidSight-MLB-NFT";
        symbol_ = "MLBCB";
    }

    /**
     * @dev        Sets the address for the NFT Contract
     * @param      _saleManagerAddress  The nft address
     */
    function setSaleManagerAddress(address _saleManagerAddress) public onlyManager {
        require (_saleManagerAddress != address(0));
        saleManagerAddress = SaleManager(_saleManagerAddress);
    }

    /**
    * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator
    * @param _tokenId uint256 ID of the token to validate
    */
    modifier canTransfer(uint256 _tokenId) {
        uint256 isAttached = checkIsAttached(_tokenId);
        if(isAttached == 2) {
            //One-Time Auth for Physical Card Transfers
            require (msg.sender == managerPrimary ||
                msg.sender == managerSecondary ||
                msg.sender == bankManager ||
                otherManagers[msg.sender] == 1
            );
            updateIsAttached(_tokenId, 0);
        } else if(attachedSystemActive == true && isAttached >= 1) {
            require (msg.sender == managerPrimary ||
                msg.sender == managerSecondary ||
                msg.sender == bankManager ||
                otherManagers[msg.sender] == 1
            );
        }
        else {
            require (isApprovedOrOwner(msg.sender, _tokenId));
        }
    _;
    }

    /**
     * @dev Used to mark the smart contract as upgraded, in case of a issue
     * @param _v2Address    The new contract address
     */
    function setNewAddress(address _v2Address) external onlyManager {
        require (_v2Address != address(0));
        newContractAddress = _v2Address;
        emit ContractUpgrade(_v2Address);
    }

    /**
     * @dev Returns all the relevant information about a specific Collectible.
     * @notice Get details about your collectible
     * @param _tokenId              The token identifier
     * @return isAttached           Is Object attached
     * @return teamId               team identifier of the asset/token/collectible
     * @return positionId           position identifier of the asset/token/collectible
     * @return creationTime         creation timestamp
     * @return attributes           attribute of the asset/token/collectible
     * @return currentGameCardId    current game card of the asset/token/collectible
     * @return mlbGameID            mlb game identifier in which the asset/token/collectible was generated
     * @return playerOverrideId     player override identifier of the asset/token/collectible
     * @return playerStatus         status of the player (Rookie/Veteran/Historical)
     * @return playerHandedness     handedness of the asset
     * @return mlbPlayerId          official MLB Player Identifier
     */
    function getCollectibleDetails(uint256 _tokenId)
        external
        view
        returns (
        uint256 isAttached,
        uint32 sequenceId,
        uint8 teamId,
        uint8 positionId,
        uint64 creationTime,
        uint256 attributes,
        uint256 playerOverrideId,
        uint256 mlbGameId,
        uint256 currentGameCardId,
        uint256 mlbPlayerId,
        uint256 earnedBy,
        uint256 generationSeason
        ) {
        NFT memory obj  = _getAttributesOfToken(_tokenId);
        
        attributes = obj.attributes;
        currentGameCardId = obj.currentGameCardId;
        mlbGameId = obj.mlbGameId;
        playerOverrideId = obj.playerOverrideId;
        mlbPlayerId = obj.mlbPlayerId;

        creationTime = uint64(obj.assetDetails);
        sequenceId = uint32(obj.assetDetails>>64);
        teamId = uint8(obj.assetDetails>>96);
        positionId = uint8(obj.assetDetails>>104);
        isAttached = obj.isAttached;
        earnedBy = obj.earnedBy;

        generationSeason = generationSeasonDict[(obj.attributes % 1000000) / 1000];
    }

    
    /**
     * @dev This is public rather than external so we can call super.unpause
     * without using an expensive CALL.
     */
    function unpause() public onlyManager {
        /// Actually unpause the contract.
        super.unpause();
    }

    /**
     * @dev Helper function to get the teamID of a collectible.To avoid using getCollectibleDetails
     * @notice Returns the teamID associated with the asset/collectible/token
     * @param _tokenId  The token identifier
     */
    function getTeamId(uint256 _tokenId) external view returns (uint256) {
        NFT memory obj  = _getAttributesOfToken(_tokenId);

        uint256 teamId = uint256(uint8(obj.assetDetails>>96));
        return uint256(teamId);
    }

    /**
     * @dev Helper function to get the position of a collectible.To avoid using getCollectibleDetails
     * @notice Returns the position of the asset/collectible/token
     * @param _tokenId  The token identifier
     */
    function getPositionId(uint256 _tokenId) external view returns (uint256) {
        NFT memory obj  = _getAttributesOfToken(_tokenId);

        uint256 positionId = uint256(uint8(obj.assetDetails>>104));

        return positionId;
    }

    /**
     * @dev Helper function to get the game card. To avoid using getCollectibleDetails
     * @notice Returns the gameCard associated with the asset/collectible/token
     * @param _tokenId  The token identifier
     */
    function getGameCardId(uint256 _tokenId) public view returns (uint256) {
        NFT memory obj  = _getAttributesOfToken(_tokenId);
        return obj.currentGameCardId;
    }

    /**
     * @dev Returns isAttached property value for an asset/collectible/token
     * @param _tokenId  The token identifier
     */
    function checkIsAttached(uint256 _tokenId) public view returns (uint256) {
        NFT memory obj  = _getAttributesOfToken(_tokenId);
        return obj.isAttached;
    }

    /**
     * @dev Helper function to get the attirbute of the collectible.To avoid using getCollectibleDetails
     * @notice Returns the ability of an asset/collectible/token from attributes.
     * @param _tokenId  The token identifier
     * @return ability  ability of the asset
     */
    function getAbilitiesForCollectibleId(uint256 _tokenId) external view returns (uint256 ability) {
        NFT memory obj  = _getAttributesOfToken(_tokenId);
        uint256 _attributes = uint256(obj.attributes);
        ability = (_attributes % 1000);
    }

    /**
     * @dev Only allows trasnctions to go throught if the msg.sender is in the apporved list
     * @notice Updates the gameCardID properrty of the asset
     * @param _gameCardNumber  The game card number
     * @param _playerId        The player identifier
     */
    function updateCurrentGameCardId(uint256 _gameCardNumber, uint256 _playerId) public whenNotPaused {
        require (contractsApprovedList[msg.sender]);

        NFT memory obj  = _getAttributesOfToken(_playerId);
        
        obj.currentGameCardId = _gameCardNumber;
        
        if ( _gameCardNumber == 0 ) {
            obj.isAttached = 0;
        } else {
            obj.isAttached = 1;
        }

        allNFTs[_playerId] = obj;
    }

    /**
     * @dev Only Manager can add an attachment (special events) to the collectible
     * @notice Adds an attachment to collectible.
     * @param _tokenId  The token identifier
     * @param _attachment  The attachment
     */
    function addAttachmentToCollectible ( 
        uint256 _tokenId,
        uint256 _attachment)
        external
        onlyManager
        whenNotPaused {
        require (exists(_tokenId));

        nftCollectibleAttachments[_tokenId].push(_attachment);
        emit AssetUpdated(_tokenId);
    }

    /**
     * @dev It will remove the attachment form the collectible. We will need to re-add all attachment(s) if removed.
     * @notice Removes all attachments from collectible.
     * @param _tokenId  The token identifier
     */
    function removeAllAttachmentsFromCollectible(uint256 _tokenId)
        external
        onlyManager
        whenNotPaused {

        require (exists(_tokenId));
        
        delete nftCollectibleAttachments[_tokenId];
        emit AssetUpdated(_tokenId);
    }

    /**
     * @notice Transfers the ownership of NFT from one address to another address
     * @dev responsible for gifting assets to other user.
     * @param _to       to address
     * @param _tokenId  The token identifier
     */
    function giftAsset(address _to, uint256 _tokenId) public whenNotPaused {        
        safeTransferFrom(msg.sender, _to, _tokenId);
    }
    
    /**
     * @dev responsible for setting the tokenURI.
     * @notice The user/developper needs to add the tokenID, in the end of URL, to 
     * use the URI and get all details. Ex. www.<apiURL>.com/token/<tokenID>
     * @param _tokenURI  The token uri
     */
    function setTokenURIBase (string _tokenURI) public anyOperator {
        _setTokenURIBase(_tokenURI);
    }

    /**
     * @dev Allowed to be called by onlyGameManager to update a certain collectible playerOverrideID
     * @notice Sets the player override identifier.
     * @param _tokenId      The token identifier
     * @param _newOverrideId     The new player override identifier
     */
    function setPlayerOverrideId(uint256 _tokenId, uint256 _newOverrideId) public onlyManager whenNotPaused {
        require (exists(_tokenId));

        _updatePlayerOverrideId(_tokenId, _newOverrideId);
    }

    /**
     * @notice Updates the Generation Season Controller.
     * @dev Allowed to be called by onlyGameManager to update the generation season.
     * this helps to control the generation of collectible.
     * @param _season    Season UINT representation
     * @param _value    0-Not allowed, 1-open, >=2 Locked Forever
     */
    function updateGenerationStopTime(uint256 _season, uint8 _value ) public  onlyManager whenNotPaused {
        require (generationSeasonController[_season] == 1 && _value != 0);
        _updateGenerationSeasonFlag(_season, _value);
    }

    /**
     * @dev set Generation Season Controller, can only be called by Managers._season can be [0,1,2,3..] and 
     * _value can be [0,1,N].
     * @notice _value of 1: means generation of collectible is allowed. anything, apart from 1, wont allow generating assets for that season.
     * @param _season    Season UINT representation
     */
    function setGenerationSeasonController(uint256 _season) public onlyManager whenNotPaused {
        require (generationSeasonController[_season] == 0);
        _updateGenerationSeasonFlag(_season, 1);
    }

    /**
     * @dev Adding value to DICT helps in showing the season value in getCollectibleDetails
     * @notice Updates the Generation Season Dict.
     * @param _season    Season UINT representation
     * @param _value    0-Not allowed,1-allowed
     */
    function updateGenerationDict(uint256 _season, uint64 _value) public onlyManager whenNotPaused {
        require (generationSeasonDict[_season] <= 1);
        generationSeasonDict[_season] = _value;
    }

    /**
     * @dev Helper function to avoid calling getCollectibleDetails
     * @notice Gets the MLB player Id from the player attributes
     * @param _tokenId  The token identifier
     * @return playerId  MLB Player Identifier
     */
    function getPlayerId(uint256 _tokenId) external view returns (uint256 playerId) {
        NFT memory obj  = _getAttributesOfToken(_tokenId);
        playerId = ((obj.attributes.div(100000000000000000)) % 1000);
    }
    
    /**
     * @dev Helper function to avoid calling getCollectibleDetails
     * @notice Gets the attachments for an asset
     * @param _tokenId  The token identifier
     * @return attachments
     */
    function getAssetAttachment(uint256 _tokenId) external view returns (uint256[]) {
        uint256[] _attachments = nftCollectibleAttachments[_tokenId];
        uint256[] attachments;
        for(uint i=0;i<_attachments.length;i++){
            attachments.push(_attachments[i]);
        }
        
        return attachments;
    }

    /**
     * @dev Can only be trigerred by Managers. Updates the earnedBy property of the NFT
     * @notice Helps in updating the earned _by property of an asset/token.
     * @param  _tokenId        asser/token identifier
     * @param  _earnedBy       New asset/token DNA
     */
    function updateEarnedBy(uint256 _tokenId, uint256 _earnedBy) public onlyManager whenNotPaused {
        require (exists(_tokenId));

        _updateEarnedBy(_tokenId, _earnedBy);
    }

    /**
     * @dev A batch function to facilitate batching of asset creation. canCreate modifier
     * helps in controlling who can call the function
     * @notice Batch Function to Create Assets
     * @param      _teamId            The team identifier
     * @param      _attributes        The attributes
     * @param      _playerOverrideId  The player override identifier
     * @param      _mlbPlayerId       The mlb player identifier
     * @param      _to                To Address
     */
    function batchCreateAsset(
        uint8[] _teamId,
        uint256[] _attributes,
        uint256[] _playerOverrideId,
        uint256[] _mlbPlayerId,
        address[] _to)
        external
        canCreate
        whenNotPaused {
            require (isBatchSupported);

            require (_teamId.length > 0 && _attributes.length > 0 && 
                _playerOverrideId.length > 0 && _mlbPlayerId.length > 0 && 
                _to.length > 0);

            uint256 assetDetails;
            uint256[5] memory _nftData;
            
            for(uint ii = 0; ii < _attributes.length; ii++){
                require (_to[ii] != address(0) && _teamId[ii] != 0 && _attributes.length != 0 && 
                    _mlbPlayerId[ii] != 0);
                
                assetDetails = uint256(uint64(now));
                assetDetails |= uint256(getSequenceId(_teamId[ii]))<<64;
                assetDetails |= uint256(_teamId[ii])<<96;
                assetDetails |= uint256((_attributes[ii]/1000000000000000000000000000000000000000)-800)<<104;
        
                _nftData = [assetDetails, _attributes[ii], 0, _playerOverrideId[ii], _mlbPlayerId[ii]];
                
                _createNFTCollectible(_teamId[ii], _attributes[ii], _to[ii], 0, _nftData);
            }
        }

    /**
     * @dev A batch function to facilitate batching of asset creation for ETH Cards. canCreate modifier
     * helps in controlling who can call the function
     * @notice        Batch Function to Create Assets
     * @param      _teamId            The team identifier
     * @param      _attributes        The attributes
     * @param      _playerOverrideId  The player override identifier
     * @param      _mlbPlayerId       The mlb player identifier
     * @param      _to                { parameter_description }
     */
    function batchCreateETHCardAsset(
        uint8[] _teamId,
        uint256[] _attributes,
        uint256[] _playerOverrideId,
        uint256[] _mlbPlayerId,
        address[] _to)
        external
        canCreate
        whenNotPaused {
            require (isBatchSupported);

            require (_teamId.length > 0 && _attributes.length > 0
                        && _playerOverrideId.length > 0 &&
                        _mlbPlayerId.length > 0 && _to.length > 0);

            uint256 assetDetails;
            uint256[5] memory _nftData;

            for(uint ii = 0; ii < _attributes.length; ii++){

                require (_to[ii] != address(0) && _teamId[ii] != 0 && _attributes.length != 0 && 
                    _mlbPlayerId[ii] != 0);
        
                assetDetails = uint256(uint64(now));
                assetDetails |= uint256(getSequenceId(_teamId[ii]))<<64;
                assetDetails |= uint256(_teamId[ii])<<96;
                assetDetails |= uint256((_attributes[ii]/1000000000000000000000000000000000000000)-800)<<104;
        
                _nftData = [assetDetails, _attributes[ii], 0, _playerOverrideId[ii], _mlbPlayerId[ii]];
                
                _createNFTCollectible(_teamId[ii], _attributes[ii], _to[ii], 2, _nftData);
            }
        }

    /**
     * @dev        Overriden TransferFrom, with the modifier canTransfer which uses our attachment system
     * @notice     Helps in trasnferring assets
     * @param      _from     the address sending from
     * @param      _to       the address sending to
     * @param      _tokenId  The token identifier
     */
    function transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    )
        public
        canTransfer(_tokenId)
    {
        // Asset should not be in play
        require (checkIsAttached(_tokenId) == 0);
        
        require (_from != address(0));

        require (_to != address(0));

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

        emit Transfer(_from, _to, _tokenId);
    }

    /**
     * @dev     Facilitates batch trasnfer of collectible with multiple TO Address, depending if batch is supported on contract.
     * @notice  Batch Trasnfer with multpple TO addresses
     * @param      _tokenIds  The token identifiers
     * @param      _fromB     the address sending from
     * @param      _toB       the address sending to
     */
    function multiBatchTransferFrom(
        uint256[] _tokenIds, 
        address[] _fromB, 
        address[] _toB) 
        public
    {
        require (isBatchSupported);

        require (_tokenIds.length > 0 && _fromB.length > 0 && _toB.length > 0);

        uint256 _id;
        address _to;
        address _from;
        
        for (uint256 i = 0; i < _tokenIds.length; ++i) {

            require (_tokenIds[i] != 0 && _fromB[i] != 0 && _toB[i] != 0);

            _id = _tokenIds[i];
            _to = _toB[i];
            _from = _fromB[i];

            transferFrom(_from, _to, _id);
        }
        
    }
    
    /**
     * @dev     Facilitates batch trasnfer of collectible, depending if batch is supported on contract
     * @notice        Batch TransferFrom with the same to & from address
     * @param      _tokenIds  The asset identifiers
     * @param      _from      the address sending from
     * @param      _to        the address sending to
     */
    function batchTransferFrom(uint256[] _tokenIds, address _from, address _to) 
        public
    {
        require (isBatchSupported);

        require (_tokenIds.length > 0 && _from != address(0) && _to != address(0));

        uint256 _id;
        
        for (uint256 i = 0; i < _tokenIds.length; ++i) {
            
            require (_tokenIds[i] != 0);

            _id = _tokenIds[i];

            transferFrom(_from, _to, _id);
        }
    }
    
    /**
     * @dev     Facilitates batch trasnfer of collectible, depending if batch is supported on contract.
     * Checks for collectible 0,address 0 and then performs the transfer
     * @notice        Batch SafeTransferFrom with multiple From and to Addresses
     * @param      _tokenIds  The asset identifiers
     * @param      _fromB     the address sending from
     * @param      _toB       the address sending to
     */
    function multiBatchSafeTransferFrom(
        uint256[] _tokenIds, 
        address[] _fromB, 
        address[] _toB
        )
        public
    {
        require (isBatchSupported);

        require (_tokenIds.length > 0 && _fromB.length > 0 && _toB.length > 0);

        uint256 _id;
        address _to;
        address _from;
        
        for (uint256 i = 0; i < _tokenIds.length; ++i) {

            require (_tokenIds[i] != 0 && _fromB[i] != 0 && _toB[i] != 0);

            _id = _tokenIds[i];
            _to  = _toB[i];
            _from  = _fromB[i];

            safeTransferFrom(_from, _to, _id);
        }
    }

    /**
     * @dev     Facilitates batch trasnfer of collectible, depending if batch is supported on contract.
     * Checks for collectible 0,address 0 and then performs the transfer
     * @notice        Batch SafeTransferFrom from a single address to another address
     * @param      _tokenIds  The asset identifiers
     * @param      _from     the address sending from
     * @param      _to       the address sending to
     */
    function batchSafeTransferFrom(
        uint256[] _tokenIds, 
        address _from, 
        address _to
        )
        public
    {   
        require (isBatchSupported);

        require (_tokenIds.length > 0 && _from != address(0) && _to != address(0));

        uint256 _id;
        for (uint256 i = 0; i < _tokenIds.length; ++i) {
            require (_tokenIds[i] != 0);
            _id = _tokenIds[i];
            safeTransferFrom(_from, _to, _id);
        }
    }

    /**
     * @notice     Batch Function to approve the spender
     * @dev        Helps to approve a batch of collectibles 
     * @param      _tokenIds  The asset identifiers
     * @param      _spender   The spender
     */
    function batchApprove(
        uint256[] _tokenIds, 
        address _spender
        )
        public
    {   
        require (isBatchSupported);

        require (_tokenIds.length > 0 && _spender != address(0));
        
        uint256 _id;
        for (uint256 i = 0; i < _tokenIds.length; ++i) {

            require (_tokenIds[i] != 0);
            
            _id = _tokenIds[i];
            approve(_spender, _id);
        }
        
    }

    /**
     * @dev        Batch Function to mark spender for approved for all. Does a check
     * for address(0) and throws if true
     * @notice     Facilitates batch approveAll
     * @param      _spenders  The spenders
     * @param      _approved  The approved
     */
    function batchSetApprovalForAll(
        address[] _spenders,
        bool _approved
        )
        public
    {   
        require (isBatchSupported);

        require (_spenders.length > 0);

        address _spender;
        for (uint256 i = 0; i < _spenders.length; ++i) {        

            require (address(_spenders[i]) != address(0));
                
            _spender = _spenders[i];
            setApprovalForAll(_spender, _approved);
        }
    }  
    
    /**
     * @dev        Function to request Detachment from our Contract
     * @notice     a wallet can request to detach it collectible, so, that it can be used in other third-party contracts.
     * @param      _tokenId  The token identifier
     */
    function requestDetachment(
        uint256 _tokenId
    )
        public
    {
        //Request can only be made by owner or approved address
        require (isApprovedOrOwner(msg.sender, _tokenId));

        uint256 isAttached = checkIsAttached(_tokenId);

        //If collectible is on a gamecard prevent detachment
        require(getGameCardId(_tokenId) == 0);

        require (isAttached >= 1);

        if(attachedSystemActive == true) {
            //Checks to see if request was made and if time elapsed
            if(isAttached > 1 && block.timestamp - isAttached > detachmentTime) {
                isAttached = 0;
            } else if(isAttached > 1) {
                //Forces Tx Fail if time is already set for attachment and not less than detachmentTime
                require (isAttached == 1);
            } else {
                //Is attached, set detachment time and make request to detach
                // emit AssetUpdated(_tokenId);
                isAttached = block.timestamp;
            }
        } else {
            isAttached = 0;
        }

        updateIsAttached(_tokenId, isAttached);
    }

    /**
     * @dev        Function to attach the asset, thus, restricting transfer
     * @notice     Attaches the collectible to our contract
     * @param      _tokenId  The token identifier
     */
    function attachAsset(
        uint256 _tokenId
    )
        public
        canTransfer(_tokenId)
    {
        uint256 isAttached = checkIsAttached(_tokenId);

        require (isAttached == 0);
        isAttached = 1;

        updateIsAttached(_tokenId, isAttached);

        emit AssetUpdated(_tokenId);
    }

    /**
     * @dev        Batch attach function
     * @param      _tokenIds  The identifiers
     */
    function batchAttachAssets(uint256[] _tokenIds) public {
        require (isBatchSupported);

        for(uint i = 0; i < _tokenIds.length; i++) {
            attachAsset(_tokenIds[i]);
        }
    }

    /**
     * @dev        Batch detach function
     * @param      _tokenIds  The identifiers
     */
    function batchDetachAssets(uint256[] _tokenIds) public {
        require (isBatchSupported);

        for(uint i = 0; i < _tokenIds.length; i++) {
            requestDetachment(_tokenIds[i]);
        }
    }

    /**
     * @dev        Function to facilitate detachment when contract is paused
     * @param      _tokenId  The identifiers
     */
    function requestDetachmentOnPause (uint256 _tokenId) public whenPaused {
        //Request can only be made by owner or approved address
        require (isApprovedOrOwner(msg.sender, _tokenId));

        updateIsAttached(_tokenId, 0);
    }

    /**
     * @dev        Toggle the Attachment Switch
     * @param      _state  The state
     */
    function toggleAttachedEnforcement (bool _state) public onlyManager {
        attachedSystemActive = _state;
    }

    /**
     * @dev        Set Attachment Time Period (this restricts user from continuously trigger detachment)
     * @param      _time  The time
     */
    function setDetachmentTime (uint256 _time) public onlyManager {
        //Detactment Time can not be set greater than 2 weeks.
        require (_time <= 1209600);
        detachmentTime = uint32(_time);
    }

    /**
     * @dev        Detach Asset From System
     * @param      _tokenId  The token iddentifier
     */
    function setNFTDetached(uint256 _tokenId) public anyOperator {
        require (checkIsAttached(_tokenId) > 0);

        updateIsAttached(_tokenId, 0);
    }

    /**
     * @dev        Batch function to detach multiple assets
     * @param      _tokenIds  The token identifiers
     */
    function setBatchDetachCollectibles(uint256[] _tokenIds) public anyOperator {
        uint256 _id;
        for(uint i = 0; i < _tokenIds.length; i++) {
            _id = _tokenIds[i];
            setNFTDetached(_id);
        }
    }

    /**
     * @dev        Function to update attach value
     * @param      _tokenId     The asset id
     * @param      _isAttached  Indicates if attached
     */
    function updateIsAttached(uint256 _tokenId, uint256 _isAttached) internal {
        NFT memory obj  = _getAttributesOfToken(_tokenId);
        
        obj.isAttached = _isAttached;
    
        allNFTs[_tokenId] = obj;
        emit AssetUpdated(_tokenId);
    }

    /**
    * @dev   Facilitates Creating Sale using the Sale Contract. Forces owner check & collectibleId check
    * @notice Helps a wallet to create a sale using our Sale Contract
    * @param      _tokenId        The token identifier
    * @param      _startingPrice  The starting price
    * @param      _endingPrice    The ending price
    * @param      _duration       The duration
    */
    function initiateCreateSale(uint256 _tokenId, uint256 _startingPrice, uint256 _endingPrice, uint256 _duration) external {
        require (_tokenId != 0);
        
        // If MLBNFT is already on any sale, this will throw
        // because it will be owned by the sale contract.
        address owner = ownerOf(_tokenId);
        require (owner == msg.sender);

        // Sale contract checks input sizes
        require (_startingPrice == _startingPrice);
        require (_endingPrice == _endingPrice);
        require (_duration == _duration);

        require (checkIsAttached(_tokenId) == 0);
        
        // One time approval for the tokenID
        _approveForSale(msg.sender, address(saleManagerAddress), _tokenId);

        saleManagerAddress.createSale(_tokenId, _startingPrice, _endingPrice, _duration, msg.sender);
    }

    /**
     * @dev        Facilitates batch auction of collectibles, and enforeces strict checking on the collectibleId,starting/ending price, duration.
     * @notice     Batch function to put 10 or less collectibles on sale
     * @param      _tokenIds        The token identifier
     * @param      _startingPrices  The starting price
     * @param      _endingPrices    The ending price
     * @param      _durations       The duration
     */
    function batchCreateAssetSale(uint256[] _tokenIds, uint256[] _startingPrices, uint256[] _endingPrices, uint256[] _durations) external whenNotPaused {

        require (_tokenIds.length > 0 && _startingPrices.length > 0 && _endingPrices.length > 0 && _durations.length > 0);
        
        // Sale contract checks input sizes
        for(uint ii = 0; ii < _tokenIds.length; ii++){

            // Do not process for tokenId 0
            require (_tokenIds[ii] != 0);
            
            require (_startingPrices[ii] == _startingPrices[ii]);
            require (_endingPrices[ii] == _endingPrices[ii]);
            require (_durations[ii] == _durations[ii]);

            // If MLBNFT is already on any sale, this will throw
            // because it will be owned by the sale contract.
            address _owner = ownerOf(_tokenIds[ii]);
            address _msgSender = msg.sender;
            require (_owner == _msgSender);

            // Check whether the collectible is inPlay. If inPlay cant put it on Sale
            require (checkIsAttached(_tokenIds[ii]) == 0);
            
            // approve token to for Sale creation
            _approveForSale(msg.sender, address(saleManagerAddress), _tokenIds[ii]);
            
            saleManagerAddress.createSale(_tokenIds[ii], _startingPrices[ii], _endingPrices[ii], _durations[ii], msg.sender);
        }
    }
}

    Contract ABI  
[{"constant":true,"inputs":[{"name":"_interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokenIds","type":"uint256[]"},{"name":"_fromB","type":"address[]"},{"name":"_toB","type":"address[]"}],"name":"multiBatchSafeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_teamId","type":"uint8[]"},{"name":"_attributes","type":"uint256[]"},{"name":"_playerOverrideId","type":"uint256[]"},{"name":"_mlbPlayerId","type":"uint256[]"},{"name":"_to","type":"address[]"}],"name":"batchCreateAsset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"requestDetachment","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"implementsERC721","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_teamId","type":"uint8"},{"name":"_posId","type":"uint8"},{"name":"_attributes","type":"uint256"},{"name":"_owner","type":"address"},{"name":"_gameId","type":"uint256"},{"name":"_playerOverrideId","type":"uint256"},{"name":"_mlbPlayerId","type":"uint256"}],"name":"createETHCardCollectible","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spenders","type":"address[]"},{"name":"_approved","type":"bool"}],"name":"batchSetApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"detachmentTime","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"promoCreatedCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokenIds","type":"uint256[]"},{"name":"_fromB","type":"address[]"},{"name":"_toB","type":"address[]"}],"name":"multiBatchTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"generationSeasonDict","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"otherManagers","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"giftAsset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_saleManagerAddress","type":"address"}],"name":"setSaleManagerAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_flag","type":"bool"}],"name":"updateBatchSupport","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenIds","type":"uint256[]"},{"name":"_spender","type":"address"}],"name":"batchApprove","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_teamId","type":"uint8"},{"name":"_posId","type":"uint8"},{"name":"_attributes","type":"uint256"},{"name":"_owner","type":"address"},{"name":"_gameId","type":"uint256"},{"name":"_playerOverrideId","type":"uint256"},{"name":"_mlbPlayerId","type":"uint256"}],"name":"createRewardCollectible","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MLB_Legal","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"nftTeamIndexToCollectibleCount","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"contractsApprovedList","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"exists","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_teamId","type":"uint8"},{"name":"_posId","type":"uint8"},{"name":"_attributes","type":"uint256"},{"name":"_owner","type":"address"},{"name":"_gameId","type":"uint256"},{"name":"_playerOverrideId","type":"uint256"},{"name":"_mlbPlayerId","type":"uint256"}],"name":"createSeedCollectible","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"checkIsAttached","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newAddress","type":"address"}],"name":"removeFromApproveList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_time","type":"uint256"}],"name":"setDetachmentTime","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"InterfaceSignature_ERC721Optional","outputs":[{"name":"","type":"bytes4"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_gameCardNumber","type":"uint256"},{"name":"_playerId","type":"uint256"}],"name":"updateCurrentGameCardId","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"attachedSystemActive","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getGameCardId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_teamId","type":"uint8[]"},{"name":"_attributes","type":"uint256[]"},{"name":"_playerOverrideId","type":"uint256[]"},{"name":"_mlbPlayerId","type":"uint256[]"},{"name":"_to","type":"address[]"}],"name":"batchCreateETHCardAsset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isLSNFT","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"newContractAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokenIds","type":"uint256[]"}],"name":"batchDetachAssets","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getCollectibleDetails","outputs":[{"name":"isAttached","type":"uint256"},{"name":"sequenceId","type":"uint32"},{"name":"teamId","type":"uint8"},{"name":"positionId","type":"uint8"},{"name":"creationTime","type":"uint64"},{"name":"attributes","type":"uint256"},{"name":"playerOverrideId","type":"uint256"},{"name":"mlbGameId","type":"uint256"},{"name":"currentGameCardId","type":"uint256"},{"name":"mlbPlayerId","type":"uint256"},{"name":"earnedBy","type":"uint256"},{"name":"generationSeason","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_v2Address","type":"address"}],"name":"setNewAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rewardsRedeemed","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getTeamId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"},{"name":"_earnedBy","type":"uint256"}],"name":"updateEarnedBy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenIds","type":"uint256[]"},{"name":"_startingPrices","type":"uint256[]"},{"name":"_endingPrices","type":"uint256[]"},{"name":"_durations","type":"uint256[]"}],"name":"batchCreateAssetSale","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newGM","type":"address"}],"name":"setSecondaryManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getAbilitiesForCollectibleId","outputs":[{"name":"ability","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"name":"ownerTokens","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getPositionId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"removeAllAttachmentsFromCollectible","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenIds","type":"uint256[]"}],"name":"batchAttachAssets","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"noError","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_season","type":"uint256"},{"name":"_value","type":"uint64"}],"name":"updateGenerationDict","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenIds","type":"uint256[]"},{"name":"_from","type":"address"},{"name":"_to","type":"address"}],"name":"batchTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenIds","type":"uint256[]"},{"name":"_from","type":"address"},{"name":"_to","type":"address"}],"name":"batchSafeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"},{"name":"_attachment","type":"uint256"}],"name":"addAttachmentToCollectible","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"name":"nftCollectibleAttachments","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isBatchSupported","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokenIds","type":"uint256[]"}],"name":"setBatchDetachCollectibles","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"hasError","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"},{"name":"","type":"uint32"}],"name":"nftTeamIdToSequenceIdToCollectible","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"managerPrimary","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_teamId","type":"uint8"},{"name":"_posId","type":"uint8"},{"name":"_attributes","type":"uint256"},{"name":"_owner","type":"address"},{"name":"_gameId","type":"uint256"},{"name":"_playerOverrideId","type":"uint256"},{"name":"_mlbPlayerId","type":"uint256"}],"name":"createPromoCollectible","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"},{"name":"_startingPrice","type":"uint256"},{"name":"_endingPrice","type":"uint256"},{"name":"_duration","type":"uint256"}],"name":"initiateCreateSale","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newOp","type":"address"},{"name":"_state","type":"uint8"}],"name":"setOtherManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"seedCreatedCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newGM","type":"address"}],"name":"setPrimaryManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"attachAsset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"error","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_state","type":"bool"}],"name":"toggleAttachedEnforcement","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newAddress","type":"address"}],"name":"addToApproveList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_season","type":"uint256"}],"name":"setGenerationSeasonController","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"generationSeasonController","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"saleManagerAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokenURI","type":"string"}],"name":"setTokenURIBase","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"requestDetachmentOnPause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getAssetAttachment","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"setNFTDetached","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_season","type":"uint256"},{"name":"_value","type":"uint8"}],"name":"updateGenerationStopTime","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"},{"name":"_newOverrideId","type":"uint256"}],"name":"setPlayerOverrideId","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"bankManager","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ERC721_RECEIVED","outputs":[{"name":"","type":"bytes4"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"managerSecondary","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newBK","type":"address"}],"name":"setBanker","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getPlayerId","outputs":[{"name":"playerId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newContract","type":"address"}],"name":"ContractUpgrade","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"tokenId","type":"uint256"}],"name":"AssetUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"tokenId","type":"uint256"}],"name":"Created","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":true,"name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_approved","type":"address"},{"indexed":true,"name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_operator","type":"address"},{"indexed":false,"name":"_approved","type":"bool"}],"name":"ApprovalForAll","type":"event"}]

  Contract Creation Code Switch To Opcodes View
60806040526015805461ffff1916905560006016556037805460ff191660011790556039805460a060020a63ffffffff02191690553480156200004157600080fd5b506015805460ff1916600117905560118054600160a060020a03199081163390811790925560128054821683178155601380549092169092179055604080518082019091528181527f4c7563696453696768742d4d4c422d4e465400000000000000000000000000006020909101908152620000c191600491906200010d565b506040805180820190915260058082527f4d4c42434200000000000000000000000000000000000000000000000000000060209092019182526200010691816200010d565b50620001b2565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200015057805160ff191683800117855562000180565b8280016001018555821562000180579182015b828111156200018057825182559160200191906001019062000163565b506200018e92915062000192565b5090565b620001af91905b808211156200018e576000815560010162000199565b90565b61512080620001c26000396000f3006080604052600436106104605763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166301ffc9a7811461046557806306fdde031461049b57806307ff141314610525578063081812fc146105ee578063095ea7b314610622578063098e652b146106465780630dec1c23146106965780631051db34146106ae578063116ea900146106c3578063173428591461070e57806318160ddd146107675780631b825e891461077c5780631d6b0b82146107aa57806321bcc5e5146107c257806322d4cda31461088957806323b872dd146108a157806323d7af24146108cb5780632f745c59146109025780633331f3911461092657806335f3cf851461094a578063362f74e71461096b57806338752e58146109855780633f4ba83a146109e557806341763225146109fa57806342842e0e14610a3357806342c81f4514610a5d57806343ef32c314610a725780634e8522fb14610a8a5780634f558e7914610aab5780634f6ccce714610ac35780634f6d04e714610adb5780635265440c14610b14578063568f57e114610b2c5780635bc8a67214610b4d5780635c975abb14610b65578063624de3d914610b7a5780636352211e14610bac578063635439ac14610bc45780636554d17914610bdf5780636653be1a14610bf45780636723eab514610c0c5780636a8d7eb3146106ae5780636af04a5714610c5c5780636ff2817c14610c7157806370994b3114610cc657806370a0823114610d515780637158798814610d7257806374f6164214610d935780637942857014610da85780637fcf64b214610dc05780637ff860f614610ddb578063825bdb7414610e1f57806382d4004114610e405780638456cb5914610e585780638462151c14610e6d57806385d19a2514610ede57806386a3171f14610ef65780638920641114610f0e5780638a53f23014610f635780638c1e04a614610f7857806391177db414610f9d5780639493f0121461100857806395d89b41146110735780639ad8b5b714611088578063a22cb465146110a3578063a678108e146110c9578063aaeaa36c146110e4578063abd44556146110f9578063ad5e46cb1461114e578063b478f15a14611163578063b777cad714611184578063b7dcf6a914611199578063b88d4fde146111d2578063b8bdf70114611241578063bb1d45fc14611262578063bb642f6514611289578063c0619c701461129e578063c0f64f43146112bf578063c79f8b62146112d7578063c7e59334146112ec578063c87b56dd14611306578063d0b368a01461131e578063d37990ce1461133f578063d8b61a7714611357578063d9a96f9b1461136f578063da2bbfc714611384578063dd280c7a146113dd578063de0b18f2146113f5578063e080241c1461140d578063e172a57e14611425578063e96d01d414611443578063e985e9c51461145e578063e9e2990e14611485578063ecc98ce41461149a578063ee70f392146114af578063f1ff732b146114c4578063f4385912146114e5575b600080fd5b34801561047157600080fd5b50610487600160e060020a0319600435166114fd565b604080519115158252519081900360200190f35b3480156104a757600080fd5b506104b06115ce565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104ea5781810151838201526020016104d2565b50505050905090810190601f1680156105175780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561053157600080fd5b50604080516020600480358082013583810280860185019096528085526105ec95369593946024949385019291829185019084908082843750506040805187358901803560208181028481018201909552818452989b9a998901989297509082019550935083925085019084908082843750506040805187358901803560208181028481018201909552818452989b9a9989019892975090820195509350839250850190849080828437509497506116659650505050505050565b005b3480156105fa57600080fd5b506106066004356117a1565b60408051600160a060020a039092168252519081900360200190f35b34801561062e57600080fd5b506105ec600160a060020a03600435166024356117bc565b34801561065257600080fd5b506105ec6024600480358281019290820135918135808301929082013591604435808301929082013591606435808301929082013591608435918201910135611865565b3480156106a257600080fd5b506105ec600435611b20565b3480156106ba57600080fd5b50610487611bee565b3480156106cf57600080fd5b506106fc60ff60043581169060243516604435600160a060020a036064351660843560a43560c435611bf3565b60408051918252519081900360200190f35b34801561071a57600080fd5b50604080516020600480358082013583810280860185019096528085526105ec95369593946024949385019291829185019084908082843750949750505050913515159250611d17915050565b34801561077357600080fd5b506106fc611da9565b34801561078857600080fd5b50610791611daf565b6040805163ffffffff9092168252519081900360200190f35b3480156107b657600080fd5b506106fc600435611dd3565b3480156107ce57600080fd5b50604080516020600480358082013583810280860185019096528085526105ec95369593946024949385019291829185019084908082843750506040805187358901803560208181028481018201909552818452989b9a998901989297509082019550935083925085019084908082843750506040805187358901803560208181028481018201909552818452989b9a998901989297509082019550935083925085019084908082843750949750611de79650505050505050565b34801561089557600080fd5b506106fc600435611f1a565b3480156108ad57600080fd5b506105ec600160a060020a0360043581169060243516604435611f2c565b3480156108d757600080fd5b506108ec600160a060020a03600435166120ef565b6040805160ff9092168252519081900360200190f35b34801561090e57600080fd5b506106fc600160a060020a0360043516602435612104565b34801561093257600080fd5b506105ec600160a060020a0360043516602435612151565b34801561095657600080fd5b506105ec600160a060020a036004351661216c565b34801561097757600080fd5b506105ec60043515156121d1565b34801561099157600080fd5b50604080516020600480358082013583810280860185019096528085526105ec9536959394602494938501929182918501908490808284375094975050509235600160a060020a0316935061221292505050565b3480156109f157600080fd5b506105ec6122a8565b348015610a0657600080fd5b506106fc60ff60043581169060243516604435600160a060020a036064351660843560a43560c4356122e0565b348015610a3f57600080fd5b506105ec600160a060020a03600435811690602435166044356123f4565b348015610a6957600080fd5b506104b0612537565b348015610a7e57600080fd5b506107916004356125e3565b348015610a9657600080fd5b50610487600160a060020a03600435166125fb565b348015610ab757600080fd5b50610487600435612610565b348015610acf57600080fd5b506106fc60043561262d565b348015610ae757600080fd5b506106fc60ff60043581169060243516604435600160a060020a036064351660843560a43560c435612662565b348015610b2057600080fd5b506106fc6004356126ff565b348015610b3857600080fd5b506105ec600160a060020a036004351661271d565b348015610b5957600080fd5b506105ec600435612793565b348015610b7157600080fd5b50610487612819565b348015610b8657600080fd5b50610b8f612822565b60408051600160e060020a03199092168252519081900360200190f35b348015610bb857600080fd5b50610606600435612846565b348015610bd057600080fd5b506105ec60043560243561286a565b348015610beb57600080fd5b50610487612943565b348015610c0057600080fd5b506106fc600435612953565b348015610c1857600080fd5b506105ec6024600480358281019290820135918135808301929082013591604435808301929082013591606435808301929082013591608435918201910135612971565b348015610c6857600080fd5b50610606612c0b565b348015610c7d57600080fd5b50604080516020600480358082013583810280860185019096528085526105ec95369593946024949385019291829185019084908082843750949750612c1a9650505050505050565b348015610cd257600080fd5b50610cde600435612c63565b604080519c8d5263ffffffff909b1660208d015260ff998a168c8c01529790981660608b015267ffffffffffffffff90951660808a015260a089019390935260c088019190915260e087015261010086015261012085015261014084019190915261016083015251908190036101800190f35b348015610d5d57600080fd5b506106fc600160a060020a0360043516612d32565b348015610d7e57600080fd5b506105ec600160a060020a0360043516612d65565b348015610d9f57600080fd5b506106fc612dfc565b348015610db457600080fd5b506106fc600435612e02565b348015610dcc57600080fd5b506105ec600435602435612e36565b348015610de757600080fd5b506105ec6024600480358281019290820135918135808301929082013591604435808301929082013591606435918201910135612e92565b348015610e2b57600080fd5b506105ec600160a060020a0360043516613140565b348015610e4c57600080fd5b506106fc6004356131a5565b348015610e6457600080fd5b506105ec6131c8565b348015610e7957600080fd5b50610e8e600160a060020a0360043516613215565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610eca578181015183820152602001610eb2565b505050509050019250505060405180910390f35b348015610eea57600080fd5b506106fc6004356132cd565b348015610f0257600080fd5b506105ec600435613302565b348015610f1a57600080fd5b50604080516020600480358082013583810280860185019096528085526105ec9536959394602494938501929182918501908490808284375094975061338f9650505050505050565b348015610f6f57600080fd5b506105ec6133d8565b348015610f8457600080fd5b506105ec60043567ffffffffffffffff60243516613424565b348015610fa957600080fd5b50604080516020600480358082013583810280860185019096528085526105ec9536959394602494938501929182918501908490808284375094975050600160a060020a03853581169650602090950135909416935061349d92505050565b34801561101457600080fd5b50604080516020600480358082013583810280860185019096528085526105ec9536959394602494938501929182918501908490808284375094975050600160a060020a03853581169650602090950135909416935061354892505050565b34801561107f57600080fd5b506104b06135f3565b34801561109457600080fd5b506105ec600435602435613654565b3480156110af57600080fd5b506105ec600160a060020a036004351660243515156136ef565b3480156110d557600080fd5b506106fc600435602435613773565b3480156110f057600080fd5b506104876137a3565b34801561110557600080fd5b50604080516020600480358082013583810280860185019096528085526105ec953695939460249493850192918291850190849080828437509497506137ac9650505050505050565b34801561115a57600080fd5b506105ec61384e565b34801561116f57600080fd5b506106fc60043563ffffffff6024351661389e565b34801561119057600080fd5b506106066138bb565b3480156111a557600080fd5b506106fc60ff60043581169060243516604435600160a060020a036064351660843560a43560c4356138ca565b3480156111de57600080fd5b50604080516020601f6064356004818101359283018490048402850184019095528184526105ec94600160a060020a0381358116956024803590921695604435953695608494019181908401838280828437509497506139829650505050505050565b34801561124d57600080fd5b506105ec600435602435604435606435613acc565b34801561126e57600080fd5b506105ec600160a060020a036004351660ff60243516613bc5565b34801561129557600080fd5b506106fc613c35565b3480156112aa57600080fd5b506105ec600160a060020a0360043516613c3b565b3480156112cb57600080fd5b506105ec600435613ca0565b3480156112e357600080fd5b50610487613e0d565b3480156112f857600080fd5b506105ec6004351515613e1b565b34801561131257600080fd5b506104b0600435613e7c565b34801561132a57600080fd5b506105ec600160a060020a0360043516613f24565b34801561134b57600080fd5b506105ec600435613f9c565b34801561136357600080fd5b506106fc600435614001565b34801561137b57600080fd5b50610606614013565b34801561139057600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526105ec9436949293602493928401919081908401838280828437509497506140229650505050505050565b3480156113e957600080fd5b506105ec60043561408b565b34801561140157600080fd5b50610e8e6004356140bc565b34801561141957600080fd5b506105ec600435614163565b34801561143157600080fd5b506105ec60043560ff602435166141d8565b34801561144f57600080fd5b506105ec60043560243561424b565b34801561146a57600080fd5b50610487600160a060020a03600435811690602435166142a7565b34801561149157600080fd5b506106066142d5565b3480156114a657600080fd5b50610b8f6142e4565b3480156114bb57600080fd5b50610606614308565b3480156114d057600080fd5b506105ec600160a060020a0360043516614317565b3480156114f157600080fd5b506106fc60043561437c565b6000600160e060020a031982167f01ffc9a70000000000000000000000000000000000000000000000000000000014806115605750600160e060020a031982167f80ac58cd00000000000000000000000000000000000000000000000000000000145b806115945750600160e060020a031982167f780e9d6300000000000000000000000000000000000000000000000000000000145b806115c85750600160e060020a031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b92915050565b60048054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561165a5780601f1061162f5761010080835404028352916020019161165a565b820191906000526020600020905b81548152906001019060200180831161163d57829003601f168201915b505050505090505b90565b60375460009081908190819060ff16151561167f57600080fd5b60008751118015611691575060008651115b801561169e575060008551115b15156116a957600080fd5b5060005b86518110156117985786818151811015156116c457fe5b906020019060200201516000141580156116ff575085818151811015156116e757fe5b90602001906020020151600160a060020a0316600014155b801561172c5750848181518110151561171457fe5b90602001906020020151600160a060020a0316600014155b151561173757600080fd5b868181518110151561174557fe5b906020019060200201519350848181518110151561175f57fe5b906020019060200201519250858181518110151561177957fe5b9060200190602002015191506117908284866123f4565b6001016116ad565b50505050505050565b600090815260016020526040902054600160a060020a031690565b60006117c782612846565b9050600160a060020a0383811690821614156117e257600080fd5b33600160a060020a03821614806117fe57506117fe81336142a7565b151561180957600080fd5b6000828152600160205260408082208054600160a060020a031916600160a060020a0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600061186f614f95565b3360009081526038602052604081205460ff16806118975750601154600160a060020a031633145b806118ac5750601254600160a060020a031633145b15156118b757600080fd5b60155460ff16156118c757600080fd5b60375460ff1615156118d857600080fd5b60008c1180156118e8575060008a115b80156118f45750600088115b80156119005750600086115b801561190c5750600084115b151561191757600080fd5b5060005b89811015611b1157600085858381811061193157fe5b90506020020135600160a060020a0316600160a060020a03161415801561197157508c8c8281811061195f57fe5b9050602002013560ff1660ff16600014155b801561197c57508915155b801561199b575086868281811061198f57fe5b90506020020135600014155b15156119a657600080fd5b67ffffffffffffffff4216925060406119d68e8e848181106119c457fe5b9050602002013560ff1660ff166143c1565b63ffffffff169060020a028317925060608d8d8381811015156119f557fe5b9050602002013560ff1660ff169060020a028317925060686103207002f050fe938943acc45f655680000000008d8d858181101515611a3057fe5b90506020020135811515611a4057fe5b04039060020a028317925060a0604051908101604052808481526020018c8c848181101515611a6b57fe5b905060200201358152602001600081526020018a8a848181101515611a8c57fe5b9050602002013581526020018888848181101515611aa657fe5b905060200201358152509150611b088d8d838181101515611ac357fe5b9050602002013560ff168c8c848181101515611adb57fe5b905060200201358787858181101515611af057fe5b90506020020135600160a060020a03166000866143de565b5060010161191b565b50505050505050505050505050565b6000611b2c338361447a565b1515611b3757600080fd5b611b40826126ff565b9050611b4b82612953565b15611b5557600080fd5b6001811015611b6357600080fd5b60395460c060020a900460ff16151560011415611bdc57600181118015611bac575060395474010000000000000000000000000000000000000000900463ffffffff1642829003115b15611bb957506000611bd7565b6001811115611bd45760018114611bcf57600080fd5b611bd7565b50425b611be0565b5060005b611bea82826144d9565b5050565b600190565b600080600080611c01614f95565b3360009081526038602052604090205460ff1680611c295750601154600160a060020a031633145b80611c3e5750601254600160a060020a031633145b1515611c4957600080fd5b60155460ff1615611c5957600080fd5b889350600160a060020a0384161515611c7b57601154600160a060020a031693505b601680546001019055611c9060ff8d166143c1565b92504267ffffffffffffffff16915060408363ffffffff169060020a028217915060608c60ff169060020a028217915060688b60ff169060020a028217915060a0604051908101604052808381526020018b8152602001898152602001888152602001878152509050611d078c8b866002856143de565b9c9b505050505050505050505050565b603754600090819060ff161515611d2d57600080fd5b8351600010611d3b57600080fd5b5060005b8351811015611da3578351600090859083908110611d5957fe5b60209081029091010151600160a060020a03161415611d7757600080fd5b8381815181101515611d8557fe5b906020019060200201519150611d9b82846136ef565b600101611d3f565b50505050565b60085490565b60395474010000000000000000000000000000000000000000900463ffffffff1681565b601781601f8110611de057fe5b0154905081565b60375460009081908190819060ff161515611e0157600080fd5b60008751118015611e13575060008651115b8015611e20575060008551115b1515611e2b57600080fd5b5060005b8651811015611798578681815181101515611e4657fe5b90602001906020020151600014158015611e8157508581815181101515611e6957fe5b90602001906020020151600160a060020a0316600014155b8015611eae57508481815181101515611e9657fe5b90602001906020020151600160a060020a0316600014155b1515611eb957600080fd5b8681815181101515611ec757fe5b9060200190602002015193508481815181101515611ee157fe5b9060200190602002015192508581815181101515611efb57fe5b906020019060200201519150611f12828486611f2c565b600101611e2f565b60106020526000908152604090205481565b806000611f38826126ff565b90508060021415611fb357601154600160a060020a0316331480611f665750601254600160a060020a031633145b80611f7b5750601354600160a060020a031633145b80611f9857503360009081526014602052604090205460ff166001145b1515611fa357600080fd5b611fae8260006144d9565b61204c565b60395460c060020a900460ff1615156001148015611fd2575060018110155b1561203757601154600160a060020a0316331480611ffa5750601254600160a060020a031633145b8061200f5750601354600160a060020a031633145b8061202c57503360009081526014602052604090205460ff166001145b1515611fae57600080fd5b612041338361447a565b151561204c57600080fd5b612055836126ff565b1561205f57600080fd5b600160a060020a038516151561207457600080fd5b600160a060020a038416151561208957600080fd5b6120938584614586565b61209d85846145e8565b6120a784846146ef565b8284600160a060020a031686600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050565b60146020526000908152604090205460ff1681565b600061210f83612d32565b821061211a57600080fd5b600160a060020a038316600090815260066020526040902080548390811061213e57fe5b9060005260206000200154905092915050565b60155460ff161561216157600080fd5b611bea3383836123f4565b601154600160a060020a031633148061218f5750601254600160a060020a031633145b151561219a57600080fd5b600160a060020a03811615156121af57600080fd5b603a8054600160a060020a031916600160a060020a0392909216919091179055565b601154600160a060020a03163314806121f45750601254600160a060020a031633145b15156121ff57600080fd5b6037805460ff1916911515919091179055565b603754600090819060ff16151561222857600080fd5b600084511180156122415750600160a060020a03831615155b151561224c57600080fd5b5060005b8351811015611da357838181518110151561226757fe5b60209081029091010151151561227c57600080fd5b838181518110151561228a57fe5b9060200190602002015191506122a083836117bc565b600101612250565b601154600160a060020a03163314806122cb5750601254600160a060020a031633145b15156122d657600080fd5b6122de614738565b565b6000806000806122ee614f95565b3360009081526038602052604090205460ff16806123165750601154600160a060020a031633145b8061232b5750601254600160a060020a031633145b151561233657600080fd5b60155460ff161561234657600080fd5b889350600160a060020a038416151561236857601154600160a060020a031693505b60168054600101905561237d60ff8d166143c1565b92504267ffffffffffffffff16915060408363ffffffff169060020a028217915060608c60ff169060020a028217915060688b60ff169060020a028217915060a0604051908101604052808381526020018b8152602001898152602001888152602001878152509050611d078c8b866000856143de565b806000612400826126ff565b9050806002141561247b57601154600160a060020a031633148061242e5750601254600160a060020a031633145b806124435750601354600160a060020a031633145b8061246057503360009081526014602052604090205460ff166001145b151561246b57600080fd5b6124768260006144d9565b612514565b60395460c060020a900460ff161515600114801561249a575060018110155b156124ff57601154600160a060020a03163314806124c25750601254600160a060020a031633145b806124d75750601354600160a060020a031633145b806124f457503360009081526014602052604090205460ff166001145b151561247657600080fd5b612509338361447a565b151561251457600080fd5b6125308585856020604051908101604052806000815250613982565b5050505050565b60a060405190810160405280607c81526020017f4d616a6f72204c6561677565204261736562616c6c2074726164656d61726b7381526020017f20616e6420636f7079726967687473206172652075736564207769746820706581526020017f726d697373696f6e206f6620746865206170706c696361626c65204d4c42206581526020017f6e746974792e2020416c6c207269676874732072657365727665642e0000000081525081565b600d6020526000908152604090205463ffffffff1681565b60386020526000908152604090205460ff1681565b600090815260208190526040902054600160a060020a0316151590565b6000612637611da9565b821061264257600080fd5b600880548390811061265057fe5b90600052602060002001549050919050565b600080600080612670614f95565b3360009081526038602052604090205460ff16806126985750601154600160a060020a031633145b806126ad5750601254600160a060020a031633145b15156126b857600080fd5b60155460ff16156126c857600080fd5b889350600160a060020a03841615156126ea57601154600160a060020a031693505b60368054600101905561237d60ff8d166143c1565b6000612709614fb4565b61271283614783565b60e001519392505050565b601154600160a060020a03163314806127405750601254600160a060020a031633145b151561274b57600080fd5b600160a060020a03811660009081526038602052604090205460ff16151561277257600080fd5b600160a060020a03166000908152603860205260409020805460ff19169055565b601154600160a060020a03163314806127b65750601254600160a060020a031633145b15156127c157600080fd5b621275008111156127d157600080fd5b6039805463ffffffff909216740100000000000000000000000000000000000000000277ffffffff000000000000000000000000000000000000000019909216919091179055565b60155460ff1681565b7fb0aa71870000000000000000000000000000000000000000000000000000000081565b600081815260208190526040812054600160a060020a03168015156115c857600080fd5b612872614fb4565b60155460ff161561288257600080fd5b3360009081526038602052604090205460ff1615156128a057600080fd5b6128a982614783565b6020810184905290508215156128c557600060e08201526128cd565b600160e08201525b80600b838154811015156128dd57fe5b9060005260206000209060080201600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e08201518160070155905050505050565b60395460c060020a900460ff1681565b600061295d614fb4565b61296683614783565b602001519392505050565b600061297b614f95565b3360009081526038602052604081205460ff16806129a35750601154600160a060020a031633145b806129b85750601254600160a060020a031633145b15156129c357600080fd5b60155460ff16156129d357600080fd5b60375460ff1615156129e457600080fd5b60008c1180156129f4575060008a115b8015612a005750600088115b8015612a0c5750600086115b8015612a185750600084115b1515612a2357600080fd5b5060005b89811015611b11576000858583818110612a3d57fe5b90506020020135600160a060020a0316600160a060020a031614158015612a7d57508c8c82818110612a6b57fe5b9050602002013560ff1660ff16600014155b8015612a8857508915155b8015612aa75750868682818110612a9b57fe5b90506020020135600014155b1515612ab257600080fd5b67ffffffffffffffff421692506040612ad08e8e848181106119c457fe5b63ffffffff169060020a028317925060608d8d838181101515612aef57fe5b9050602002013560ff1660ff169060020a028317925060686103207002f050fe938943acc45f655680000000008d8d858181101515612b2a57fe5b90506020020135811515612b3a57fe5b04039060020a028317925060a0604051908101604052808481526020018c8c848181101515612b6557fe5b905060200201358152602001600081526020018a8a848181101515612b8657fe5b9050602002013581526020018888848181101515612ba057fe5b905060200201358152509150612c028d8d838181101515612bbd57fe5b9050602002013560ff168c8c848181101515612bd557fe5b905060200201358787858181101515612bea57fe5b90506020020135600160a060020a03166002866143de565b50600101612a27565b603954600160a060020a031681565b60375460009060ff161515612c2e57600080fd5b5060005b8151811015611bea57612c5b8282815181101515612c4c57fe5b90602001906020020151611b20565b600101612c32565b600080600080600080600080600080600080612c7d614fb4565b612c868e614783565b905080600001519750806020015194508060400151955080606001519650806080015193508060c00151985060408160c001519060020a90049b5060608160c001519060020a90049a5060688160c001519060020a900499508060e001519c508060a001519250601060006103e8620f42408460000151811515612d0657fe5b06811515612d1057fe5b0481526020019081526020016000205491505091939597999b5091939597999b565b6000600160a060020a0382161515612d4957600080fd5b50600160a060020a031660009081526002602052604090205490565b601154600160a060020a0316331480612d885750601254600160a060020a031633145b1515612d9357600080fd5b600160a060020a0381161515612da857600080fd5b60398054600160a060020a038316600160a060020a0319909116811790915560408051918252517f450db8da6efbe9c22f2347f7c2021231df1fc58d3ae9a2fa75d39fa4461993059181900360200190a150565b60165481565b6000612e0c614fb4565b6000612e1784614783565b60c001516c01000000000000000000000000900460ff16949350505050565b601154600160a060020a0316331480612e595750601254600160a060020a031633145b1515612e6457600080fd5b60155460ff1615612e7457600080fd5b612e7d82612610565b1515612e8857600080fd5b611bea8282614812565b6015546000908190819060ff1615612ea957600080fd5b60008a118015612eb95750600088115b8015612ec55750600086115b8015612ed15750600084115b1515612edc57600080fd5b600092505b89831015613133578a8a84818110612ef557fe5b90506020020135600014151515612f0b57600080fd5b888884818110612f1757fe5b905060200201358989858181101515612f2c57fe5b90506020020135141515612f3f57600080fd5b868684818110612f4b57fe5b905060200201358787858181101515612f6057fe5b90506020020135141515612f7357600080fd5b848484818110612f7f57fe5b905060200201358585858181101515612f9457fe5b90506020020135141515612fa757600080fd5b612fc28b8b85818110612fb657fe5b90506020020135612846565b9150339050600160a060020a0382168114612fdc57600080fd5b612ff78b8b85818110612feb57fe5b905060200201356126ff565b1561300157600080fd5b603a5461302b903390600160a060020a03168d8d8781811061301f57fe5b905060200201356148d7565b603a54600160a060020a03166372a1b73f8c8c8681811061304857fe5b905060200201358b8b87818110151561305d57fe5b905060200201358a8a88818110151561307257fe5b90506020020135898989818110151561308757fe5b90506020020135336040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086815260200185815260200184815260200183815260200182600160a060020a0316600160a060020a0316815260200195505050505050600060405180830381600087803b15801561310f57600080fd5b505af1158015613123573d6000803e3d6000fd5b505060019094019350612ee19050565b5050505050505050505050565b601154600160a060020a03163314806131635750601254600160a060020a031633145b151561316e57600080fd5b600160a060020a038116151561318357600080fd5b60128054600160a060020a031916600160a060020a0392909216919091179055565b60006131af614fb4565b60006131ba84614783565b516103e89006949350505050565b601154600160a060020a03163314806131eb5750601254600160a060020a031633145b15156131f657600080fd5b60155460ff161561320657600080fd5b6015805460ff19166001179055565b606060006060600080600061322987612d32565b94508415156132485760408051600081526020810190915295506132c3565b84604051908082528060200260200182016040528015613272578160200160208202803883390190505b50935061327e87612d32565b925060009150600090505b828110156132bf5761329b8782612104565b84838151811015156132a957fe5b6020908102909101015260019182019101613289565b8395505b5050505050919050565b60006132d7614fb4565b60006132e284614783565b60c001516d0100000000000000000000000000900460ff16949350505050565b601154600160a060020a03163314806133255750601254600160a060020a031633145b151561333057600080fd5b60155460ff161561334057600080fd5b61334981612610565b151561335457600080fd5b6000818152600e6020526040812061336b91614ffa565b6040805182815290516000805160206150d58339815191529181900360200190a150565b60375460009060ff1615156133a357600080fd5b5060005b8151811015611bea576133d082828151811015156133c157fe5b90602001906020020151613ca0565b6001016133a7565b601154600160a060020a03163314806133fb5750601254600160a060020a031633145b151561340657600080fd5b60155460ff16151561341757600080fd5b6015805461ff0019169055565b601154600160a060020a03163314806134475750601254600160a060020a031633145b151561345257600080fd5b60155460ff161561346257600080fd5b6000828152601060205260409020546001101561347e57600080fd5b60009182526010602052604090912067ffffffffffffffff9091169055565b603754600090819060ff1615156134b357600080fd5b600085511180156134cc5750600160a060020a03841615155b80156134e05750600160a060020a03831615155b15156134eb57600080fd5b5060005b845181101561253057848181518110151561350657fe5b60209081029091010151151561351b57600080fd5b848181518110151561352957fe5b906020019060200201519150613540848484611f2c565b6001016134ef565b603754600090819060ff16151561355e57600080fd5b600085511180156135775750600160a060020a03841615155b801561358b5750600160a060020a03831615155b151561359657600080fd5b5060005b84518110156125305784818151811015156135b157fe5b6020908102909101015115156135c657600080fd5b84818151811015156135d457fe5b9060200190602002015191506135eb8484846123f4565b60010161359a565b60058054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561165a5780601f1061162f5761010080835404028352916020019161165a565b601154600160a060020a03163314806136775750601254600160a060020a031633145b151561368257600080fd5b60155460ff161561369257600080fd5b61369b82612610565b15156136a657600080fd5b6000828152600e60209081526040808320805460018101825590845292829020909201839055815184815291516000805160206150d58339815191529281900390910190a15050565b600160a060020a03821633141561370557600080fd5b336000818152600360209081526040808320600160a060020a03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b600e6020528160005260406000208181548110151561378e57fe5b90600052602060002001600091509150505481565b60375460ff1681565b6011546000908190600160a060020a03163314806137d45750601254600160a060020a031633145b806137e95750601354600160a060020a031633145b8061380657503360009081526014602052604090205460ff166001145b151561381157600080fd5b5060005b825181101561384957828181518110151561382c57fe5b90602001906020020151915061384182614163565b600101613815565b505050565b601154600160a060020a03163314806138715750601254600160a060020a031633145b151561387c57600080fd5b60155460ff16151561388d57600080fd5b6015805461ff001916610100179055565b600c60209081526000928352604080842090915290825290205481565b601154600160a060020a031681565b6000806000806138d8614f95565b3360009081526038602052604090205460ff16806139005750601154600160a060020a031633145b806139155750601254600160a060020a031633145b151561392057600080fd5b60155460ff161561393057600080fd5b889350600160a060020a038416151561395257601154600160a060020a031693505b600b546000101561397657601760ff8d16601f811061396d57fe5b01805460010190555b61237d8c60ff166143c1565b81600061398e826126ff565b90508060021415613a0957601154600160a060020a03163314806139bc5750601254600160a060020a031633145b806139d15750601354600160a060020a031633145b806139ee57503360009081526014602052604090205460ff166001145b15156139f957600080fd5b613a048260006144d9565b613aa2565b60395460c060020a900460ff1615156001148015613a28575060018110155b15613a8d57601154600160a060020a0316331480613a505750601254600160a060020a031633145b80613a655750601354600160a060020a031633145b80613a8257503360009081526014602052604090205460ff166001145b1515613a0457600080fd5b613a97338361447a565b1515613aa257600080fd5b613aad868686611f2c565b613ab9868686866149b8565b1515613ac457600080fd5b505050505050565b6000841515613ada57600080fd5b613ae385612846565b9050600160a060020a0381163314613afa57600080fd5b613b03856126ff565b15613b0d57600080fd5b603a54613b25903390600160a060020a0316876148d7565b603a54604080517f72a1b73f000000000000000000000000000000000000000000000000000000008152600481018890526024810187905260448101869052606481018590523360848201529051600160a060020a03909216916372a1b73f9160a48082019260009290919082900301818387803b158015613ba657600080fd5b505af1158015613bba573d6000803e3d6000fd5b505050505050505050565b601154600160a060020a0316331480613be85750601254600160a060020a031633145b1515613bf357600080fd5b600160a060020a0382161515613c0857600080fd5b600160a060020a03919091166000908152601460205260409020805460ff191660ff909216919091179055565b60365481565b601154600160a060020a0316331480613c5e5750601254600160a060020a031633145b1515613c6957600080fd5b600160a060020a0381161515613c7e57600080fd5b60118054600160a060020a031916600160a060020a0392909216919091179055565b6000816000613cae826126ff565b90508060021415613d2957601154600160a060020a0316331480613cdc5750601254600160a060020a031633145b80613cf15750601354600160a060020a031633145b80613d0e57503360009081526014602052604090205460ff166001145b1515613d1957600080fd5b613d248260006144d9565b613dc2565b60395460c060020a900460ff1615156001148015613d48575060018110155b15613dad57601154600160a060020a0316331480613d705750601254600160a060020a031633145b80613d855750601354600160a060020a031633145b80613da257503360009081526014602052604090205460ff166001145b1515613d2457600080fd5b613db7338361447a565b1515613dc257600080fd5b613dcb846126ff565b92508215613dd857600080fd5b60019250613de684846144d9565b6040805185815290516000805160206150d58339815191529181900360200190a150505050565b601554610100900460ff1681565b601154600160a060020a0316331480613e3e5750601254600160a060020a031633145b1515613e4957600080fd5b6039805491151560c060020a0278ff00000000000000000000000000000000000000000000000019909216919091179055565b6060613e8782612610565b1515613e9257600080fd5b600a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015613f185780601f10613eed57610100808354040283529160200191613f18565b820191906000526020600020905b815481529060010190602001808311613efb57829003601f168201915b50505050509050919050565b601154600160a060020a0316331480613f475750601254600160a060020a031633145b1515613f5257600080fd5b600160a060020a03811660009081526038602052604090205460ff1615613f7857600080fd5b600160a060020a03166000908152603860205260409020805460ff19166001179055565b601154600160a060020a0316331480613fbf5750601254600160a060020a031633145b1515613fca57600080fd5b60155460ff1615613fda57600080fd5b6000818152600f602052604090205415613ff357600080fd5b613ffe816001614b25565b50565b600f6020526000908152604090205481565b603a54600160a060020a031681565b601154600160a060020a03163314806140455750601254600160a060020a031633145b8061405a5750601354600160a060020a031633145b8061407757503360009081526014602052604090205460ff166001145b151561408257600080fd5b613ffe81614b3d565b60155460ff16151561409c57600080fd5b6140a6338261447a565b15156140b157600080fd5b613ffe8160006144d9565b6000818152600e60205260408120606091805b825481101561410d578183828154811015156140e757fe5b6000918252602080832090910154835460018181018655948452919092200155016140cf565b81546040805160208084028201810190925282815291849183018282801561415457602002820191906000526020600020905b815481526020019060010190808311614140575b50505050509350505050919050565b601154600160a060020a03163314806141865750601254600160a060020a031633145b8061419b5750601354600160a060020a031633145b806141b857503360009081526014602052604090205460ff166001145b15156141c357600080fd5b60006141ce826126ff565b116140b157600080fd5b601154600160a060020a03163314806141fb5750601254600160a060020a031633145b151561420657600080fd5b60155460ff161561421657600080fd5b6000828152600f60205260409020546001148015614236575060ff811615155b151561424157600080fd5b611bea8282614b25565b601154600160a060020a031633148061426e5750601254600160a060020a031633145b151561427957600080fd5b60155460ff161561428957600080fd5b61429282612610565b151561429d57600080fd5b611bea8282614b50565b600160a060020a03918216600090815260036020908152604080832093909416825291909152205460ff1690565b601354600160a060020a031681565b7f150b7a020000000000000000000000000000000000000000000000000000000081565b601254600160a060020a031681565b601154600160a060020a031633148061433a5750601254600160a060020a031633145b151561434557600080fd5b600160a060020a038116151561435a57600080fd5b60138054600160a060020a031916600160a060020a0392909216919091179055565b6000614386614fb4565b61438f83614783565b80519091506103e8906143b09067016345785d8a000063ffffffff614b8a16565b8115156143b957fe5b069392505050565b6000818152600d602052604090205463ffffffff16600101919050565b60008080806143f4620f424089066103e8614b8a565b6000818152600f602052604090205490935060011461441257600080fd5b61441e8960ff166143c1565b915061442b858888614bad565b60ff999099166000818152600c6020908152604080832063ffffffff969096168084529582528083208d9055928252600d905220805463ffffffff191690921790915550959695505050505050565b60008061448683612846565b905080600160a060020a031684600160a060020a031614806144c1575083600160a060020a03166144b6846117a1565b600160a060020a0316145b806144d157506144d181856142a7565b949350505050565b6144e1614fb4565b6144ea83614783565b60e08101839052600b805491925082918590811061450457fe5b600091825260209182902083516008909202019081558282015160018201556040808401516002830155606084015160038301556080840151600483015560a0840151600583015560c0840151600683015560e090930151600790910155815185815291516000805160206150d58339815191529281900390910190a1505050565b81600160a060020a031661459982612846565b600160a060020a0316146145ac57600080fd5b600081815260016020526040902054600160a060020a031615611bea5760009081526001602052604090208054600160a060020a031916905550565b60008060006145f78585614da9565b600084815260076020908152604080832054600160a060020a038916845260069092529091205490935061463290600163ffffffff614e3116565b600160a060020a03861660009081526006602052604090208054919350908390811061465a57fe5b90600052602060002001549050806006600087600160a060020a0316600160a060020a031681526020019081526020016000208481548110151561469a57fe5b6000918252602080832090910192909255600160a060020a03871681526006909152604090208054906146d1906000198301615018565b50600093845260076020526040808520859055908452909220555050565b60006146fb8383614e48565b50600160a060020a039091166000908152600660209081526040808320805460018101825590845282842081018590559383526007909152902055565b601154600160a060020a031633148061475b5750601254600160a060020a031633145b151561476657600080fd5b60155460ff16151561477757600080fd5b6015805460ff19169055565b61478b614fb4565b6000600b8381548110151561479c57fe5b9060005260206000209060080201905080610100604051908101604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201548152602001600782015481525050915050919050565b6000600b8381548110151561482357fe5b9060005260206000209060080201905081816005018190555080600b8481548110151561484c57fe5b906000526020600020906008020160008201548160000155600182015481600101556002820154816002015560038201548160030155600482015481600401556005820154816005015560068201548160060155600782015481600701559050506000805160206150d5833981519152836040518082815260200191505060405180910390a1505050565b60006148e282612846565b9050600160a060020a0383811690821614156148fd57600080fd5b80600160a060020a031684600160a060020a03161480614922575061492281856142a7565b151561492d57600080fd5b6000614938836117a1565b600160a060020a03161415806149565750600160a060020a03831615155b15611da3576000828152600160205260408082208054600160a060020a031916600160a060020a0387811691821790925591518593918816917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a450505050565b6000806149cd85600160a060020a0316614eca565b15156149dc5760019150614b1c565b6040517f150b7a020000000000000000000000000000000000000000000000000000000081523360048201818152600160a060020a03898116602485015260448401889052608060648501908152875160848601528751918a169463150b7a0294938c938b938b93909160a490910190602085019080838360005b83811015614a6f578181015183820152602001614a57565b50505050905090810190601f168015614a9c5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015614abe57600080fd5b505af1158015614ad2573d6000803e3d6000fd5b505050506040513d6020811015614ae857600080fd5b5051600160e060020a031981167f150b7a020000000000000000000000000000000000000000000000000000000014925090505b50949350505050565b6000918252600f602052604090912060ff9091169055565b8051611bea90600a90602084019061503c565b6000600b83815481101515614b6157fe5b9060005260206000209060080201905081816003018190555080600b8481548110151561484c57fe5b600080808311614b9957600080fd5b8284811515614ba457fe5b04949350505050565b6000614bb7614fb4565b50604080516101008101825260208681015182526000908201818152878401519383019384526060808901519084019081526080808a015190850190815260a085018481528a5160c0870190815260e087018a8152600b805460018101825597528751600888027f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db981019190915595517f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dba87015597517f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbb86015592517f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbc85015590517f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbd840155517f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbe830155517f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbf82015592517f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dc09093019290925590614d5c8582614ed2565b60408051600160a060020a03871681526020810183905281517f0ce3610e89a4bb9ec9359763f99110ed52a4abaea0b62028a1637e242ca2768b929181900390910190a195945050505050565b81600160a060020a0316614dbc82612846565b600160a060020a031614614dcf57600080fd5b600160a060020a038216600090815260026020526040902054614df990600163ffffffff614e3116565b600160a060020a0390921660009081526002602090815260408083209490945591815290819052208054600160a060020a0319169055565b60008083831115614e4157600080fd5b5050900390565b600081815260208190526040902054600160a060020a031615614e6a57600080fd5b6000818152602081815260408083208054600160a060020a031916600160a060020a03871690811790915583526002909152902054614eaa906001614f21565b600160a060020a0390921660009081526002602052604090209190915550565b6000903b1190565b614edc8282614f3a565b600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3015550565b600082820183811015614f3357600080fd5b9392505050565b600160a060020a0382161515614f4f57600080fd5b614f5982826146ef565b6040518190600160a060020a038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60a0604051908101604052806005906020820280388339509192915050565b6101006040519081016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5080546000825590600052602060002090810190613ffe91906150ba565b815481835581811115613849576000838152602090206138499181019083016150ba565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061507d57805160ff19168380011785556150aa565b828001600101855582156150aa579182015b828111156150aa57825182559160200191906001019061508f565b506150b69291506150ba565b5090565b61166291905b808211156150b657600081556001016150c05600ec666837ce46f92c7ff76499d757ade0ebd48ddade4d6acbccdc17b4257372f3a165627a7a72305820b844c610420cdd36c8a3fb492ba0f595eacb52f350ee6bdad4aae6fb4b0665e00029

   Swarm Source:
bzzr://b844c610420cdd36c8a3fb492ba0f595eacb52f350ee6bdad4aae6fb4b0665e0

 

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.