Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0x18d657832C75A9aC8bC5d15A129d5F23B04f8628
Balance 0 ETH
Nonce 1
Code Size 6938 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

6938 bytes
0x6080604052600436106101745763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166301ffc9a7811461017957806306fdde03146101d6578063081812fc14610260578063095ea7b3146102a65780630fbdbfaa146102e157806318160ddd1461032657806318d877171461033b57806323b872dd146103655780632f745c59146103a85780633112de9a146103e157806333f6832a1461041157806340c10f191461043b57806342842e0e146104745780634f6ccce7146104b75780636352211e146104e1578063685731071461050b57806370a082311461068f57806381422d8a146106c2578063922b8a92146106ec57806395d89b4114610716578063983b2d561461072b578063986502751461075e578063a22cb46514610773578063aa271e1a146107ae578063b38b4509146107e1578063b88d4fde14610891578063e223ccec14610964578063e6c3b1f614610994578063e985e9c5146109be575b600080fd5b34801561018557600080fd5b506101c26004803603602081101561019c57600080fd5b50357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166109f9565b604080519115158252519081900360200190f35b3480156101e257600080fd5b506101eb610a2d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561022557818101518382015260200161020d565b50505050905090810190601f1680156102525780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561026c57600080fd5b5061028a6004803603602081101561028357600080fd5b5035610ac4565b60408051600160a060020a039092168252519081900360200190f35b3480156102b257600080fd5b506102df600480360360408110156102c957600080fd5b50600160a060020a038135169060200135610af6565b005b3480156102ed57600080fd5b506103146004803603602081101561030457600080fd5b5035600160a060020a0316610bac565b60408051918252519081900360200190f35b34801561033257600080fd5b50610314610bbe565b34801561034757600080fd5b506103146004803603602081101561035e57600080fd5b5035610bc4565b34801561037157600080fd5b506102df6004803603606081101561038857600080fd5b50600160a060020a03813581169160208101359091169060400135610bd6565b3480156103b457600080fd5b50610314600480360360408110156103cb57600080fd5b50600160a060020a038135169060200135610bfb565b3480156103ed57600080fd5b506103146004803603604081101561040457600080fd5b5080359060200135610caa565b34801561041d57600080fd5b506103146004803603602081101561043457600080fd5b5035610cd6565b34801561044757600080fd5b506103146004803603604081101561045e57600080fd5b50600160a060020a038135169060200135610cf5565b34801561048057600080fd5b506102df6004803603606081101561049757600080fd5b50600160a060020a03813581169160208101359091169060400135610e9c565b3480156104c357600080fd5b50610314600480360360208110156104da57600080fd5b5035610eb8565b3480156104ed57600080fd5b5061028a6004803603602081101561050457600080fd5b5035610f4f565b34801561051757600080fd5b5061063f6004803603604081101561052e57600080fd5b81019060208101813564010000000081111561054957600080fd5b82018360208201111561055b57600080fd5b8035906020019184602083028401116401000000008311171561057d57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092959493602081019350359150506401000000008111156105cd57600080fd5b8201836020820111156105df57600080fd5b8035906020019184602083028401116401000000008311171561060157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610f79945050505050565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561067b578181015183820152602001610663565b505050509050019250505060405180910390f35b34801561069b57600080fd5b50610314600480360360208110156106b257600080fd5b5035600160a060020a031661101c565b3480156106ce57600080fd5b50610314600480360360208110156106e557600080fd5b5035611054565b3480156106f857600080fd5b506103146004803603602081101561070f57600080fd5b5035611066565b34801561072257600080fd5b506101eb611078565b34801561073757600080fd5b506102df6004803603602081101561074e57600080fd5b5035600160a060020a03166110d9565b34801561076a57600080fd5b506102df61115b565b34801561077f57600080fd5b506102df6004803603604081101561079657600080fd5b50600160a060020a0381351690602001351515611166565b3480156107ba57600080fd5b506101c2600480360360208110156107d157600080fd5b5035600160a060020a03166111ea565b3480156107ed57600080fd5b5061063f6004803603602081101561080457600080fd5b81019060208101813564010000000081111561081f57600080fd5b82018360208201111561083157600080fd5b8035906020019184602083028401116401000000008311171561085357600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506111fd945050505050565b34801561089d57600080fd5b506102df600480360360808110156108b457600080fd5b600160a060020a038235811692602081013590911691604082013591908101906080810160608201356401000000008111156108ef57600080fd5b82018360208201111561090157600080fd5b8035906020019184600183028401116401000000008311171561092357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506112c5945050505050565b34801561097057600080fd5b506103146004803603604081101561098757600080fd5b50803590602001356112ed565b3480156109a057600080fd5b50610314600480360360208110156109b757600080fd5b503561131d565b3480156109ca57600080fd5b506101c2600480360360408110156109e157600080fd5b50600160a060020a038135811691602001351661132f565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660009081526020819052604090205460ff1690565b600a8054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ab95780601f10610a8e57610100808354040283529160200191610ab9565b820191906000526020600020905b815481529060010190602001808311610a9c57829003601f168201915b505050505090505b90565b6000610acf8261135d565b1515610ada57600080fd5b50600090815260026020526040902054600160a060020a031690565b6000610b0182610f4f565b9050600160a060020a038381169082161415610b1c57600080fd5b33600160a060020a0382161480610b385750610b38813361132f565b1515610b4357600080fd5b600082815260026020526040808220805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000610bb78261137a565b5492915050565b60075490565b600c6020526000908152604090205481565b610be03382611394565b1515610beb57600080fd5b610bf68383836113f3565b505050565b6000610c068361101c565b8210610c7357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4f776e657220646f6573206e6f74206f776e0000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0383166000908152600560205260409020805483908110610c9757fe5b9060005260206000200154905092915050565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b6010805482908110610ce457fe5b600091825260209091200154905081565b6000610d00336111ea565b1515610d6d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4f6e6c79206d696e7465722063616e206d696e74000000000000000000000000604482015290519081900360640190fd5b6000828152600d6020908152604080832054600c909252909120548110610df557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f546f6b656e20737570706c79206c696d69742072656163686564000000000000604482015290519081900360640190fd5b610dff8382610caa565b6000848152600d60209081526040808320805460018101825590845282842001849055838352600e8252808320879055600f90915290208290559150610e458483611412565b60408051600160a060020a0386168152602081018590528082018390526060810184905290517f10546b1a6f5245ff0ffa18c256b9e46859c585cbb473b453fcd4c2dc39ae08db9181900360800190a15092915050565b610bf683838360206040519081016040528060008152506112c5565b6000610ec2610bbe565b8210610f2f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e646578206f7574206f662072616e67650000000000000000000000000000604482015290519081900360640190fd5b6007805483908110610f3d57fe5b90600052602060002001549050919050565b600081815260016020526040812054600160a060020a0316801515610f7357600080fd5b92915050565b6060808351604051908082528060200260200182016040528015610fa7578160200160208202803883390190505b50905060005b8451811015611014576000610ff08683815181101515610fc957fe5b906020019060200201518684815181101515610fe157fe5b90602001906020020151610cf5565b905080838381518110151561100157fe5b6020908102909101015250600101610fad565b509392505050565b6000600160a060020a038216151561103357600080fd5b600160a060020a0382166000908152600360205260409020610f7390611433565b6000908152600d602052604090205490565b600f6020526000908152604090205481565b600b8054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ab95780601f10610a8e57610100808354040283529160200191610ab9565b6110e2336111ea565b151561114f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4f6e6c79206d696e7465722063616e206d696e74000000000000000000000000604482015290519081900360640190fd5b61115881611437565b50565b6111643361147f565b565b600160a060020a03821633141561117c57600080fd5b336000818152600460209081526040808320600160a060020a03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b6000610f7360098363ffffffff6114c716565b606080601080549050835102604051908082528060200260200182016040528015611232578160200160208202803883390190505b5090506000805b84518110156112bc5760005b6010548110156112b357600061128b878481518110151561126257fe5b9060200190602002015160108481548110151561127b57fe5b9060005260206000200154610cf5565b905080858581518110151561129c57fe5b602090810290910101525060019283019201611245565b50600101611239565b50909392505050565b6112d0848484610bd6565b6112dc848484846114fe565b15156112e757600080fd5b50505050565b600d6020528160005260406000208181548110151561130857fe5b90600052602060002001600091509150505481565b600e6020526000908152604090205481565b600160a060020a03918216600090815260046020908152604080832093909416825291909152205460ff1690565b600090815260016020526040902054600160a060020a0316151590565b600160a060020a0316600090815260056020526040902090565b6000806113a083610f4f565b905080600160a060020a031684600160a060020a031614806113db575083600160a060020a03166113d084610ac4565b600160a060020a0316145b806113eb57506113eb818561132f565b949350505050565b6113fe83838361167a565b6114088382611769565b610bf68282611860565b61141c828261189e565b6114268282611860565b61142f8161194e565b5050565b5490565b61144860098263ffffffff61199216565b604051600160a060020a038216907f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f690600090a250565b61149060098263ffffffff6119e016565b604051600160a060020a038216907fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669290600090a250565b6000600160a060020a03821615156114de57600080fd5b50600160a060020a03166000908152602091909152604090205460ff1690565b600061151284600160a060020a0316611a2c565b1515611520575060016113eb565b6040517f150b7a020000000000000000000000000000000000000000000000000000000081523360048201818152600160a060020a03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b838110156115b357818101518382015260200161159b565b50505050905090810190601f1680156115e05780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561160257600080fd5b505af1158015611616573d6000803e3d6000fd5b505050506040513d602081101561162c57600080fd5b50517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167f150b7a020000000000000000000000000000000000000000000000000000000014915050949350505050565b82600160a060020a031661168d82610f4f565b600160a060020a0316146116a057600080fd5b600160a060020a03821615156116b557600080fd5b6116be81611a34565b600160a060020a03831660009081526003602052604090206116df90611a7c565b600160a060020a038216600090815260036020526040902061170090611a93565b600081815260016020526040808220805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600160a060020a03821660009081526005602052604081205461179390600163ffffffff611a9c16565b60008381526006602052604090205490915080821461183057600160a060020a03841660009081526005602052604081208054849081106117d057fe5b90600052602060002001549050806005600087600160a060020a0316600160a060020a031681526020019081526020016000208381548110151561181057fe5b600091825260208083209091019290925591825260069052604090208190555b600160a060020a0384166000908152600560205260409020805490611859906000198301611ab1565b5050505050565b600160a060020a0390911660009081526005602081815260408084208054868652600684529185208290559282526001810183559183529091200155565b600160a060020a03821615156118b357600080fd5b6118bc8161135d565b156118c657600080fd5b6000818152600160209081526040808320805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03871690811790915583526003909152902061191290611a93565b6040518190600160a060020a038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600780546000838152600860205260408120829055600182018355919091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880155565b600160a060020a03811615156119a757600080fd5b6119b182826114c7565b156119bb57600080fd5b600160a060020a0316600090815260209190915260409020805460ff19166001179055565b600160a060020a03811615156119f557600080fd5b6119ff82826114c7565b1515611a0a57600080fd5b600160a060020a0316600090815260209190915260409020805460ff19169055565b6000903b1190565b600081815260026020526040902054600160a060020a031615611158576000908152600260205260409020805473ffffffffffffffffffffffffffffffffffffffff19169055565b8054611a8f90600163ffffffff611a9c16565b9055565b80546001019055565b600082821115611aab57600080fd5b50900390565b815481835581811115610bf657600083815260209020610bf6918101908301610ac191905b80821115611aea5760008155600101611ad6565b509056fea165627a7a7230582099264883a0769274349d07970e53155103efd21d30d89798ea42ee1e403c6ffa0029

