Contract Address Details
contract
token
0x906d56D114Ef1bb430a1c450dC6b24dF22D3E759
- Token
- ArtiNFTic (ArtiNFTic)
- Creator
- 0x6a76d7–e86abd at 0x5ffb7f–4646e8
- Balance
- 0 xDAI ( )
- Tokens
-
Fetching tokens...
- Transactions
- 144 Transactions
- Transfers
- 1 Transfers
- Gas Used
- 21,807,455
- Last Balance Update
- 23689402
Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
- Contract name:
- ERC721Matcha
- Optimization enabled
- true
- Compiler version
- v0.5.17+commit.d19bba13
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2021-05-28T16:01:35.228552Z
Constructor Arguments
000000000000000000000000f4c7acf01926113817ad251947753a12201f703b000000000000000000000000f4c7acf01926113817ad251947753a12201f703b000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000009417274694e4654696300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009417274694e465469630000000000000000000000000000000000000000000000
Arg [0] (address) : 0xf4c7acf01926113817ad251947753a12201f703b
Arg [1] (address) : 0xf4c7acf01926113817ad251947753a12201f703b
Arg [2] (uint256) : 2
Arg [3] (string) : ArtiNFTic
Arg [4] (string) : ArtiNFTic
Arg [5] (bool) : true
Contract source code
/** MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWWWWWWWWWWWWWMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMWWNXXKKKKKKKXXXXKKKKKKXXNWWMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMWNXKKKKXXNWWWWMMWWWWMWWWWNXXXKKKXNWMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMWNXKKKXNWMMMMMMMMMNOdxKWMMMMMMMMWNXKKKXNWMMMMMMMMMMMMMM MMMMMMMMMMMMMWXKKKNWMMMMMMMMMMMMNx:;;l0WMMMMMMMMMMMWNK0KXWMMMMMMMMMMMM MMMMMMMMMMMWXKKXWMMMMMMMMMMMMMMXd:;;;;cOWMMMMMMMMMMMMMWXKKXWMMMMMMMMMM MMMMMMMMMWNKKXWMMMMMMMMMMMMMMWKo;;col:;:kNMMMMMMMMMMMMMMWX0KNWMMMMMMMM MMMMMMMMWX0XWMMMMMMMMMMMMMMMWOl;;oKWXkc;:dXMMMMMMMMMMMMMMMWX0XWMMMMMMM MMMMMMMNKKNWMMMMMMMMMMMMMMMNkc;:dXMMMWOc;;oKWMMMMMMMMMMMMMMWNKKNMMMMMM MMMMMMNKKNMMMMMMMMMMMMMMMMNx:;:xNMMMMMW0l;;l0WMMMMMMMWMMMMMMMNKKNMMMMM MMMMMNKKNMMMMMMMMMMMMMMMMXd:;ckNMMMMMMMMKo:;cOWMMMMXkxkXWMMMMMNKKNMMMM MMMMWK0NMMMMMMMMMMMMMMMWKo;;l0WMMMMMMMMMMXx:;:xNMMW0lccxXMMMMMMN0KWMMM MMMMX0XWMMMMMMWWMMMMMMWOl;;oKWMMMMMMMMMMMMNkc;:dXMMNklcoKMMMMMMMX0XMMM MMMWKKNMMWK0OkkkkkkKWNkc;:dXMMMMMMMMMMMMMMMWOl;;oKWMXdcxNMMMMMMMNKKWMM MMMN0XWMMWNXX0OdlccdKOc;:xNMMMWXKKXNWNNNNWWMW0o;;l0WNkdKWMMMMMMMWX0NMM MMMX0XMMMMMMMMMN0dlcdOxoONMMMMW0xdddddodxk0KNWXd:;l0Kx0WMMMMMMMMMX0XMM MMMX0NMMMMMMMMMMWXxlcoOXWMMMMWKkolclodkKNNNNWWMNxcxOkKWMMMMMMMMMMX0XMM MMMX0XMMMMMMMMMMMMNklclkNMMWXklccodxdodKWMMMMMMMNKOkKWMMMMMMMMMMMX0XMM MMMN0XWMMMMMMMMMMMMNOoclxXN0occcdKX0xlco0WMMMMMMNOOXMMMMMMMMMMMMMX0NMM MMMWKKWMMMMMMMMMMMMMW0dccoxocccdKWMWNklclONMMMMXOONMMMMMMMMMMMMMWKKWMM MMMMX0XMMMMMMMMMMMMMMWKdcccccco0WMMMMNOoclkNWWKk0NMMMMMMMMMMMMMMX0XWMM MMMMWKKNMMMMMMMMMMMMMMMXxlcccckNMMMMMMW0oclxK0kKWMMMMMMMMMMMMMMNKKWMMM MMMMMN0KWMMMMMMMMMMMMMMMNklccoKWMMMMMMMWKdlcoxKWMMMMMMMMMMMMMMWK0NMMMM MMMMMMN0KWMMMMMMMMMMMMMMMNOod0KXWMMMMMMNK0xoxXWMMMMMMMMMMMMMMWK0NMMMMM MMMMMMMN0KNMMMMMMMMMMMMMMMWXKkll0WMMMMXdcoOKNMMMMMMMMMMMMMMMNK0NMMMMMM MMMMMMMMNK0XWMMMMMMMMMMMMMMMNd:;cOWMWKo:;c0WMMMMMMMMMMMMMMWX0KNMMMMMMM MMMMMMMMMWXKKNWMMMMMMMMMMMMMMXd:;cx0kl;;l0WMMMMMMMMMMMMMWNKKXWMMMMMMMM MMMMMMMMMMMWX0KNWMMMMMMMMMMMMMNkc;;::;:oKWMMMMMMMMMMMMWNK0XWMMMMMMMMMM MMMMMMMMMMMMMNXKKXNWMMMMMMMMMMMWOc;;;:dXMMMMMMMMMMMWNXKKXWMMMMMMMMMMMM MMMMMMMMMMMMMMMWNKKKXNWMMMMMMMMMW0l:ckNMMMMMMMMMWNXKKKNWMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMWNXKKKXXNWWWMMMMX0KWMMMWWWNXXKKKXNWMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMWWNXXKKKKKXXXXXXXXXXKKKKXXNWWMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMWWNNNNNNNNNNNNWWWMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ---------------------- [ WPSmartContracts.com ] ---------------------- [ Blockchain Made Easy ] | | ERC-721 NFT Marketplace | |---------------------------- | | Flavors | | > Matcha: Fully featured ERC-721 Token, with Buy, | Sell and Auction NFT Marketplace | */ pragma solidity ^0.5.7; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } /** * @dev Required interface of an ERC721 compliant contract. */ 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 ); /** * @dev Returns the number of NFTs in `owner`'s account. */ function balanceOf(address owner) public view returns (uint256 balance); /** * @dev Returns the owner of the NFT specified by `tokenId`. */ function ownerOf(uint256 tokenId) public view returns (address owner); /** * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to * another (`to`). * * * * Requirements: * - `from`, `to` cannot be zero. * - `tokenId` must be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this * NFT by either {approve} or {setApproveForAll}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public; /** * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to * another (`to`). * * Requirements: * - If the caller is not `from`, it must be approved to move this NFT by * either {approve} or {setApproveForAll}. */ function transferFrom( address from, address to, uint256 tokenId ) public; 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 safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public; } /** * @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 {IERC721-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); } /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot 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, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, "SafeMath: division by zero"); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, "SafeMath: modulo by zero"); return a % b; } } /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * This test is non-exhaustive, and there may be false-negatives: during the * execution of a contract's constructor, its address will be reported as * not containing a contract. * * IMPORTANT: It is unsafe to assume that an address for which this * function returns false is an externally-owned account (EOA) and not a * contract. */ function isContract(address account) internal view returns (bool) { // This method relies in extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != 0x0 && codehash != accountHash); } /** * @dev Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. */ function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } } /** * @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); } } /** * @dev Implementation of the {IERC165} interface. * * Contracts may inherit from this and call {_registerInterface} to declare * their support of an interface. */ contract ERC165 is IERC165 { /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Mapping of interface ids to whether or not it's supported. */ mapping(bytes4 => bool) private _supportedInterfaces; constructor() internal { // Derived contracts need only register support for their own interfaces, // we register support for ERC165 itself here _registerInterface(_INTERFACE_ID_ERC165); } /** * @dev See {IERC165-supportsInterface}. * * Time complexity O(1), guaranteed to always use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev Registers the contract as an implementer of the interface defined by * `interfaceId`. Support of the actual ERC165 interface is automatic and * registering its interface id is not required. * * See {IERC165-supportsInterface}. * * Requirements: * * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). */ function _registerInterface(bytes4 interfaceId) internal { require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); _supportedInterfaces[interfaceId] = true; } } /** * @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(keccak256('balanceOf(address)')) == 0x70a08231 * bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e * bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3 * bytes4(keccak256('getApproved(uint256)')) == 0x081812fc * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 * bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde * * => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^ * 0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd */ bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; 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), "ERC721: balance query for the zero address" ); 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), "ERC721: owner query for nonexistent token" ); 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, "ERC721: approval to current owner"); require( msg.sender == owner || isApprovedForAll(owner, msg.sender), "ERC721: approve caller is not owner nor approved for all" ); _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), "ERC721: approved query for nonexistent token" ); 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, "ERC721: approve to caller"); _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 { //solhint-disable-next-line max-line-length require( _isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved" ); _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 {IERC721Receiver-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 {IERC721Receiver-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), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @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) { require( _exists(tokenId), "ERC721: operator query for nonexistent token" ); 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), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _tokenOwner[tokenId] = to; _ownedTokensCount[to].increment(); emit Transfer(address(0), to, 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, "ERC721: transfer of token that is not own" ); require(to != address(0), "ERC721: transfer to the zero address"); _clearApproval(tokenId); _ownedTokensCount[from].decrement(); _ownedTokensCount[to].increment(); _tokenOwner[tokenId] = to; emit Transfer(from, to, tokenId); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * This function is deprecated. * @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); } } } /** * @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(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); 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), "Roles: account is the zero address"); return role.bearer[account]; } } 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), "MinterRole: caller does not have the Minter role" ); _; } 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); } } /** * @title ERC721Mintable * @dev ERC721 minting logic. */ contract ERC721Mintable is ERC721, MinterRole { bool public anyoneCanMint; /** * @dev Options to activate or deactivate mint ability */ function _setMintableOption(bool _anyoneCanMint) internal { anyoneCanMint = _anyoneCanMint; } /** * @dev Function to mint tokens. * @param to The address that will receive the minted tokens. * @param tokenId The token id to mint. * @return A boolean that indicates if the operation was successful. */ function mint(address to, uint256 tokenId) public onlyMinter returns (bool) { _mint(to, tokenId); return true; } function canIMint() public view returns (bool) { return anyoneCanMint || isMinter(msg.sender); } /** * Open modifier to anyone can mint possibility */ modifier onlyMinter() { string memory mensaje; require( canIMint(), "MinterRole: caller does not have the Minter role" ); _; } } /** * @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); } /** * @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(keccak256('totalSupply()')) == 0x18160ddd * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59 * bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7 * * => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63 */ bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; /** * @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), "ERC721Enumerable: owner index out of bounds"); 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(), "ERC721Enumerable: global index out of bounds"); 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 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). } } /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ contract IERC721Metadata is IERC721 { function name() external view returns (string memory); function symbol() external view returns (string memory); function tokenURI(uint256 tokenId) external view returns (string memory); } contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { // Token name string private _name; // Token symbol string private _symbol; // Optional mapping for token URIs mapping(uint256 => string) private _tokenURIs; /* * bytes4(keccak256('name()')) == 0x06fdde03 * bytes4(keccak256('symbol()')) == 0x95d89b41 * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd * * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f */ bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f; /** * @dev Constructor function */ constructor (string memory name, string memory symbol) public { _name = name; _symbol = symbol; // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(_INTERFACE_ID_ERC721_METADATA); } /** * @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; } /** * @dev Returns an URI for a given token ID. * Throws if the token ID does not exist. May return an empty string. * @param tokenId uint256 ID of the token to query */ function tokenURI(uint256 tokenId) external view returns (string memory) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); return _tokenURIs[tokenId]; } /** * @dev Internal function to set the token URI for a given token. * Reverts if the token ID does not exist. * @param tokenId uint256 ID of the token to set its URI * @param uri string URI to assign */ function _setTokenURI(uint256 tokenId, string memory uri) internal { require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token"); _tokenURIs[tokenId] = uri; } } /** * @title ERC721MetadataMintable * @dev ERC721 minting logic with metadata. */ contract ERC721MetadataMintable is ERC721, ERC721Metadata, MinterRole { /** * @dev Function to mint tokens. * @param to The address that will receive the minted tokens. * @param tokenId The token id to mint. * @param tokenURI The token URI of the minted token. * @return A boolean that indicates if the operation was successful. */ function mintWithTokenURI(address to, uint256 tokenId, string memory tokenURI) public onlyMinter returns (bool) { _mint(to, tokenId); _setTokenURI(tokenId, tokenURI); return true; } } /** * @title ERC721 * Full ERC-721 Token with automint function */ contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata, ERC721Mintable, ERC721MetadataMintable { uint256 autoTokenId; constructor (string memory name, string memory symbol, bool _anyoneCanMint) public ERC721Mintable() ERC721Metadata(name, symbol) { // solhint-disable-previous-line no-empty-blocks _setMintableOption(_anyoneCanMint); } function exists(uint256 tokenId) public view returns (bool) { return _exists(tokenId); } function tokensOfOwner(address owner) public view returns (uint256[] memory) { return _tokensOfOwner(owner); } function setTokenURI(uint256 tokenId, string memory uri) public { _setTokenURI(tokenId, uri); } /** * @dev Function to mint tokens with automatic ID * @param to The address that will receive the minted tokens. * @return A boolean that indicates if the operation was successful. */ function autoMint(string memory tokenURI, address to) public onlyMinter returns (bool) { do { autoTokenId++; } while(_exists(autoTokenId)); _mint(to, autoTokenId); _setTokenURI(autoTokenId, tokenURI); return true; } /** * @dev Function to transfer tokens * @param to The address that will receive the minted tokens. * @param tokenId the token ID */ function transfer( address to, uint256 tokenId ) public { _transferFrom(msg.sender, to, tokenId); } } /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be aplied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. */ contract ReentrancyGuard { // counter to allow mutex lock with only one SSTORE operation uint256 private _guardCounter; constructor () internal { // The counter starts at one to prevent changing it from zero to a non-zero // value, which is a more expensive operation. _guardCounter = 1; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { _guardCounter += 1; uint256 localCounter = _guardCounter; _; require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call"); } } /** * @title ERC721Matcha * ERC-721 Marketplace */ contract ERC721Matcha is ERC721Full, ReentrancyGuard { using SafeMath for uint256; using Address for address payable; // admin address, the owner of the marketplace address payable admin; address public contract_owner; // commission rate is a value from 0 to 100 uint256 commissionRate; // last price sold or auctioned mapping(uint256 => uint256) public soldFor; // Mapping from token ID to sell price in Ether or to bid price, depending if it is an auction or not mapping(uint256 => uint256) public sellBidPrice; // Mapping payment address for tokenId mapping(uint256 => address payable) private _wallets; event Sale(uint256 indexed tokenId, address indexed from, address indexed to, uint256 value); event Commission(uint256 indexed tokenId, address indexed to, uint256 value, uint256 rate, uint256 total); /* index _isAuction _sellBidPrice Meaning 0 true 0 Item 0 is on auction and no bids so far 1 true 10 Item 1 is on auction and the last bid is for 10 Ethers 2 false 0 Item 2 is not on auction nor for sell 3 false 10 Item 3 is on sale for 10 Ethers */ // Auction data struct Auction { // Parameters of the auction. Times are either // absolute unix timestamps (seconds since 1970-01-01) // or time periods in seconds. address payable beneficiary; uint auctionEnd; // Current state of the auction. address payable highestBidder; uint highestBid; // Set to true at the end, disallows any change bool open; // minimum reserve price in wei uint256 reserve; } // mapping auctions for each tokenId mapping(uint256 => Auction) public auctions; // Events that will be fired on changes. event Refund(address bidder, uint amount); event HighestBidIncreased(address indexed bidder, uint amount, uint256 tokenId); event AuctionEnded(address winner, uint amount); event LimitSell(address indexed from, address indexed to, uint256 amount); event LimitBuy(address indexed from, address indexed to, uint256 amount); event MarketSell(address indexed from, address indexed to, uint256 amount); event MarketBuy(address indexed from, address indexed to, uint256 amount); constructor(address _owner, address payable _admin, uint256 _commissionRate, string memory name, string memory symbol, bool _anyoneCanMint) public ERC721Full(name, symbol, _anyoneCanMint) { admin = _admin; contract_owner = _owner; require(_commissionRate<=100, "ERC721Matcha: Commission rate has to be between 0 and 100"); commissionRate = _commissionRate; } function canSell(uint256 tokenId) public view returns (bool) { return (ownerOf(tokenId)==msg.sender && !auctions[tokenId].open); } // Sell option for a fixed price function sell(uint256 tokenId, uint256 price, address payable wallet) public { // onlyOwner require(ownerOf(tokenId)==msg.sender, "ERC721Matcha: Only owner can sell this item"); // cannot set a price if auction is activated require(!auctions[tokenId].open, "ERC721Matcha: Cannot sell an item which has an active auction"); // set sell price for index sellBidPrice[tokenId] = price; // If price is zero, means not for sale if (price>0) { // approve the Index to the current contract approve(address(this), tokenId); // set wallet payment _wallets[tokenId] = wallet; } } // simple function to return the price of a tokenId // returns: sell price, bid price, sold price, only one can be non zero function getPrice(uint256 tokenId) public view returns (uint256, uint256, uint256) { if (sellBidPrice[tokenId]>0) return (sellBidPrice[tokenId], 0, 0); if (auctions[tokenId].highestBid>0) return (0, auctions[tokenId].highestBid, 0); return (0, 0, soldFor[tokenId]); } function canBuy(uint256 tokenId) public view returns (uint256) { if (!auctions[tokenId].open && sellBidPrice[tokenId]>0 && sellBidPrice[tokenId]>0 && getApproved(tokenId) == address(this)) { return sellBidPrice[tokenId]; } else { return 0; } } // Buy option function buy(uint256 tokenId) public payable nonReentrant { // is on sale require(!auctions[tokenId].open && sellBidPrice[tokenId]>0, "ERC721Matcha: The collectible is not for sale"); // transfer funds require(msg.value >= sellBidPrice[tokenId], "ERC721Matcha: Not enough funds"); // transfer ownership address owner = ownerOf(tokenId); require(msg.sender!=owner, "ERC721Matcha: The seller cannot buy his own collectible"); // we need to call a transferFrom from this contract, which is the one with permission to sell the NFT callOptionalReturn(this, abi.encodeWithSelector(this.transferFrom.selector, owner, msg.sender, tokenId)); // calculate amounts uint256 amount4admin = msg.value.mul(commissionRate).div(100); uint256 amount4owner = msg.value.sub(amount4admin); // to owner (bool success, ) = _wallets[tokenId].call.value(amount4owner)(""); require(success, "Transfer failed."); // to admin (bool success2, ) = admin.call.value(amount4admin)(""); require(success2, "Transfer failed."); // close the sell sellBidPrice[tokenId] = 0; _wallets[tokenId] = address(0); soldFor[tokenId] = msg.value; emit Sale(tokenId, owner, msg.sender, msg.value); emit Commission(tokenId, owner, msg.value, commissionRate, amount4admin); } function canAuction(uint256 tokenId) public view returns (bool) { return (ownerOf(tokenId)==msg.sender && !auctions[tokenId].open && sellBidPrice[tokenId]==0); } // Instantiate an auction contract for a tokenId function createAuction(uint256 tokenId, uint _closingTime, address payable _beneficiary, uint256 _reservePrice) public { require(sellBidPrice[tokenId]==0, "ERC721Matcha: The selected NFT is open for sale, cannot be auctioned"); require(!auctions[tokenId].open, "ERC721Matcha: The selected NFT already has an auction"); require(ownerOf(tokenId)==msg.sender, "ERC721Matcha: Only owner can auction this item"); auctions[tokenId].beneficiary = _beneficiary; auctions[tokenId].auctionEnd = _closingTime; auctions[tokenId].reserve = _reservePrice; auctions[tokenId].open = true; // approve the Index to the current contract approve(address(this), tokenId); } function canBid(uint256 tokenId) public view returns (bool) { if (!msg.sender.isContract() && auctions[tokenId].open && now <= auctions[tokenId].auctionEnd && msg.sender != ownerOf(tokenId) && getApproved(tokenId) == address(this) ) { return true; } else { return false; } } /// Bid on the auction with the value sent /// together with this transaction. /// The value will only be refunded if the /// auction is not won. function bid(uint256 tokenId) public payable nonReentrant { // No arguments are necessary, all // information is already part of // the transaction. The keyword payable // is required for the function to // be able to receive Ether. // Contracts cannot bid, because they can block the auction with a reentrant attack require(!msg.sender.isContract(), "No script kiddies"); // auction has to be opened require(auctions[tokenId].open, "No opened auction found"); // approve was lost require(getApproved(tokenId) == address(this), "Cannot complete the auction"); // Revert the call if the bidding // period is over. require( now <= auctions[tokenId].auctionEnd, "Auction already ended." ); // If the bid is not higher, send the // money back. require( msg.value > auctions[tokenId].highestBid, "There already is a higher bid." ); address owner = ownerOf(tokenId); require(msg.sender!=owner, "ERC721Matcha: The owner cannot bid his own collectible"); // return the funds to the previous bidder, if there is one if (auctions[tokenId].highestBid>0) { (bool success, ) = auctions[tokenId].highestBidder.call.value(auctions[tokenId].highestBid)(""); require(success, "Transfer failed."); emit Refund(auctions[tokenId].highestBidder, auctions[tokenId].highestBid); } // now store the bid data auctions[tokenId].highestBidder = msg.sender; auctions[tokenId].highestBid = msg.value; emit HighestBidIncreased(msg.sender, msg.value, tokenId); } // anyone can execute withdraw if auction is opened and // the bid time expired and the reserve was not met // or // the auction is openen but the contract is unable to transfer function canWithdraw(uint256 tokenId) public view returns (bool) { if (auctions[tokenId].open && ( ( now >= auctions[tokenId].auctionEnd && auctions[tokenId].highestBid<auctions[tokenId].reserve ) || getApproved(tokenId) != address(this) ) ) { return true; } else { return false; } } /// Withdraw a bid when the auction is not finalized function withdraw(uint256 tokenId) public nonReentrant returns (bool) { require(canWithdraw(tokenId), "Conditions to withdraw are not met"); // transfer funds to highest bidder always if (auctions[tokenId].highestBid > 0) { (bool success, ) = auctions[tokenId].highestBidder.call.value(auctions[tokenId].highestBid)(""); require(success, "Transfer failed."); } // finalize the auction delete auctions[tokenId]; } function canFinalize(uint256 tokenId) public view returns (bool) { if (auctions[tokenId].open && now >= auctions[tokenId].auctionEnd && auctions[tokenId].highestBid>=auctions[tokenId].reserve ) { return true; } else { return false; } } // implement the auctionFinalize including the NFT transfer logic function auctionFinalize(uint256 tokenId) public nonReentrant { require(auctions[tokenId].open, "ERC721Matcha: There is no auction opened for this tokenId"); require(now >= auctions[tokenId].auctionEnd, "Auction not yet ended."); require(auctions[tokenId].highestBid>=auctions[tokenId].reserve, "Auction has not reached its minimum reserve price."); // transfer the ownership of token to the highest bidder address payable highestBidder = auctions[tokenId].highestBidder; // calculate payment amounts uint256 amount4admin = auctions[tokenId].highestBid.mul(commissionRate).div(100); uint256 amount4owner = auctions[tokenId].highestBid.sub(amount4admin); // to owner (bool success, ) = auctions[tokenId].beneficiary.call.value(amount4owner)(""); require(success, "Transfer failed."); // to admin (bool success2, ) = admin.call.value(amount4admin)(""); require(success2, "Transfer failed."); emit Sale(tokenId, auctions[tokenId].beneficiary, highestBidder, auctions[tokenId].highestBid); emit Commission(tokenId, auctions[tokenId].beneficiary, auctions[tokenId].highestBid, commissionRate, amount4admin); emit AuctionEnded(auctions[tokenId].highestBidder, auctions[tokenId].highestBid); // transfer ownership address owner = ownerOf(tokenId); // we need to call a transferFrom from this contract, which is the one with permission to sell the NFT // transfer the NFT to the auction's highest bidder callOptionalReturn(this, abi.encodeWithSelector(this.transferFrom.selector, owner, highestBidder, tokenId)); soldFor[tokenId] = auctions[tokenId].highestBid; // finalize the auction delete auctions[tokenId]; } // Bid query functions function highestBidder(uint256 tokenId) public view returns (address payable) { return auctions[tokenId].highestBidder; } function highestBid(uint256 tokenId) public view returns (uint256) { return auctions[tokenId].highestBid; } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function callOptionalReturn(IERC721 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC721: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC721: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC721: ERC20 operation did not succeed"); } } // update contract fields function updateAdmin(address payable _admin, uint256 _commissionRate, bool _anyoneCanMint) public { require(msg.sender==contract_owner, "Only contract owner can do this"); admin=_admin; commissionRate=_commissionRate; anyoneCanMint=_anyoneCanMint; } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","payable":false,"inputs":[{"type":"address","name":"_owner","internalType":"address"},{"type":"address","name":"_admin","internalType":"address payable"},{"type":"uint256","name":"_commissionRate","internalType":"uint256"},{"type":"string","name":"name","internalType":"string"},{"type":"string","name":"symbol","internalType":"string"},{"type":"bool","name":"_anyoneCanMint","internalType":"bool"}]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"approved","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"ApprovalForAll","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"operator","internalType":"address","indexed":true},{"type":"bool","name":"approved","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"AuctionEnded","inputs":[{"type":"address","name":"winner","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Commission","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"uint256","name":"rate","internalType":"uint256","indexed":false},{"type":"uint256","name":"total","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"HighestBidIncreased","inputs":[{"type":"address","name":"bidder","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"LimitBuy","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"LimitSell","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"MarketBuy","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"MarketSell","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"MinterAdded","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"MinterRemoved","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Refund","inputs":[{"type":"address","name":"bidder","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Sale","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"addMinter","inputs":[{"type":"address","name":"account","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"anyoneCanMint","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"approve","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"auctionFinalize","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"beneficiary","internalType":"address payable"},{"type":"uint256","name":"auctionEnd","internalType":"uint256"},{"type":"address","name":"highestBidder","internalType":"address payable"},{"type":"uint256","name":"highestBid","internalType":"uint256"},{"type":"bool","name":"open","internalType":"bool"},{"type":"uint256","name":"reserve","internalType":"uint256"}],"name":"auctions","inputs":[{"type":"uint256","name":"","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"autoMint","inputs":[{"type":"string","name":"tokenURI","internalType":"string"},{"type":"address","name":"to","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"owner","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[],"name":"bid","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"payable","payable":true,"outputs":[],"name":"buy","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"canAuction","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"canBid","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"canBuy","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"canFinalize","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"canIMint","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"canSell","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"canWithdraw","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contract_owner","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"createAuction","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"_closingTime","internalType":"uint256"},{"type":"address","name":"_beneficiary","internalType":"address payable"},{"type":"uint256","name":"_reservePrice","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"exists","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getApproved","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getPrice","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"highestBid","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address payable"}],"name":"highestBidder","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isApprovedForAll","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"operator","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isMinter","inputs":[{"type":"address","name":"account","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"mint","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"mintWithTokenURI","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"string","name":"tokenURI","internalType":"string"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"ownerOf","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"renounceMinter","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"safeTransferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"safeTransferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"sell","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"address","name":"wallet","internalType":"address payable"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"sellBidPrice","inputs":[{"type":"uint256","name":"","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setApprovalForAll","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"bool","name":"approved","internalType":"bool"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setTokenURI","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"string","name":"uri","internalType":"string"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"soldFor","inputs":[{"type":"uint256","name":"","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokenByIndex","inputs":[{"type":"uint256","name":"index","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokenOfOwnerByIndex","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"uint256","name":"index","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"string","name":"","internalType":"string"}],"name":"tokenURI","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"tokensOfOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"transfer","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"updateAdmin","inputs":[{"type":"address","name":"_admin","internalType":"address payable"},{"type":"uint256","name":"_commissionRate","internalType":"uint256"},{"type":"bool","name":"_anyoneCanMint","internalType":"bool"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"withdraw","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}],"constant":false}]
Deployed ByteCode
0x6080604052600436106102935760003560e01c806370a082311161015a578063b1cb48ef116100c1578063dc16bd431161007a578063dc16bd4314610d88578063e4e2bfe414610db2578063e757223014610ddc578063e985e9c514610e24578063ee1b59e414610e5f578063fbe85f0614610e7457610293565b8063b1cb48ef14610bc2578063b2ecfad414610c07578063b88d4fde14610c31578063c87b56dd14610d02578063d04c698314610d2c578063d96a094a14610d6b57610293565b8063a22cb46511610113578063a22cb46514610ab2578063a36b146214610aed578063a9059cbb14610b17578063aa271e1a14610b50578063b13fbe9614610b83578063b14c63c514610b9857610293565b806370a08231146109755780638462151c146109a857806389f4c0b114610a2b57806395d89b4114610a55578063983b2d5614610a6a5780639865027514610a9d57610293565b8063384f58eb116101fe5780634f558e79116101b75780634f558e79146107075780634f6ccce71461073157806350bb4e7f1461075b578063571a26a01461082157806361a09c971461088f5780636352211e1461094b57610293565b8063384f58eb146106055780633ca88a2f1461061a57806340c10f191461064457806342842e0e1461067d578063451df52e146106c0578063454a2ab3146106ea57610293565b806318160ddd1161025057806318160ddd146104df5780631ac70f6f146104f457806323b872dd1461051e578063263f5877146105615780632e1a7d4d146105a25780632f745c59146105cc57610293565b806301ffc9a71461029857806306fdde03146102e0578063081812fc1461036a578063095ea7b3146103b0578063162094c4146103eb578063172b099d146104a3575b600080fd5b3480156102a457600080fd5b506102cc600480360360208110156102bb57600080fd5b50356001600160e01b031916610e9e565b604080519115158252519081900360200190f35b3480156102ec57600080fd5b506102f5610ec1565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561032f578181015183820152602001610317565b50505050905090810190601f16801561035c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561037657600080fd5b506103946004803603602081101561038d57600080fd5b5035610f58565b604080516001600160a01b039092168252519081900360200190f35b3480156103bc57600080fd5b506103e9600480360360408110156103d357600080fd5b506001600160a01b038135169060200135610fba565b005b3480156103f757600080fd5b506103e96004803603604081101561040e57600080fd5b81359190810190604081016020820135600160201b81111561042f57600080fd5b82018360208201111561044157600080fd5b803590602001918460018302840111600160201b8311171561046257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506110cb945050505050565b3480156104af57600080fd5b506104cd600480360360208110156104c657600080fd5b50356110d9565b60408051918252519081900360200190f35b3480156104eb57600080fd5b506104cd6110eb565b34801561050057600080fd5b506102cc6004803603602081101561051757600080fd5b50356110f1565b34801561052a57600080fd5b506103e96004803603606081101561054157600080fd5b506001600160a01b03813581169160208101359091169060400135611143565b34801561056d57600080fd5b506103e96004803603606081101561058457600080fd5b506001600160a01b0381351690602081013590604001351515611198565b3480156105ae57600080fd5b506102cc600480360360208110156105c557600080fd5b503561122e565b3480156105d857600080fd5b506104cd600480360360408110156105ef57600080fd5b506001600160a01b0381351690602001356113d9565b34801561061157600080fd5b50610394611458565b34801561062657600080fd5b506104cd6004803603602081101561063d57600080fd5b5035611467565b34801561065057600080fd5b506102cc6004803603604081101561066757600080fd5b506001600160a01b0381351690602001356114ed565b34801561068957600080fd5b506103e9600480360360608110156106a057600080fd5b506001600160a01b03813581169160208101359091169060400135611548565b3480156106cc57600080fd5b50610394600480360360208110156106e357600080fd5b5035611563565b6103e96004803603602081101561070057600080fd5b5035611581565b34801561071357600080fd5b506102cc6004803603602081101561072a57600080fd5b5035611996565b34801561073d57600080fd5b506104cd6004803603602081101561075457600080fd5b50356119a1565b34801561076757600080fd5b506102cc6004803603606081101561077e57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b8111156107ad57600080fd5b8201836020820111156107bf57600080fd5b803590602001918460018302840111600160201b831117156107e057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611a07945050505050565b34801561082d57600080fd5b5061084b6004803603602081101561084457600080fd5b5035611a6d565b604080516001600160a01b0397881681526020810196909652939095168484015260608401919091521515608083015260a082019290925290519081900360c00190f35b34801561089b57600080fd5b506102cc600480360360408110156108b257600080fd5b810190602081018135600160201b8111156108cc57600080fd5b8201836020820111156108de57600080fd5b803590602001918460018302840111600160201b831117156108ff57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b03169150611ab49050565b34801561095757600080fd5b506103946004803603602081101561096e57600080fd5b5035611b2b565b34801561098157600080fd5b506104cd6004803603602081101561099857600080fd5b50356001600160a01b0316611b7f565b3480156109b457600080fd5b506109db600480360360208110156109cb57600080fd5b50356001600160a01b0316611be7565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610a175781810151838201526020016109ff565b505050509050019250505060405180910390f35b348015610a3757600080fd5b506102cc60048036036020811015610a4e57600080fd5b5035611c48565b348015610a6157600080fd5b506102f5611cdd565b348015610a7657600080fd5b506103e960048036036020811015610a8d57600080fd5b50356001600160a01b0316611d3e565b348015610aa957600080fd5b506103e9611d8c565b348015610abe57600080fd5b506103e960048036036040811015610ad557600080fd5b506001600160a01b0381351690602001351515611d97565b348015610af957600080fd5b506104cd60048036036020811015610b1057600080fd5b5035611e63565b348015610b2357600080fd5b506103e960048036036040811015610b3a57600080fd5b506001600160a01b038135169060200135611e75565b348015610b5c57600080fd5b506102cc60048036036020811015610b7357600080fd5b50356001600160a01b0316611e80565b348015610b8f57600080fd5b506102cc611e93565b348015610ba457600080fd5b506104cd60048036036020811015610bbb57600080fd5b5035611e9c565b348015610bce57600080fd5b506103e960048036036080811015610be557600080fd5b508035906020810135906001600160a01b036040820135169060600135611eb1565b348015610c1357600080fd5b506102cc60048036036020811015610c2a57600080fd5b5035611ff2565b348015610c3d57600080fd5b506103e960048036036080811015610c5457600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610c8e57600080fd5b820183602082011115610ca057600080fd5b803590602001918460018302840111600160201b83111715610cc157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612029945050505050565b348015610d0e57600080fd5b506102f560048036036020811015610d2557600080fd5b503561207b565b348015610d3857600080fd5b506103e960048036036060811015610d4f57600080fd5b50803590602081013590604001356001600160a01b0316612156565b6103e960048036036020811015610d8157600080fd5b5035612245565b348015610d9457600080fd5b506103e960048036036020811015610dab57600080fd5b503561265b565b348015610dbe57600080fd5b506102cc60048036036020811015610dd557600080fd5b5035612b4c565b348015610de857600080fd5b50610e0660048036036020811015610dff57600080fd5b5035612bab565b60408051938452602084019290925282820152519081900360600190f35b348015610e3057600080fd5b506102cc60048036036040811015610e4757600080fd5b506001600160a01b0381358116916020013516612c2a565b348015610e6b57600080fd5b506102cc612c58565b348015610e8057600080fd5b506102cc60048036036020811015610e9757600080fd5b5035612c75565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60098054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610f4d5780601f10610f2257610100808354040283529160200191610f4d565b820191906000526020600020905b815481529060010190602001808311610f3057829003601f168201915b505050505090505b90565b6000610f6382612cee565b610f9e5760405162461bcd60e51b815260040180806020018281038252602c815260200180613c9b602c913960400191505060405180910390fd5b506000908152600260205260409020546001600160a01b031690565b6000610fc582611b2b565b9050806001600160a01b0316836001600160a01b031614156110185760405162461bcd60e51b8152600401808060200182810382526021815260200180613db16021913960400191505060405180910390fd5b336001600160a01b038216148061103457506110348133612c2a565b61106f5760405162461bcd60e51b8152600401808060200182810382526038815260200180613b7d6038913960400191505060405180910390fd5b60008281526002602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6110d58282612d0b565b5050565b60146020526000908152604090205481565b60075490565b6000336110fd83611b2b565b6001600160a01b0316148015611125575060008281526016602052604090206004015460ff16155b801561113d5750600082815260146020526040902054155b92915050565b61114d3382612d6e565b6111885760405162461bcd60e51b8152600401808060200182810382526031815260200180613dff6031913960400191505060405180910390fd5b611193838383612e12565b505050565b6011546001600160a01b031633146111f7576040805162461bcd60e51b815260206004820152601f60248201527f4f6e6c7920636f6e7472616374206f776e65722063616e20646f207468697300604482015290519081900360640190fd5b601080546001600160a01b0319166001600160a01b039490941693909317909255601255600d805460ff1916911515919091179055565b600f80546001019081905560009061124583612c75565b6112805760405162461bcd60e51b8152600401808060200182810382526022815260200180613ec46022913960400191505060405180910390fd5b6000838152601660205260409020600301541561134857600083815260166020526040808220600281015460039091015491516001600160a01b0390911691908381818185875af1925050503d80600081146112f8576040519150601f19603f3d011682016040523d82523d6000602084013e6112fd565b606091505b5050905080611346576040805162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b604482015290519081900360640190fd5b505b600083815260166020526040812080546001600160a01b031990811682556001820183905560028201805490911690556003810182905560048101805460ff1916905560050155600f5481146113d3576040805162461bcd60e51b815260206004820152601f60248201526000805160206139b5833981519152604482015290519081900360640190fd5b50919050565b60006113e483611b7f565b82106114215760405162461bcd60e51b815260040180806020018281038252602b815260200180613a35602b913960400191505060405180910390fd5b6001600160a01b038316600090815260056020526040902080548390811061144557fe5b9060005260206000200154905092915050565b6011546001600160a01b031681565b60008181526016602052604081206004015460ff16158015611496575060008281526014602052604090205415155b80156114af575060008281526014602052604090205415155b80156114cb5750306114c083610f58565b6001600160a01b0316145b156114e55750600081815260146020526040902054610ebc565b506000610ebc565b600060606114f9612c58565b6115345760405162461bcd60e51b8152600401808060200182810382526030815260200180613c296030913960400191505060405180910390fd5b61153e8484612e31565b5060019392505050565b61119383838360405180602001604052806000815250612029565b6000908152601660205260409020600201546001600160a01b031690565b600f80546001019081905561159533612e4e565b156115db576040805162461bcd60e51b81526020600482015260116024820152704e6f20736372697074206b69646469657360781b604482015290519081900360640190fd5b60008281526016602052604090206004015460ff16611641576040805162461bcd60e51b815260206004820152601760248201527f4e6f206f70656e65642061756374696f6e20666f756e64000000000000000000604482015290519081900360640190fd5b3061164b83610f58565b6001600160a01b0316146116a6576040805162461bcd60e51b815260206004820152601b60248201527f43616e6e6f7420636f6d706c657465207468652061756374696f6e0000000000604482015290519081900360640190fd5b600082815260166020526040902060010154421115611705576040805162461bcd60e51b815260206004820152601660248201527520bab1ba34b7b71030b63932b0b23c9032b73232b21760511b604482015290519081900360640190fd5b600082815260166020526040902060030154341161176a576040805162461bcd60e51b815260206004820152601e60248201527f546865726520616c7265616479206973206120686967686572206269642e0000604482015290519081900360640190fd5b600061177583611b2b565b9050336001600160a01b03821614156117bf5760405162461bcd60e51b8152600401808060200182810382526036815260200180613ee66036913960400191505060405180910390fd5b600083815260166020526040902060030154156118e757600083815260166020526040808220600281015460039091015491516001600160a01b0390911691908381818185875af1925050503d8060008114611837576040519150601f19603f3d011682016040523d82523d6000602084013e61183c565b606091505b5050905080611885576040805162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b604482015290519081900360640190fd5b600084815260166020908152604091829020600281015460039091015483516001600160a01b0390921682529181019190915281517fbb28353e4598c3b9199101a66e0989549b659a59a54d2c27fbb183f1932c8e6d929181900390910190a1505b6000838152601660209081526040918290206002810180546001600160a01b031916339081179091553460039092018290558351918252918101869052825191927fdafc4a123c6bb3b49dd38a0cba299808581a0126a37248a5f1102d5e5fa0633792918290030190a250600f5481146110d5576040805162461bcd60e51b815260206004820152601f60248201526000805160206139b5833981519152604482015290519081900360640190fd5b600061113d82612cee565b60006119ab6110eb565b82106119e85760405162461bcd60e51b815260040180806020018281038252602c815260200180613e30602c913960400191505060405180910390fd5b600782815481106119f557fe5b90600052602060002001549050919050565b60006060611a13612c58565b611a4e5760405162461bcd60e51b8152600401808060200182810382526030815260200180613c296030913960400191505060405180910390fd5b611a588585612e31565b611a628484612d0b565b506001949350505050565b6016602052600090815260409020805460018201546002830154600384015460048501546005909501546001600160a01b0394851695939490921692909160ff9091169086565b60006060611ac0612c58565b611afb5760405162461bcd60e51b8152600401808060200182810382526030815260200180613c296030913960400191505060405180910390fd5b600e805460010190819055611b0f90612cee565b611afb57611b1f83600e54612e31565b61153e600e5485612d0b565b6000818152600160205260408120546001600160a01b03168061113d5760405162461bcd60e51b8152600401808060200182810382526029815260200180613bdf6029913960400191505060405180910390fd5b60006001600160a01b038216611bc65760405162461bcd60e51b815260040180806020018281038252602a815260200180613bb5602a913960400191505060405180910390fd5b6001600160a01b038216600090815260036020526040902061113d90612e85565b6060611bf282612e89565b805480602002602001604051908101604052809291908181526020018280548015611c3c57602002820191906000526020600020905b815481526020019060010190808311611c28575b50505050509050919050565b6000611c5333612e4e565b158015611c71575060008281526016602052604090206004015460ff165b8015611c8e57506000828152601660205260409020600101544211155b8015611cb45750611c9e82611b2b565b6001600160a01b0316336001600160a01b031614155b8015611cd0575030611cc583610f58565b6001600160a01b0316145b156114e557506001610ebc565b600a8054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610f4d5780601f10610f2257610100808354040283529160200191610f4d565b6060611d48612c58565b611d835760405162461bcd60e51b8152600401808060200182810382526030815260200180613c296030913960400191505060405180910390fd5b6110d582612ea3565b611d9533612eeb565b565b6001600160a01b038216331415611df5576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b3360008181526004602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b60136020526000908152604090205481565b6110d5338383612e12565b600061113d600c8363ffffffff612f3316565b600d5460ff1681565b60009081526016602052604090206003015490565b60008481526014602052604090205415611efc5760405162461bcd60e51b8152600401808060200182810382526044815260200180613d6d6044913960600191505060405180910390fd5b60008481526016602052604090206004015460ff1615611f4d5760405162461bcd60e51b81526004018080602001828103825260358152602001806139806035913960400191505060405180910390fd5b33611f5785611b2b565b6001600160a01b031614611f9c5760405162461bcd60e51b815260040180806020018281038252602e815260200180613a07602e913960400191505060405180910390fd5b600084815260166020526040902080546001600160a01b0319166001600160a01b0384161781556001808201859055600582018390556004909101805460ff19169091179055611fec3085610fba565b50505050565b600033611ffe83611b2b565b6001600160a01b031614801561113d57505060009081526016602052604090206004015460ff161590565b612034848484611143565b61204084848484612f9a565b611fec5760405162461bcd60e51b8152600401808060200182810382526032815260200180613a606032913960400191505060405180910390fd5b606061208682612cee565b6120c15760405162461bcd60e51b815260040180806020018281038252602f815260200180613d3e602f913960400191505060405180910390fd5b6000828152600b602090815260409182902080548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084529091830182828015611c3c5780601f1061212957610100808354040283529160200191611c3c565b820191906000526020600020905b8154815290600101906020018083116121375750939695505050505050565b3361216084611b2b565b6001600160a01b0316146121a55760405162461bcd60e51b815260040180806020018281038252602b815260200180613a92602b913960400191505060405180910390fd5b60008381526016602052604090206004015460ff16156121f65760405162461bcd60e51b815260040180806020018281038252603d815260200180613e87603d913960400191505060405180910390fd5b60008381526014602052604090208290558115611193576122173084610fba565b600083815260156020526040902080546001600160a01b0383166001600160a01b0319909116179055505050565b600f80546001019081905560008281526016602052604090206004015460ff1615801561227f575060008281526014602052604090205415155b6122ba5760405162461bcd60e51b815260040180806020018281038252602d815260200180613dd2602d913960400191505060405180910390fd5b60008281526014602052604090205434101561231d576040805162461bcd60e51b815260206004820152601e60248201527f4552433732314d61746368613a204e6f7420656e6f7567682066756e64730000604482015290519081900360640190fd5b600061232883611b2b565b9050336001600160a01b03821614156123725760405162461bcd60e51b8152600401808060200182810382526037815260200180613b1a6037913960400191505060405180910390fd5b604080516001600160a01b038316602482015233604482015260648082018690528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526123ca9030906130cd565b60006123f260646123e66012543461326f90919063ffffffff16565b9063ffffffff6132cf16565b90506000612406348363ffffffff61333916565b60008681526015602052604080822054905192935090916001600160a01b039091169083908381818185875af1925050503d8060008114612463576040519150601f19603f3d011682016040523d82523d6000602084013e612468565b606091505b50509050806124b1576040805162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b604482015290519081900360640190fd5b6010546040516000916001600160a01b03169085908381818185875af1925050503d80600081146124fe576040519150601f19603f3d011682016040523d82523d6000602084013e612503565b606091505b505090508061254c576040805162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b604482015290519081900360640190fd5b60008781526014602090815260408083208390556015825280832080546001600160a01b0319169055601382529182902034908190558251908152915133926001600160a01b038916928b927f88863d5e20f64464b554931394e2e4b6f09c10015147215bf26b3ba5070acebe9281900390910190a4601254604080513481526020810192909252818101869052516001600160a01b0387169189917fef7a63d352d8b0f42e35d7f8bd277ba75ba2ff721a50eaad4c62f1ee6561d5eb9181900360600190a35050505050600f5481146110d5576040805162461bcd60e51b815260206004820152601f60248201526000805160206139b5833981519152604482015290519081900360640190fd5b600f80546001019081905560008281526016602052604090206004015460ff166126b65760405162461bcd60e51b8152600401808060200182810382526039815260200180613abd6039913960400191505060405180910390fd5b600082815260166020526040902060010154421015612715576040805162461bcd60e51b815260206004820152601660248201527520bab1ba34b7b7103737ba103cb2ba1032b73232b21760511b604482015290519081900360640190fd5b60008281526016602052604090206005810154600390910154101561276b5760405162461bcd60e51b81526004018080602001828103825260328152602001806139d56032913960400191505060405180910390fd5b600082815260166020526040812060028101546012546003909201546001600160a01b0390911692916127ab916064916123e6919063ffffffff61326f16565b600085815260166020526040812060030154919250906127d1908363ffffffff61333916565b60008681526016602052604080822054905192935090916001600160a01b039091169083908381818185875af1925050503d806000811461282e576040519150601f19603f3d011682016040523d82523d6000602084013e612833565b606091505b505090508061287c576040805162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b604482015290519081900360640190fd5b6010546040516000916001600160a01b03169085908381818185875af1925050503d80600081146128c9576040519150601f19603f3d011682016040523d82523d6000602084013e6128ce565b606091505b5050905080612917576040805162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b604482015290519081900360640190fd5b6000878152601660209081526040918290208054600390910154835190815292516001600160a01b03808a16949216928b927f88863d5e20f64464b554931394e2e4b6f09c10015147215bf26b3ba5070acebe929081900390910190a4600087815260166020908152604091829020805460039091015460125484519182529281019290925281830187905291516001600160a01b039092169189917fef7a63d352d8b0f42e35d7f8bd277ba75ba2ff721a50eaad4c62f1ee6561d5eb919081900360600190a3600087815260166020908152604091829020600281015460039091015483516001600160a01b0390921682529181019190915281517fdaec4582d5d9595688c8c98545fdd1c696d41c6aeaeb636737e84ed2f5c00eda929181900390910190a16000612a4988611b2b565b604080516001600160a01b0380841660248301528916604482015260648082018c90528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052909150612aa69030906130cd565b505050600085815260166020818152604080842060038101805460138552928620929092559290915281546001600160a01b0319908116835560018301849055600283018054909116905582905560048101805460ff19169055600501555050600f54821490506110d5576040805162461bcd60e51b815260206004820152601f60248201526000805160206139b5833981519152604482015290519081900360640190fd5b60008181526016602052604081206004015460ff168015612b7e57506000828152601660205260409020600101544210155b8015611cd0575060008281526016602052604090206005810154600390910154106114e557506001610ebc565b6000818152601460205260408120548190819015612bdc575050506000818152601460205260408120549080612c23565b60008481526016602052604090206003015415612c0e5750505060008181526016602052604081206003015481612c23565b50505060008181526013602052604081205481905b9193909250565b6001600160a01b03918216600090815260046020908152604080832093909416825291909152205460ff1690565b600d5460009060ff1680612c705750612c7033611e80565b905090565b60008181526016602052604081206004015460ff168015611cd057506000828152601660205260409020600101544210801590612cc8575060008281526016602052604090206005810154600390910154105b80611cd0575030612cd883610f58565b6001600160a01b0316146114e557506001610ebc565b6000908152600160205260409020546001600160a01b0316151590565b612d1482612cee565b612d4f5760405162461bcd60e51b815260040180806020018281038252602c815260200180613cc7602c913960400191505060405180910390fd5b6000828152600b602090815260409091208251611193928401906138c7565b6000612d7982612cee565b612db45760405162461bcd60e51b815260040180806020018281038252602c815260200180613b51602c913960400191505060405180910390fd5b6000612dbf83611b2b565b9050806001600160a01b0316846001600160a01b03161480612dfa5750836001600160a01b0316612def84610f58565b6001600160a01b0316145b80612e0a5750612e0a8185612c2a565b949350505050565b612e1d838383613396565b612e2783826134da565b61119382826135cf565b612e3b828261360d565b612e4582826135cf565b6110d58161373e565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708115801590612e0a5750141592915050565b5490565b6001600160a01b0316600090815260056020526040902090565b612eb4600c8263ffffffff61378216565b6040516001600160a01b038216907f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f690600090a250565b612efc600c8263ffffffff61380316565b6040516001600160a01b038216907fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669290600090a250565b60006001600160a01b038216612f7a5760405162461bcd60e51b8152600401808060200182810382526022815260200180613cf36022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b6000612fae846001600160a01b0316612e4e565b612fba57506001612e0a565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b8381101561303457818101518382015260200161301c565b50505050905090810190601f1680156130615780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561308357600080fd5b505af1158015613097573d6000803e3d6000fd5b505050506040513d60208110156130ad57600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b6130df826001600160a01b0316612e4e565b613130576040805162461bcd60e51b815260206004820181905260248201527f536166654552433732313a2063616c6c20746f206e6f6e2d636f6e7472616374604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b6020831061316e5780518252601f19909201916020918201910161314f565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146131d0576040519150601f19603f3d011682016040523d82523d6000602084013e6131d5565b606091505b5091509150816132165760405162461bcd60e51b8152600401808060200182810382526021815260200180613c086021913960400191505060405180910390fd5b805115611fec5780806020019051602081101561323257600080fd5b5051611fec5760405162461bcd60e51b815260040180806020018281038252602b815260200180613e5c602b913960400191505060405180910390fd5b60008261327e5750600061113d565b8282028284828161328b57fe5b04146132c85760405162461bcd60e51b8152600401808060200182810382526021815260200180613c7a6021913960400191505060405180910390fd5b9392505050565b6000808211613325576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161333057fe5b04949350505050565b600082821115613390576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b826001600160a01b03166133a982611b2b565b6001600160a01b0316146133ee5760405162461bcd60e51b8152600401808060200182810382526029815260200180613d156029913960400191505060405180910390fd5b6001600160a01b0382166134335760405162461bcd60e51b8152600401808060200182810382526024815260200180613af66024913960400191505060405180910390fd5b61343c8161386a565b6001600160a01b038316600090815260036020526040902061345d906138a7565b6001600160a01b038216600090815260036020526040902061347e906138be565b60008181526001602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6001600160a01b03821660009081526005602052604081205461350490600163ffffffff61333916565b60008381526006602052604090205490915080821461359f576001600160a01b038416600090815260056020526040812080548490811061354157fe5b906000526020600020015490508060056000876001600160a01b03166001600160a01b03168152602001908152602001600020838154811061357f57fe5b600091825260208083209091019290925591825260069052604090208190555b6001600160a01b03841660009081526005602052604090208054906135c8906000198301613945565b5050505050565b6001600160a01b0390911660009081526005602081815260408084208054868652600684529185208290559282526001810183559183529091200155565b6001600160a01b038216613668576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b61367181612cee565b156136c3576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b600081815260016020908152604080832080546001600160a01b0319166001600160a01b038716908117909155835260039091529020613702906138be565b60405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600780546000838152600860205260408120829055600182018355919091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880155565b61378c8282612f33565b156137de576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b61380d8282612f33565b6138485760405162461bcd60e51b8152600401808060200182810382526021815260200180613c596021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b6000818152600260205260409020546001600160a01b0316156138a457600081815260026020526040902080546001600160a01b03191690555b50565b80546138ba90600163ffffffff61333916565b9055565b80546001019055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061390857805160ff1916838001178555613935565b82800160010185558215613935579182015b8281111561393557825182559160200191906001019061391a565b50613941929150613965565b5090565b815481835581811115611193576000838152602090206111939181019083015b610f5591905b80821115613941576000815560010161396b56fe4552433732314d61746368613a205468652073656c6563746564204e465420616c72656164792068617320616e2061756374696f6e5265656e7472616e637947756172643a207265656e7472616e742063616c6c0041756374696f6e20686173206e6f74207265616368656420697473206d696e696d756d20726573657276652070726963652e4552433732314d61746368613a204f6e6c79206f776e65722063616e2061756374696f6e2074686973206974656d455243373231456e756d657261626c653a206f776e657220696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732314d61746368613a204f6e6c79206f776e65722063616e2073656c6c2074686973206974656d4552433732314d61746368613a205468657265206973206e6f2061756374696f6e206f70656e656420666f72207468697320746f6b656e49644552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732314d61746368613a205468652073656c6c65722063616e6e6f742062757920686973206f776e20636f6c6c65637469626c654552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e536166654552433732313a206c6f772d6c6576656c2063616c6c206661696c65644d696e746572526f6c653a2063616c6c657220646f6573206e6f74206861766520746865204d696e74657220726f6c65526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732314d657461646174613a2055524920736574206f66206e6f6e6578697374656e7420746f6b656e526f6c65733a206163636f756e7420697320746865207a65726f20616464726573734552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732314d61746368613a205468652073656c6563746564204e4654206973206f70656e20666f722073616c652c2063616e6e6f742062652061756374696f6e65644552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732314d61746368613a2054686520636f6c6c65637469626c65206973206e6f7420666f722073616c654552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564455243373231456e756d657261626c653a20676c6f62616c20696e646578206f7574206f6620626f756e6473536166654552433732313a204552433230206f7065726174696f6e20646964206e6f7420737563636565644552433732314d61746368613a2043616e6e6f742073656c6c20616e206974656d2077686963682068617320616e206163746976652061756374696f6e436f6e646974696f6e7320746f20776974686472617720617265206e6f74206d65744552433732314d61746368613a20546865206f776e65722063616e6e6f742062696420686973206f776e20636f6c6c65637469626c65a265627a7a72315820e297f5c0e9f86f85fb4bc6421604bb889a26fc438fbeb2728252e011ae07fdc964736f6c63430005110032