Address Contract Partially Verified
Address
0x18d657832C75A9aC8bC5d15A129d5F23B04f8628
Balance
0 ETH
Nonce
1
Code Size
6938 bytes
Creator
0x6792B02f...f930 at tx 0x35697900...134a8e
Indexed Transactions
0
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