Verified Source Code Partial Match

Compiler: v0.5.0+commit.1d4f565a EVM: byzantium Optimization: Yes (500 runs)
IERC165.sol 15 lines
pragma solidity >=0.5.0 <0.6.0;

/**
 * @title IERC165
 * @dev https://eips.ethereum.org/EIPS/eip-165
 */
interface IERC165 {
    /**
     * @notice Query if a contract implements an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @dev Interface identification is specified in ERC-165. This function
     * uses less than 30,000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
Roles.sol 40 lines
pragma solidity >=0.5.0 <0.6.0;

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

    /**
     * @dev give an account access to this role
     */
    function add(Role storage role, address account) internal {
        require(account != address(0));
        require(!has(role, account));

        role.bearer[account] = true;
    }

    /**
     * @dev remove an account's access to this role
     */
    function remove(Role storage role, address account) internal {
        require(account != address(0));
        require(has(role, account));

        role.bearer[account] = false;
    }

    /**
     * @dev check if an account has this role
     * @return bool
     */
    function has(Role storage role, address account) internal view returns (bool) {
        require(account != address(0));
        return role.bearer[account];
    }
}
ERC165.sol 44 lines
pragma solidity >=0.5.0 <0.6.0;

import "./IERC165.sol";

/**
 * @title ERC165
 * @author Matt Condon (@shrugs)
 * @dev Implements ERC165 using a lookup table.
 */
contract ERC165 is IERC165 {
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    /*
     * 0x01ffc9a7 ===
     *     bytes4(keccak256('supportsInterface(bytes4)'))
     */

    /**
     * @dev a mapping of interface id to whether or not it's supported
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    /**
     * @dev A contract implementing SupportsInterfaceWithLookup
     * implement ERC165 itself
     */
    constructor () internal {
        _registerInterface(_INTERFACE_ID_ERC165);
    }

    /**
     * @dev implement supportsInterface(bytes4) using a lookup table
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool) {
        return _supportedInterfaces[interfaceId];
    }

    /**
     * @dev internal method for registering an interface
     */
    function _registerInterface(bytes4 interfaceId) internal {
        require(interfaceId != 0xffffffff);
        _supportedInterfaces[interfaceId] = true;
    }
}
ERC721.sol 286 lines
pragma solidity >=0.5.0 <0.6.0;

import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./SafeMath.sol";
import "./Address.sol";
import "./Counters.sol";
import "./ERC165.sol";

/**
 * @title ERC721 Non-Fungible Token Standard basic implementation
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721 is ERC165, IERC721 {
    using SafeMath for uint256;
    using Address for address;
    using Counters for Counters.Counter;

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

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

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

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

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

    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
    /*
     * 0x80ac58cd ===
     *     bytes4(keccak256('balanceOf(address)')) ^
     *     bytes4(keccak256('ownerOf(uint256)')) ^
     *     bytes4(keccak256('approve(address,uint256)')) ^
     *     bytes4(keccak256('getApproved(uint256)')) ^
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) ^
     *     bytes4(keccak256('isApprovedForAll(address,address)')) ^
     *     bytes4(keccak256('transferFrom(address,address,uint256)')) ^
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
     */

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

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

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

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

        _tokenApprovals[tokenId] = to;
        emit Approval(owner, to, tokenId);
    }

    /**
     * @dev Gets the approved address for a token ID, or zero if no address set
     * Reverts if the token ID does not exist.
     * @param tokenId uint256 ID of the token to query the approval of
     * @return address currently approved for the given token ID
     */
    function getApproved(uint256 tokenId) public view returns (address) {
        require(_exists(tokenId));
        return _tokenApprovals[tokenId];
    }

    /**
     * @dev Sets or unsets the approval of a given operator
     * An operator is allowed to transfer all tokens of the sender on their behalf
     * @param to operator address to set the approval
     * @param approved representing the status of the approval to be set
     */
    function setApprovalForAll(address to, bool approved) public {
        require(to != msg.sender);
        _operatorApprovals[msg.sender][to] = approved;
        emit ApprovalForAll(msg.sender, to, approved);
    }

    /**
     * @dev Tells whether an operator is approved by a given owner
     * @param owner owner address which you want to query the approval of
     * @param operator operator address which you want to query the approval of
     * @return bool whether the given operator is approved by the given owner
     */
    function isApprovedForAll(address owner, address operator) public view returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev Transfers the ownership of a given token ID to another address
     * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
     * Requires the msg.sender to be the owner, approved, or operator
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function transferFrom(address from, address to, uint256 tokenId) public {
        require(_isApprovedOrOwner(msg.sender, tokenId));

        _transferFrom(from, to, tokenId);
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the msg.sender to be the owner, approved, or operator
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) public {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the msg.sender to be the owner, approved, or operator
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes data to send along with a safe transfer check
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
        transferFrom(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data));
    }

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

    /**
     * @dev Returns whether the given spender can transfer a given token ID
     * @param spender address of the spender to query
     * @param tokenId uint256 ID of the token to be transferred
     * @return bool whether the msg.sender is approved for the given token ID,
     * is an operator of the owner, or is the owner of the token
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
        address owner = ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }

    /**
     * @dev Internal function to mint a new token
     * Reverts if the given token ID already exists
     * @param to The address that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     */
    function _mint(address to, uint256 tokenId) internal {
        require(to != address(0));
        require(!_exists(tokenId));

        _tokenOwner[tokenId] = to;
        _ownedTokensCount[to].increment();

        emit Transfer(address(0), to, tokenId);
    }

    /**
     * @dev Internal function to burn a specific token
     * Reverts if the token does not exist
     * Deprecated, use _burn(uint256) instead.
     * @param owner owner of the token to burn
     * @param tokenId uint256 ID of the token being burned
     */
    function _burn(address owner, uint256 tokenId) internal {
        require(ownerOf(tokenId) == owner);

        _clearApproval(tokenId);

        _ownedTokensCount[owner].decrement();
        _tokenOwner[tokenId] = address(0);

        emit Transfer(owner, address(0), tokenId);
    }

    /**
     * @dev Internal function to burn a specific token
     * Reverts if the token does not exist
     * @param tokenId uint256 ID of the token being burned
     */
    function _burn(uint256 tokenId) internal {
        _burn(ownerOf(tokenId), tokenId);
    }

    /**
     * @dev Internal function to transfer ownership of a given token ID to another address.
     * As opposed to transferFrom, this imposes no restrictions on msg.sender.
     * @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) internal {
        require(ownerOf(tokenId) == from);
        require(to != address(0));

        _clearApproval(tokenId);

        _ownedTokensCount[from].decrement();
        _ownedTokensCount[to].increment();

        _tokenOwner[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Internal function to invoke `onERC721Received` on a target address
     * The call is not executed if the target address is not a contract
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
        internal returns (bool)
    {
        if (!to.isContract()) {
            return true;
        }

        bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data);
        return (retval == _ERC721_RECEIVED);
    }

    /**
     * @dev Private function to clear current approval of a given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function _clearApproval(uint256 tokenId) private {
        if (_tokenApprovals[tokenId] != address(0)) {
            _tokenApprovals[tokenId] = address(0);
        }
    }
}
Counters.sol 37 lines
pragma solidity >=0.5.0 <0.6.0;

import "./SafeMath.sol";

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids
 *
 * Include with `using Counters for Counters.Counter;`
 * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the SafeMath
 * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
 * directly accessed.
 */
library Counters {
    using SafeMath for uint256;

    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        counter._value += 1;
    }

    function decrement(Counter storage counter) internal {
        counter._value = counter._value.sub(1);
    }
}
XYProducts721.sol 127 lines
pragma solidity >=0.5.0 <0.6.0;
import "./ERC721Enumerable.sol";
import "./MinterRole.sol";


/**
 * @title A 721 Token Contract - A non-fungible token contract
 * @dev Basic version of ERC721Token.
 */
contract XYProducts721 is ERC721Enumerable, MinterRole {
    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from product ID to list of owned token IDs

    event TokenMinted(address beneficiary, uint tokenType, uint index, uint tokenId);

    mapping(uint => uint) public tokenTypeSupply;
    mapping(uint => uint[]) public tokensByType;
    mapping(uint => uint) public tokenType;
    mapping(uint => uint) public tokenIndexInTypeArray;
    uint[] public tokenTypes;

    /**
     * @dev Constructor function
     */
    constructor (
      string memory name,
      string memory symbol,
      uint[] memory types,
      uint[] memory supplies
    )
        public
        ERC721Enumerable()
        MinterRole()
      {
        _name = name;
        _symbol = symbol;
        tokenTypes = types;
        for (uint i = 0; i < types.length; i++) {
          tokenTypeSupply[types[i]] = supplies[i];
        }
    }

    /**
     * @dev Gets the token name
     * @return string representing the token name
     */
    function name() external view returns (string memory) {
        return _name;
    }

    /**
     * @dev Gets the token symbol
     * @return string representing the token symbol
     */
    function symbol() external view returns (string memory) {
        return _symbol;
    }

    function numTokensByOwner(address owner) public view returns (uint) {
      return _tokensOfOwner(owner).length;
    }
    function numTokensByType(uint tType) public view returns (uint) {
      return tokensByType[tType].length;
    }

    function getTokenId(uint tType, uint index) public pure returns (uint) {
      return uint(keccak256(abi.encode(tType, index)));
    }

    function batchMint(
      address[] memory beneficiaries,
      uint[] memory types
    ) public returns (uint[] memory) {
      uint[] memory tokens = new uint[](beneficiaries.length);
      for (uint i = 0; i < beneficiaries.length; i++) {
        uint tokenId = mint(beneficiaries[i], types[i]);
        tokens[i] = tokenId;
      }
      return tokens;
    }

    function batchMintAllTypes(
      address[] memory beneficiaries
    ) public returns (uint[] memory) {
      uint[] memory tokens = new uint[](beneficiaries.length*tokenTypes.length);
      uint index = 0;
      for (uint i = 0; i < beneficiaries.length; i++) {
        for (uint j = 0; j < tokenTypes.length; j++) {
          uint tokenId = mint(beneficiaries[i], tokenTypes[j]);
          tokens[index] = tokenId;
          index++;
        }
      }
      return tokens;
    }

    /*
      Let's at least allow some minting of tokens!
      @param beneficiary - who should receive it
      @param tokenId - the id of the 721 token
    */
    function mint
    (
        address beneficiary,
        uint tType
    )
      public
      onlyMinter()
      returns (uint tokenId)
    {
      uint index = tokensByType[tType].length;
      require (index < tokenTypeSupply[tType], "Token supply limit reached");
      tokenId = getTokenId(tType, index);
      tokensByType[tType].push(tokenId);
      tokenType[tokenId] = tType;
      tokenIndexInTypeArray[tokenId] = index;
      
      _mint(beneficiary, tokenId);
      emit TokenMinted(beneficiary, tType, index, tokenId);
    }
    
}
Address.sol 26 lines
pragma solidity >=0.5.0 <0.6.0;

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

import "./Roles.sol";

contract MinterRole {
    using Roles for Roles.Role;

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

    Roles.Role private _minters;

    constructor () internal {
        _addMinter(msg.sender);
    }

    modifier onlyMinter() {
        require(isMinter(msg.sender), 'Only minter can mint');
        _;
    }

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

    function addMinter(address account) public onlyMinter {
        _addMinter(account);
    }

    function renounceMinter() public {
        _removeMinter(msg.sender);
    }

    function _addMinter(address account) internal {
        _minters.add(account);
        emit MinterAdded(account);
    }

    function _removeMinter(address account) internal {
        _minters.remove(account);
        emit MinterRemoved(account);
    }
}
ERC721Enumerable.sol 198 lines
pragma solidity >=0.5.0 <0.6.0;

import "./IERC721Enumerable.sol";
import "./ERC721.sol";
import "./ERC165.sol";

/**
 * @title ERC-721 Non-Fungible Token with optional enumeration extension logic
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => uint256[]) private _ownedTokens;

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

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

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

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

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

    /**
     * @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), 'Owner does not own');
        return _ownedTokens[owner][index];
    }

    /**
     * @dev Gets the total amount of tokens stored by the contract
     * @return uint256 representing the total amount of tokens
     */
    function totalSupply() public view returns (uint256) {
        return _allTokens.length;
    }

    /**
     * @dev Gets the token ID at a given index of all the tokens in this contract
     * Reverts if the index is greater or equal to the total number of tokens
     * @param index uint256 representing the index to be accessed of the tokens list
     * @return uint256 token ID at the given index of the tokens list
     */
    function tokenByIndex(uint256 index) public view returns (uint256) {
        require(index < totalSupply(), 'Index out of range');
        return _allTokens[index];
    }

    /**
     * @dev Internal function to transfer ownership of a given token ID to another address.
     * As opposed to transferFrom, this imposes no restrictions on msg.sender.
     * @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) internal {
        super._transferFrom(from, to, tokenId);

        _removeTokenFromOwnerEnumeration(from, tokenId);

        _addTokenToOwnerEnumeration(to, tokenId);
    }

    /**
     * @dev Internal function to mint a new token
     * Reverts if the given token ID already exists
     * @param to address the beneficiary that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     */
    function _mint(address to, uint256 tokenId) internal {
        super._mint(to, tokenId);

        _addTokenToOwnerEnumeration(to, tokenId);

        _addTokenToAllTokensEnumeration(tokenId);
    }

    /**
     * @dev Internal function to burn a specific token
     * Reverts if the token does not exist
     * Deprecated, use _burn(uint256) instead
     * @param owner owner of the token to burn
     * @param tokenId uint256 ID of the token being burned
     */
    function _burn(address owner, uint256 tokenId) internal {
        super._burn(owner, tokenId);

        _removeTokenFromOwnerEnumeration(owner, tokenId);
        // Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund
        _ownedTokensIndex[tokenId] = 0;

        _removeTokenFromAllTokensEnumeration(tokenId);
    }

    /**
     * @dev Gets the list of token IDs of the requested owner
     * @param owner address owning the tokens
     * @return uint256[] List of token IDs owned by the requested address
     */
    function _tokensOfOwner(address owner) internal view returns (uint256[] storage) {
        return _ownedTokens[owner];
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @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 _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        _ownedTokensIndex[tokenId] = _ownedTokens[to].length;
        _ownedTokens[to].push(tokenId);
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the _ownedTokensIndex mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @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 _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _ownedTokens[from].length.sub(1);
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

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

        // Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occupied by
        // lastTokenId, or just over the end of the array if the token was the last one).
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length.sub(1);
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        _allTokens.length--;
        _allTokensIndex[tokenId] = 0;
    }
}
IERC721.sol 27 lines
pragma solidity >=0.5.0 <0.6.0;

import "./IERC165.sol";

/**
 * @title ERC721 Non-Fungible Token Standard basic interface
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
contract IERC721 is IERC165 {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    function balanceOf(address owner) public view returns (uint256 balance);
    function ownerOf(uint256 tokenId) public view returns (address owner);

    function approve(address to, uint256 tokenId) public;
    function getApproved(uint256 tokenId) public view returns (address operator);

    function setApprovalForAll(address operator, bool _approved) public;
    function isApprovedForAll(address owner, address operator) public view returns (bool);

    function transferFrom(address from, address to, uint256 tokenId) public;
    function safeTransferFrom(address from, address to, uint256 tokenId) public;

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
}
IERC721Enumerable.sol 14 lines
pragma solidity >=0.5.0 <0.6.0;

import "./IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
contract IERC721Enumerable is IERC721 {
    function totalSupply() public view returns (uint256);
    function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256 tokenId);

    function tokenByIndex(uint256 index) public view returns (uint256);
}
IERC721Receiver.sol 25 lines
pragma solidity >=0.5.0 <0.6.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
contract IERC721Receiver {
    /**
     * @notice Handle the receipt of an NFT
     * @dev The ERC721 smart contract calls this function on the recipient
     * after a `safeTransfer`. This function MUST return the function selector,
     * otherwise the caller will revert the transaction. The selector to be
     * returned can be obtained as `this.onERC721Received.selector`. This
     * function MAY throw to revert and reject the transfer.
     * Note: the ERC721 contract address is always the message sender.
     * @param operator The address which called `safeTransferFrom` function
     * @param from The address which previously owned the token
     * @param tokenId The NFT identifier which is being transferred
     * @param data Additional data with no specified format
     * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
    public returns (bytes4);
}
Migrations.sol 23 lines
pragma solidity >=0.5.0 <0.6.0;

contract Migrations {
  address public owner;
  uint public last_completed_migration;

  constructor() public {
    owner = msg.sender;
  }

  modifier restricted() {
    if (msg.sender == owner) _;
  }

  function setCompleted(uint completed) public restricted {
    last_completed_migration = completed;
  }

  function upgrade(address new_address) public restricted {
    Migrations upgraded = Migrations(new_address);
    upgraded.setCompleted(last_completed_migration);
  }
}
SafeMath.sol 65 lines
pragma solidity >=0.5.0 <0.6.0;

/**
 * @title SafeMath
 * @dev Unsigned math operations with safety checks that revert on error
 */
library SafeMath {
    /**
     * @dev Multiplies two unsigned integers, 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 unsigned integers truncating the quotient, reverts on division by zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 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 unsigned integers, 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 unsigned integers, reverts on overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);

        return c;
    }

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

Read Contract

balanceOf 0x70a08231 → uint256
getApproved 0x081812fc → address
getTokenId 0x3112de9a → uint256
isApprovedForAll 0xe985e9c5 → bool
isMinter 0xaa271e1a → bool
name 0x06fdde03 → string
numTokensByOwner 0x0fbdbfaa → uint256
numTokensByType 0x81422d8a → uint256
ownerOf 0x6352211e → address
supportsInterface 0x01ffc9a7 → bool
symbol 0x95d89b41 → string
tokenByIndex 0x4f6ccce7 → uint256
tokenIndexInTypeArray 0x922b8a92 → uint256
tokenOfOwnerByIndex 0x2f745c59 → uint256
tokenType 0xe6c3b1f6 → uint256
tokenTypeSupply 0x18d87717 → uint256
tokenTypes 0x33f6832a → uint256
tokensByType 0xe223ccec → uint256
totalSupply 0x18160ddd → uint256

Write Contract 10 functions

These functions modify contract state and require a wallet transaction to execute.

addMinter 0x983b2d56
address account
approve 0x095ea7b3
address to
uint256 tokenId
batchMint 0x68573107
address[] beneficiaries
uint256[] types
returns: uint256[]
batchMintAllTypes 0xb38b4509
address[] beneficiaries
returns: uint256[]
mint 0x40c10f19
address beneficiary
uint256 tType
returns: uint256
renounceMinter 0x98650275
No parameters
safeTransferFrom 0x42842e0e
address from
address to
uint256 tokenId
safeTransferFrom 0xb88d4fde
address from
address to
uint256 tokenId
bytes _data
setApprovalForAll 0xa22cb465
address to
bool approved
transferFrom 0x23b872dd
address from
address to
uint256 tokenId

Recent Transactions

No transactions found for this address