ERC-721
Overview
Max Total Supply
3,293 LADT
Holders
3,293
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 LADTLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
LOOTaDOG
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./ERC3525.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; contract LOOTaDOG is ERC3525, Ownable, Pausable { bool private _allow_transfer; bool private _allow_transfer_value; address private _signer; mapping(uint256 => bool) private _order_ids; string private _baseTokenURI; uint256 private _token_count_limit; /* Represents an un-minted NFT, which has not yet been recorded into the blockchain. A signed voucher can be redeemed for a real NFT using the redeem function. */ struct Voucher { uint256 id; /* The tokenId */ uint256 tokenId; /* The amount */ uint256 amount; /*expiration Time*/ uint256 expirationTime; /*owner*/ address owner; } constructor() ERC3525("LOOTaDOG Pass Card", "LADT", 2) { _allow_transfer = false; _allow_transfer_value = false; _signer = msg.sender; _token_count_limit = 1000; } function setBaseURI(string calldata baseURI) external onlyOwner { _baseTokenURI = baseURI; } function _baseURI() internal view virtual override returns (string memory) { return _baseTokenURI; } function queryId(uint256 id) public view returns (bool) { return _order_ids[id]; } function blockId(uint256 id) public { _order_ids[id] = true; } function pause() public onlyOwner { _pause(); } function unpause() public onlyOwner { _unpause(); } function mintToken( uint256 id, uint256 amount, uint256 expirationTime, address owner, uint8 v, bytes32 r, bytes32 s ) public payable whenNotPaused { require(block.timestamp < expirationTime, "Expired voucher"); require(totalSupply() < _token_count_limit, "Sold out"); require(balanceOf(msg.sender) == 0, "Already minted"); require(_order_ids[id] == false, "Duplicate id"); require(owner == msg.sender, "Invalid owner"); _verifySign(Voucher(id, 0, amount, expirationTime, owner), v, r, s); _mint(msg.sender, 1, amount); _order_ids[id] = true; } function mintValue( uint256 id, uint256 tokenId, uint256 amount, uint256 expirationTime, address owner, uint8 v, bytes32 r, bytes32 s ) public payable whenNotPaused { require(block.timestamp < expirationTime, "Expired voucher"); require(_order_ids[id] == false, "Duplicate id"); require(owner == msg.sender, "Invalid owner"); require(amount > 0, "Invalid amount"); _verifySign(Voucher(id, tokenId, amount, expirationTime, owner), v, r, s); _mintValue(tokenId, amount); _order_ids[id] = true; } function transferFrom( uint256 fromTokenId_, address to_, uint256 value_ ) public payable virtual override whenNotPaused returns (uint256) { require(_allow_transfer_value, "Value does not allow transfer"); return super.transferFrom(fromTokenId_, to_, value_); } function transferFrom( uint256 fromTokenId_, uint256 toTokenId_, uint256 value_ ) public payable virtual override whenNotPaused { super.transferFrom(fromTokenId_, toTokenId_, value_); } function transferFrom( address from_, address to_, uint256 tokenId_ ) public payable virtual override whenNotPaused { require(_allow_transfer, "Token does not allow transfer"); super.transferFrom(from_, to_, tokenId_); } function safeTransferFrom( address from_, address to_, uint256 tokenId_, bytes memory data_ ) public payable virtual override whenNotPaused { require(_allow_transfer, "Token does not allow transfer"); super.safeTransferFrom(from_, to_, tokenId_, data_); } function safeTransferFrom( address from_, address to_, uint256 tokenId_ ) public payable virtual override whenNotPaused { require(_allow_transfer, "Token does not allow transfer"); super.safeTransferFrom(from_, to_, tokenId_); } function setTokenCountLimit(uint256 count) public onlyOwner { _token_count_limit = count; } function getTokenCountLimit() public view returns (uint256) { return _token_count_limit; } function setSigner(address addr) public onlyOwner { _signer = addr; } function getSigner() public view returns (address) { return _signer; } bytes32 private constant salt = 0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558; //string private constant EIP712_DOMAIN ="EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)"; bytes32 private constant EIP712_DOMAIN_TYPEHASH = 0xd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472; //keccak256(bytes(EIP712_DOMAIN)); //string private constant VOUCHER_TYPE = //"Voucher(uint256 id,uint256 tokenId,uint256 amount,uint256 expirationTime,address owner)"; bytes32 private constant VOUCHER_TYPEHASH = 0x4bd317336ea30fdfa31168cda381dacdf9ed1dd92eda94108d28629b6cf9b8c7; //keccak256(bytes(VOUCHER_TYPEHASH)); function _verifySign( Voucher memory voucher, uint8 v, bytes32 r, bytes32 s ) internal view { address signer = ecrecover(_hashVoucher(voucher), v, r, s); require(_signer == signer, "Invalid signer"); } /// @notice Returns a hash of the given NFTVoucher, prepared using EIP712 typed data hashing rules. /// @param voucher An NFTVoucher describing an unminted NFT. function _hashVoucher(Voucher memory voucher) internal view returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", _hashDomainSeparator(), _encodeVoucher(voucher))); } function _encodeVoucher(Voucher memory voucher) internal pure returns (bytes32) { return keccak256( abi.encode( VOUCHER_TYPEHASH, voucher.id, voucher.tokenId, voucher.amount, voucher.expirationTime, voucher.owner ) ); } function _hashDomainSeparator() internal view returns (bytes32) { return keccak256( abi.encode( EIP712_DOMAIN_TYPEHASH, keccak256(bytes("LOOTaDOG Dapp")), keccak256(bytes("1")), _getChainID(), address(this), salt ) ); } /*Since v0.5.12, Solidity provides a CHAINID OPCODE in assembly */ function _getChainID() internal view returns (uint256) { return block.chainid; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is 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. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. 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;` */ library Counters { 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 { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "./IERC721.sol"; import "./IERC3525.sol"; import "./IERC721Receiver.sol"; import "./IERC3525Receiver.sol"; import "./extensions/IERC721Enumerable.sol"; import "./extensions/IERC721Metadata.sol"; import "./extensions/IERC3525Metadata.sol"; import "./periphery/interface/IERC3525MetadataDescriptor.sol"; contract ERC3525 is Context, IERC3525Metadata, IERC721Enumerable { using Strings for address; using Strings for uint256; using Address for address; using Counters for Counters.Counter; event SetMetadataDescriptor(address indexed metadataDescriptor); struct TokenData { uint256 id; uint256 slot; uint256 balance; address owner; address approved; address[] valueApprovals; } struct AddressData { uint256[] ownedTokens; mapping(uint256 => uint256) ownedTokensIndex; mapping(address => bool) approvals; } string private _name; string private _symbol; uint8 private _decimals; Counters.Counter private _tokenIdGenerator; // id => (approval => allowance) // @dev _approvedValues cannot be defined within TokenData, cause struct containing mappings cannot be constructed. mapping(uint256 => mapping(address => uint256)) private _approvedValues; TokenData[] private _allTokens; // key: id mapping(uint256 => uint256) private _allTokensIndex; mapping(address => AddressData) private _addressData; IERC3525MetadataDescriptor public metadataDescriptor; constructor(string memory name_, string memory symbol_, uint8 decimals_) { _name = name_; _symbol = symbol_; _decimals = decimals_; } function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId || interfaceId == type(IERC3525).interfaceId || interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC3525Metadata).interfaceId || interfaceId == type(IERC721Enumerable).interfaceId || interfaceId == type(IERC721Metadata).interfaceId; } /** * @dev Returns the token collection name. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the token collection symbol. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals the token uses for value. */ function valueDecimals() public view virtual override returns (uint8) { return _decimals; } function balanceOf(uint256 tokenId_) public view virtual override returns (uint256) { _requireMinted(tokenId_); return _allTokens[_allTokensIndex[tokenId_]].balance; } function ownerOf(uint256 tokenId_) public view virtual override returns (address owner_) { _requireMinted(tokenId_); owner_ = _allTokens[_allTokensIndex[tokenId_]].owner; require(owner_ != address(0), "ERC3525: invalid token ID"); } function slotOf(uint256 tokenId_) public view virtual override returns (uint256) { _requireMinted(tokenId_); return _allTokens[_allTokensIndex[tokenId_]].slot; } function _baseURI() internal view virtual returns (string memory) { return ""; } function contractURI() public view virtual override returns (string memory) { string memory baseURI = _baseURI(); return address(metadataDescriptor) != address(0) ? metadataDescriptor.constructContractURI() : bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, "contract/", Strings.toHexString(address(this)))) : ""; } function slotURI(uint256 slot_) public view virtual override returns (string memory) { string memory baseURI = _baseURI(); return address(metadataDescriptor) != address(0) ? metadataDescriptor.constructSlotURI(slot_) : bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, "slot/", slot_.toString())) : ""; } /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId_) public view virtual override returns (string memory) { _requireMinted(tokenId_); string memory baseURI = _baseURI(); return address(metadataDescriptor) != address(0) ? metadataDescriptor.constructTokenURI(tokenId_) : bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId_.toString())) : ""; } function approve(uint256 tokenId_, address to_, uint256 value_) public payable virtual override { address owner = ERC3525.ownerOf(tokenId_); require(to_ != owner, "ERC3525: approval to current owner"); require( _msgSender() == owner || ERC3525.isApprovedForAll(owner, _msgSender()), "ERC3525: approve caller is not owner nor approved for all" ); _approveValue(tokenId_, to_, value_); } function allowance(uint256 tokenId_, address operator_) public view virtual override returns (uint256) { _requireMinted(tokenId_); return _approvedValues[tokenId_][operator_]; } function transferFrom( uint256 fromTokenId_, address to_, uint256 value_ ) public payable virtual override returns (uint256) { _spendAllowance(_msgSender(), fromTokenId_, value_); uint256 newTokenId = _createDerivedTokenId(fromTokenId_); _mint(to_, newTokenId, ERC3525.slotOf(fromTokenId_), 0); _transferValue(fromTokenId_, newTokenId, value_); return newTokenId; } function transferFrom( uint256 fromTokenId_, uint256 toTokenId_, uint256 value_ ) public payable virtual override { _spendAllowance(_msgSender(), fromTokenId_, value_); _transferValue(fromTokenId_, toTokenId_, value_); } function balanceOf(address owner_) public view virtual override returns (uint256 balance) { require(owner_ != address(0), "ERC3525: balance query for the zero address"); return _addressData[owner_].ownedTokens.length; } function transferFrom( address from_, address to_, uint256 tokenId_ ) public payable virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId_), "ERC3525: transfer caller is not owner nor approved"); _transferTokenId(from_, to_, tokenId_); } function safeTransferFrom( address from_, address to_, uint256 tokenId_, bytes memory data_ ) public payable virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId_), "ERC3525: transfer caller is not owner nor approved"); _safeTransferTokenId(from_, to_, tokenId_, data_); } function safeTransferFrom( address from_, address to_, uint256 tokenId_ ) public payable virtual override { safeTransferFrom(from_, to_, tokenId_, ""); } function approve(address to_, uint256 tokenId_) public payable virtual override { address owner = ERC3525.ownerOf(tokenId_); require(to_ != owner, "ERC3525: approval to current owner"); require( _msgSender() == owner || ERC3525.isApprovedForAll(owner, _msgSender()), "ERC3525: approve caller is not owner nor approved for all" ); _approve(to_, tokenId_); } function getApproved(uint256 tokenId_) public view virtual override returns (address) { _requireMinted(tokenId_); return _allTokens[_allTokensIndex[tokenId_]].approved; } function setApprovalForAll(address operator_, bool approved_) public virtual override { _setApprovalForAll(_msgSender(), operator_, approved_); } function isApprovedForAll(address owner_, address operator_) public view virtual override returns (bool) { return _addressData[owner_].approvals[operator_]; } function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } function tokenByIndex(uint256 index_) public view virtual override returns (uint256) { require(index_ < ERC3525.totalSupply(), "ERC3525: global index out of bounds"); return _allTokens[index_].id; } function tokenOfOwnerByIndex(address owner_, uint256 index_) public view virtual override returns (uint256) { require(index_ < ERC3525.balanceOf(owner_), "ERC3525: owner index out of bounds"); return _addressData[owner_].ownedTokens[index_]; } function _setApprovalForAll( address owner_, address operator_, bool approved_ ) internal virtual { require(owner_ != operator_, "ERC3525: approve to caller"); _addressData[owner_].approvals[operator_] = approved_; emit ApprovalForAll(owner_, operator_, approved_); } function _isApprovedOrOwner(address operator_, uint256 tokenId_) internal view virtual returns (bool) { _requireMinted(tokenId_); address owner = ERC3525.ownerOf(tokenId_); return ( operator_ == owner || ERC3525.isApprovedForAll(owner, operator_) || ERC3525.getApproved(tokenId_) == operator_ ); } function _spendAllowance(address operator_, uint256 tokenId_, uint256 value_) internal virtual { uint256 currentAllowance = ERC3525.allowance(tokenId_, operator_); if (!_isApprovedOrOwner(operator_, tokenId_) && currentAllowance != type(uint256).max) { require(currentAllowance >= value_, "ERC3525: insufficient allowance"); _approveValue(tokenId_, operator_, currentAllowance - value_); } } function _exists(uint256 tokenId_) internal view virtual returns (bool) { return _allTokens.length != 0 && _allTokens[_allTokensIndex[tokenId_]].id == tokenId_; } function _requireMinted(uint256 tokenId_) internal view virtual { require(_exists(tokenId_), "ERC3525: invalid token ID"); } function _mint(address to_, uint256 slot_, uint256 value_) internal virtual returns (uint256) { uint256 tokenId = _createOriginalTokenId(); _mint(to_, tokenId, slot_, value_); return tokenId; } function _mint(address to_, uint256 tokenId_, uint256 slot_, uint256 value_) internal virtual { require(to_ != address(0), "ERC3525: mint to the zero address"); require(tokenId_ != 0, "ERC3525: cannot mint zero tokenId"); require(!_exists(tokenId_), "ERC3525: token already minted"); _beforeValueTransfer(address(0), to_, 0, tokenId_, slot_, value_); __mintToken(to_, tokenId_, slot_); __mintValue(tokenId_, value_); _afterValueTransfer(address(0), to_, 0, tokenId_, slot_, value_); } function _mintValue(uint256 tokenId_, uint256 value_) internal virtual { _requireMinted(tokenId_); address owner = ERC3525.ownerOf(tokenId_); uint256 slot = ERC3525.slotOf(tokenId_); _beforeValueTransfer(address(0), owner, 0, tokenId_, slot, value_); __mintValue(tokenId_, value_); _afterValueTransfer(address(0), owner, 0, tokenId_, slot, value_); } function __mintValue(uint256 tokenId_, uint256 value_) private { _allTokens[_allTokensIndex[tokenId_]].balance += value_; emit TransferValue(0, tokenId_, value_); } function __mintToken(address to_, uint256 tokenId_, uint256 slot_) private { TokenData memory tokenData = TokenData({ id: tokenId_, slot: slot_, balance: 0, owner: to_, approved: address(0), valueApprovals: new address[](0) }); _addTokenToAllTokensEnumeration(tokenData); _addTokenToOwnerEnumeration(to_, tokenId_); emit Transfer(address(0), to_, tokenId_); emit SlotChanged(tokenId_, 0, slot_); } function _burn(uint256 tokenId_) internal virtual { _requireMinted(tokenId_); TokenData storage tokenData = _allTokens[_allTokensIndex[tokenId_]]; address owner = tokenData.owner; uint256 slot = tokenData.slot; uint256 value = tokenData.balance; _beforeValueTransfer(owner, address(0), tokenId_, 0, slot, value); _clearApprovedValues(tokenId_); _removeTokenFromOwnerEnumeration(owner, tokenId_); _removeTokenFromAllTokensEnumeration(tokenId_); emit TransferValue(tokenId_, 0, value); emit SlotChanged(tokenId_, slot, 0); emit Transfer(owner, address(0), tokenId_); _afterValueTransfer(owner, address(0), tokenId_, 0, slot, value); } function _burnValue(uint256 tokenId_, uint256 burnValue_) internal virtual { _requireMinted(tokenId_); TokenData storage tokenData = _allTokens[_allTokensIndex[tokenId_]]; address owner = tokenData.owner; uint256 slot = tokenData.slot; uint256 value = tokenData.balance; require(value >= burnValue_, "ERC3525: burn value exceeds balance"); _beforeValueTransfer(owner, address(0), tokenId_, 0, slot, burnValue_); tokenData.balance -= burnValue_; emit TransferValue(tokenId_, 0, burnValue_); _afterValueTransfer(owner, address(0), tokenId_, 0, slot, burnValue_); } function _addTokenToOwnerEnumeration(address to_, uint256 tokenId_) private { _allTokens[_allTokensIndex[tokenId_]].owner = to_; _addressData[to_].ownedTokensIndex[tokenId_] = _addressData[to_].ownedTokens.length; _addressData[to_].ownedTokens.push(tokenId_); } function _removeTokenFromOwnerEnumeration(address from_, uint256 tokenId_) private { _allTokens[_allTokensIndex[tokenId_]].owner = address(0); AddressData storage ownerData = _addressData[from_]; uint256 lastTokenIndex = ownerData.ownedTokens.length - 1; uint256 lastTokenId = ownerData.ownedTokens[lastTokenIndex]; uint256 tokenIndex = ownerData.ownedTokensIndex[tokenId_]; ownerData.ownedTokens[tokenIndex] = lastTokenId; ownerData.ownedTokensIndex[lastTokenId] = tokenIndex; delete ownerData.ownedTokensIndex[tokenId_]; ownerData.ownedTokens.pop(); } function _addTokenToAllTokensEnumeration(TokenData memory tokenData_) private { _allTokensIndex[tokenData_.id] = _allTokens.length; _allTokens.push(tokenData_); } function _removeTokenFromAllTokensEnumeration(uint256 tokenId_) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId_]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) TokenData memory lastTokenData = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenData; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenData.id] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId_]; _allTokens.pop(); } function _approve(address to_, uint256 tokenId_) internal virtual { _allTokens[_allTokensIndex[tokenId_]].approved = to_; emit Approval(ERC3525.ownerOf(tokenId_), to_, tokenId_); } function _approveValue( uint256 tokenId_, address to_, uint256 value_ ) internal virtual { require(to_ != address(0), "ERC3525: approve value to the zero address"); if (!_existApproveValue(to_, tokenId_)) { _allTokens[_allTokensIndex[tokenId_]].valueApprovals.push(to_); } _approvedValues[tokenId_][to_] = value_; emit ApprovalValue(tokenId_, to_, value_); } function _clearApprovedValues(uint256 tokenId_) internal virtual { TokenData storage tokenData = _allTokens[_allTokensIndex[tokenId_]]; uint256 length = tokenData.valueApprovals.length; for (uint256 i = 0; i < length; i++) { address approval = tokenData.valueApprovals[i]; delete _approvedValues[tokenId_][approval]; } } function _existApproveValue(address to_, uint256 tokenId_) internal view virtual returns (bool) { uint256 length = _allTokens[_allTokensIndex[tokenId_]].valueApprovals.length; for (uint256 i = 0; i < length; i++) { if (_allTokens[_allTokensIndex[tokenId_]].valueApprovals[i] == to_) { return true; } } return false; } function _transferValue( uint256 fromTokenId_, uint256 toTokenId_, uint256 value_ ) internal virtual { require(_exists(fromTokenId_), "ERC3525: transfer from invalid token ID"); require(_exists(toTokenId_), "ERC3525: transfer to invalid token ID"); TokenData storage fromTokenData = _allTokens[_allTokensIndex[fromTokenId_]]; TokenData storage toTokenData = _allTokens[_allTokensIndex[toTokenId_]]; require(fromTokenData.balance >= value_, "ERC3525: insufficient balance for transfer"); require(fromTokenData.slot == toTokenData.slot, "ERC3525: transfer to token with different slot"); _beforeValueTransfer( fromTokenData.owner, toTokenData.owner, fromTokenId_, toTokenId_, fromTokenData.slot, value_ ); fromTokenData.balance -= value_; toTokenData.balance += value_; emit TransferValue(fromTokenId_, toTokenId_, value_); _afterValueTransfer( fromTokenData.owner, toTokenData.owner, fromTokenId_, toTokenId_, fromTokenData.slot, value_ ); require( _checkOnERC3525Received(fromTokenId_, toTokenId_, value_, ""), "ERC3525: transfer to non ERC3525Receiver" ); } function _transferTokenId( address from_, address to_, uint256 tokenId_ ) internal virtual { require(ERC3525.ownerOf(tokenId_) == from_, "ERC3525: transfer from invalid owner"); require(to_ != address(0), "ERC3525: transfer to the zero address"); uint256 slot = ERC3525.slotOf(tokenId_); uint256 value = ERC3525.balanceOf(tokenId_); _beforeValueTransfer(from_, to_, tokenId_, tokenId_, slot, value); _approve(address(0), tokenId_); _clearApprovedValues(tokenId_); _removeTokenFromOwnerEnumeration(from_, tokenId_); _addTokenToOwnerEnumeration(to_, tokenId_); emit Transfer(from_, to_, tokenId_); _afterValueTransfer(from_, to_, tokenId_, tokenId_, slot, value); } function _safeTransferTokenId( address from_, address to_, uint256 tokenId_, bytes memory data_ ) internal virtual { _transferTokenId(from_, to_, tokenId_); require( _checkOnERC721Received(from_, to_, tokenId_, data_), "ERC3525: transfer to non ERC721Receiver" ); } function _checkOnERC3525Received( uint256 fromTokenId_, uint256 toTokenId_, uint256 value_, bytes memory data_ ) private returns (bool) { address to = ERC3525.ownerOf(toTokenId_); if (to.isContract() && IERC165(to).supportsInterface(type(IERC3525Receiver).interfaceId)) { try IERC3525Receiver(to).onERC3525Received(_msgSender(), fromTokenId_, toTokenId_, value_, data_) returns (bytes4 retval) { return retval == IERC3525Receiver.onERC3525Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert( "ERC3525: transfer to non ERC3525Receiver"); } else { // solhint-disable-next-line assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from_ address representing the previous owner of the given token ID * @param to_ target address that will receive the tokens * @param tokenId_ uint256 ID of the token to be transferred * @param data_ bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from_, address to_, uint256 tokenId_, bytes memory data_ ) private returns (bool) { if (to_.isContract() && IERC165(to_).supportsInterface(type(IERC721Receiver).interfaceId)) { try IERC721Receiver(to_).onERC721Received(_msgSender(), from_, tokenId_, data_) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver"); } else { // solhint-disable-next-line assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /* solhint-disable */ function _beforeValueTransfer( address from_, address to_, uint256 fromTokenId_, uint256 toTokenId_, uint256 slot_, uint256 value_ ) internal virtual {} function _afterValueTransfer( address from_, address to_, uint256 fromTokenId_, uint256 toTokenId_, uint256 slot_, uint256 value_ ) internal virtual {} /* solhint-enable */ function _setMetadataDescriptor(address metadataDescriptor_) internal virtual { metadataDescriptor = IERC3525MetadataDescriptor(metadataDescriptor_); emit SetMetadataDescriptor(metadataDescriptor_); } function _createOriginalTokenId() internal virtual returns (uint256) { _tokenIdGenerator.increment(); return _tokenIdGenerator.current(); } function _createDerivedTokenId(uint256 fromTokenId_) internal virtual returns (uint256) { fromTokenId_; return _createOriginalTokenId(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC3525.sol"; import "./IERC721Metadata.sol"; /** * @title ERC-3525 Semi-Fungible Token Standard, optional extension for metadata * @dev Interfaces for any contract that wants to support query of the Uniform Resource Identifier * (URI) for the ERC3525 contract as well as a specified slot. * Because of the higher reliability of data stored in smart contracts compared to data stored in * centralized systems, it is recommended that metadata, including `contractURI`, `slotURI` and * `tokenURI`, be directly returned in JSON format, instead of being returned with a url pointing * to any resource stored in a centralized system. * See https://eips.ethereum.org/EIPS/eip-3525 * Note: the ERC-165 identifier for this interface is 0xe1600902. */ interface IERC3525Metadata is IERC3525, IERC721Metadata { /** * @notice Returns the Uniform Resource Identifier (URI) for the current ERC3525 contract. * @dev This function SHOULD return the URI for this contract in JSON format, starting with * header `data:application/json;`. * See https://eips.ethereum.org/EIPS/eip-3525 for the JSON schema for contract URI. * @return The JSON formatted URI of the current ERC3525 contract */ function contractURI() external view returns (string memory); /** * @notice Returns the Uniform Resource Identifier (URI) for the specified slot. * @dev This function SHOULD return the URI for `_slot` in JSON format, starting with header * `data:application/json;`. * See https://eips.ethereum.org/EIPS/eip-3525 for the JSON schema for slot URI. * @return The JSON formatted URI of `_slot` */ function slotURI(uint256 _slot) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 * Note: the ERC-165 identifier for this interface is 0x780e9d63. */ interface IERC721Enumerable is IERC721 { /** * @notice Count NFTs tracked by this contract * @return A count of valid NFTs tracked by this contract, where each one of * them has an assigned and queryable owner not equal to the zero address */ function totalSupply() external view returns (uint256); /** * @notice Enumerate valid NFTs * @dev Throws if `_index` >= `totalSupply()`. * @param _index A counter less than `totalSupply()` * @return The token identifier for the `_index`th NFT, * (sort order not specified) */ function tokenByIndex(uint256 _index) external view returns (uint256); /** * @notice Enumerate NFTs assigned to an owner * @dev Throws if `_index` >= `balanceOf(_owner)` or if * `_owner` is the zero address, representing invalid NFTs. * @param _owner An address where we are interested in NFTs owned by them * @param _index A counter less than `balanceOf(_owner)` * @return The token identifier for the `_index`th NFT assigned to `_owner`, * (sort order not specified) */ function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 * Note: the ERC-165 identifier for this interface is 0x5b5e139f. */ interface IERC721Metadata is IERC721 { /** * @notice A descriptive name for a collection of NFTs in this contract */ function name() external view returns (string memory); /** * @notice An abbreviated name for NFTs in this contract */ function symbol() external view returns (string memory); /** * @notice A distinct Uniform Resource Identifier (URI) for a given asset. * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC * 3986. The URI may point to a JSON file that conforms to the "ERC721 * Metadata JSON Schema". */ function tokenURI(uint256 _tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "./IERC721.sol"; /** * @title ERC-3525 Semi-Fungible Token Standard * @dev See https://eips.ethereum.org/EIPS/eip-3525 * Note: the ERC-165 identifier for this interface is 0xc97ae3d5. */ interface IERC3525 is IERC165, IERC721 { /** * @dev MUST emit when value of a token is transferred to another token with the same slot, * including zero value transfers (_value == 0) as well as transfers when tokens are created * (`_fromTokenId` == 0) or destroyed (`_toTokenId` == 0). * @param _fromTokenId The token id to transfer value from * @param _toTokenId The token id to transfer value to * @param _value The transferred value */ event TransferValue(uint256 indexed _fromTokenId, uint256 indexed _toTokenId, uint256 _value); /** * @dev MUST emits when the approval value of a token is set or changed. * @param _tokenId The token to approve * @param _operator The operator to approve for * @param _value The maximum value that `_operator` is allowed to manage */ event ApprovalValue(uint256 indexed _tokenId, address indexed _operator, uint256 _value); /** * @dev MUST emit when the slot of a token is set or changed. * @param _tokenId The token of which slot is set or changed * @param _oldSlot The previous slot of the token * @param _newSlot The updated slot of the token */ event SlotChanged(uint256 indexed _tokenId, uint256 indexed _oldSlot, uint256 indexed _newSlot); /** * @notice Get the number of decimals the token uses for value - e.g. 6, means the user * representation of the value of a token can be calculated by dividing it by 1,000,000. * Considering the compatibility with third-party wallets, this function is defined as * `valueDecimals()` instead of `decimals()` to avoid conflict with ERC20 tokens. * @return The number of decimals for value */ function valueDecimals() external view returns (uint8); /** * @notice Get the value of a token. * @param _tokenId The token for which to query the balance * @return The value of `_tokenId` */ function balanceOf(uint256 _tokenId) external view returns (uint256); /** * @notice Get the slot of a token. * @param _tokenId The identifier for a token * @return The slot of the token */ function slotOf(uint256 _tokenId) external view returns (uint256); /** * @notice Allow an operator to manage the value of a token, up to the `_value` amount. * @dev MUST revert unless caller is the current owner, an authorized operator, or the approved * address for `_tokenId`. * MUST emit ApprovalValue event. * @param _tokenId The token to approve * @param _operator The operator to be approved * @param _value The maximum value of `_toTokenId` that `_operator` is allowed to manage */ function approve( uint256 _tokenId, address _operator, uint256 _value ) external payable; /** * @notice Get the maximum value of a token that an operator is allowed to manage. * @param _tokenId The token for which to query the allowance * @param _operator The address of an operator * @return The current approval value of `_tokenId` that `_operator` is allowed to manage */ function allowance(uint256 _tokenId, address _operator) external view returns (uint256); /** * @notice Transfer value from a specified token to another specified token with the same slot. * @dev Caller MUST be the current owner, an authorized operator or an operator who has been * approved the whole `_fromTokenId` or part of it. * MUST revert if `_fromTokenId` or `_toTokenId` is zero token id or does not exist. * MUST revert if slots of `_fromTokenId` and `_toTokenId` do not match. * MUST revert if `_value` exceeds the balance of `_fromTokenId` or its allowance to the * operator. * MUST emit `TransferValue` event. * @param _fromTokenId The token to transfer value from * @param _toTokenId The token to transfer value to * @param _value The transferred value */ function transferFrom( uint256 _fromTokenId, uint256 _toTokenId, uint256 _value ) external payable; /** * @notice Transfer value from a specified token to an address. The caller should confirm that * `_to` is capable of receiving ERC3525 tokens. * @dev This function MUST create a new ERC3525 token with the same slot for `_to` to receive * the transferred value. * MUST revert if `_fromTokenId` is zero token id or does not exist. * MUST revert if `_to` is zero address. * MUST revert if `_value` exceeds the balance of `_fromTokenId` or its allowance to the * operator. * MUST emit `Transfer` and `TransferValue` events. * @param _fromTokenId The token to transfer value from * @param _to The address to transfer value to * @param _value The transferred value * @return ID of the new token created for `_to` which receives the transferred value */ function transferFrom( uint256 _fromTokenId, address _to, uint256 _value ) external payable returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title EIP-3525 token receiver interface * @dev Interface for a smart contract that wants to be informed by EIP-3525 contracts when * receiving values from ANY addresses or EIP-3525 tokens. * Note: the EIP-165 identifier for this interface is 0x009ce20b. */ interface IERC3525Receiver { /** * @notice Handle the receipt of an EIP-3525 token value. * @dev An EIP-3525 smart contract MUST check whether this function is implemented by the * recipient contract, if the recipient contract implements this function, the EIP-3525 * contract MUST call this function after a value transfer (i.e. `transferFrom(uint256, * uint256,uint256,bytes)`). * MUST return 0x009ce20b (i.e. `bytes4(keccak256('onERC3525Received(address,uint256,uint256, * uint256,bytes)'))`) if the transfer is accepted. * MUST revert or return any value other than 0x009ce20b if the transfer is rejected. * @param _operator The address which triggered the transfer * @param _fromTokenId The token id to transfer value from * @param _toTokenId The token id to transfer value to * @param _value The transferred value * @param _data Additional data with no specified format * @return `bytes4(keccak256('onERC3525Received(address,uint256,uint256,uint256,bytes)'))` * unless the transfer is rejected. */ function onERC3525Received(address _operator, uint256 _fromTokenId, uint256 _toTokenId, uint256 _value, bytes calldata _data) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @title ERC-721 Non-Fungible Token Standard * @dev See https://eips.ethereum.org/EIPS/eip-721 * Note: the ERC-165 identifier for this interface is 0x80ac58cd. */ interface IERC721 is IERC165 { /** * @dev This emits when ownership of any NFT changes by any mechanism. * This event emits when NFTs are created (`from` == 0) and destroyed * (`to` == 0). Exception: during contract creation, any number of NFTs * may be created and assigned without emitting Transfer. At the time of * any transfer, the approved address for that NFT (if any) is reset to none. */ event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); /** * @dev This emits when the approved address for an NFT is changed or * reaffirmed. The zero address indicates there is no approved address. * When a Transfer event emits, this also indicates that the approved * address for that NFT (if any) is reset to none. */ event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); /** * @dev This emits when an operator is enabled or disabled for an owner. * The operator can manage all NFTs of the owner. */ event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); /** * @notice Count all NFTs assigned to an owner * @dev NFTs assigned to the zero address are considered invalid, and this * function throws for queries about the zero address. * @param _owner An address for whom to query the balance * @return The number of NFTs owned by `_owner`, possibly zero */ function balanceOf(address _owner) external view returns (uint256); /** * @notice Find the owner of an NFT * @dev NFTs assigned to zero address are considered invalid, and queries * about them do throw. * @param _tokenId The identifier for an NFT * @return The address of the owner of the NFT */ function ownerOf(uint256 _tokenId) external view returns (address); /** * @notice Transfers the ownership of an NFT from one address to another address * @dev Throws unless `msg.sender` is the current owner, an authorized * operator, or the approved address for this NFT. Throws if `_from` is * not the current owner. Throws if `_to` is the zero address. Throws if * `_tokenId` is not a valid NFT. When transfer is complete, this function * checks if `_to` is a smart contract (code size > 0). If so, it calls * `onERC721Received` on `_to` and throws if the return value is not * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. * @param _from The current owner of the NFT * @param _to The new owner * @param _tokenId The NFT to transfer * @param data Additional data with no specified format, sent in call to `_to` */ function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable; /** * @notice Transfers the ownership of an NFT from one address to another address * @dev This works identically to the other function with an extra data parameter, * except this function just sets data to "". * @param _from The current owner of the NFT * @param _to The new owner * @param _tokenId The NFT to transfer */ function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; /** * @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE * TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE * THEY MAY BE PERMANENTLY LOST * @dev Throws unless `msg.sender` is the current owner, an authorized * operator, or the approved address for this NFT. Throws if `_from` is * not the current owner. Throws if `_to` is the zero address. Throws if * `_tokenId` is not a valid NFT. * @param _from The current owner of the NFT * @param _to The new owner * @param _tokenId The NFT to transfer */ function transferFrom(address _from, address _to, uint256 _tokenId) external payable; /** * @notice Change or reaffirm the approved address for an NFT * @dev The zero address indicates there is no approved address. * Throws unless `msg.sender` is the current NFT owner, or an authorized * operator of the current owner. * @param _approved The new approved NFT controller * @param _tokenId The NFT to approve */ function approve(address _approved, uint256 _tokenId) external payable; /** * @notice Enable or disable approval for a third party ("operator") to manage * all of `msg.sender`'s assets * @dev Emits the ApprovalForAll event. The contract MUST allow * multiple operators per owner. * @param _operator Address to add to the set of authorized operators * @param _approved True if the operator is approved, false to revoke approval */ function setApprovalForAll(address _operator, bool _approved) external; /** * @notice Get the approved address for a single NFT * @dev Throws if `_tokenId` is not a valid NFT. * @param _tokenId The NFT to find the approved address for * @return The approved address for this NFT, or the zero address if there is none */ function getApproved(uint256 _tokenId) external view returns (address); /** * @notice Query if an address is an authorized operator for another address * @param _owner The address that owns the NFTs * @param _operator The address that acts on behalf of the owner * @return True if `_operator` is an approved operator for `_owner`, false otherwise */ function isApprovedForAll(address _owner, address _operator) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers from ERC721 asset contracts. * Note: the ERC-165 identifier for this interface is 0x150b7a02. */ interface IERC721Receiver { /** * @notice Handle the receipt of an NFT * @dev The ERC721 smart contract calls this function on the recipient * after a `transfer`. This function MAY throw to revert and reject the * transfer. Return of other than the magic value MUST result in the * transaction being reverted. * Note: the 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(keccak256("onERC721Received(address,address,uint256,bytes)"))` * unless throwing */ function onERC721Received( address _operator, address _from, uint256 _tokenId, bytes calldata _data ) external returns(bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IERC3525MetadataDescriptor { function constructContractURI() external view returns (string memory); function constructSlotURI(uint256 slot) external view returns (string memory); function constructTokenURI(uint256 tokenId) external view returns (string memory); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_operator","type":"address"},{"indexed":false,"internalType":"bool","name":"_approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_operator","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"ApprovalValue","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"metadataDescriptor","type":"address"}],"name":"SetMetadataDescriptor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_oldSlot","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_newSlot","type":"uint256"}],"name":"SlotChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_toTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"TransferValue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"operator_","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"blockId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokenCountLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"operator_","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataDescriptor","outputs":[{"internalType":"contract IERC3525MetadataDescriptor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"mintToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"mintValue","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"queryId","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator_","type":"address"},{"internalType":"bool","name":"approved_","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"setTokenCountLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"slotOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot_","type":"uint256"}],"name":"slotURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index_","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"uint256","name":"index_","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"fromTokenId_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fromTokenId_","type":"uint256"},{"internalType":"uint256","name":"toTokenId_","type":"uint256"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"valueDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50604051806040016040528060128152602001711313d3d5185113d1c814185cdcc810d85c9960721b815250604051806040016040528060048152602001631310511560e21b815250600282600090816200006d9190620001ca565b5060016200007c8382620001ca565b506002805460ff191660ff9290921691909117905550620000a69050620000a03390565b620000d3565b6009805462ffffff60a01b19169055600a80546001600160a01b031916331790556103e8600d5562000296565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200015057607f821691505b6020821081036200017157634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001c557600081815260208120601f850160051c81016020861015620001a05750805b601f850160051c820191505b81811015620001c157828155600101620001ac565b5050505b505050565b81516001600160401b03811115620001e657620001e662000125565b620001fe81620001f784546200013b565b8462000177565b602080601f8311600181146200023657600084156200021d5750858301515b600019600386901b1c1916600185901b178555620001c1565b600085815260208120601f198616915b82811015620002675788860151825594840194600190910190840162000246565b5085821015620002865787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b613ad380620002a66000396000f3fe6080604052600436106102465760003560e01c80636352211e1161013957806395d89b41116100b6578063e345e0bc1161007a578063e345e0bc14610630578063e8a3d48514610650578063e985e9c514610665578063f2fde38b146106b2578063f7b6feab146106d2578063f7dba4d51461070257600080fd5b806395d89b41146105a85780639cc7f708146105bd578063a22cb465146105dd578063b88d4fde146105fd578063c87b56dd1461061057600080fd5b80637ac3c02f116100fd5780637ac3c02f14610524578063840f7113146105425780638456cb59146105625780638cb0a511146105775780638da5cb5b1461058a57600080fd5b80636352211e1461049a5780636c19e783146104ba57806370a08231146104da578063715018a6146104fa5780637789a00c1461050f57600080fd5b8063263f3e7e116101c757806342842e0e1161018b57806342842e0e146104155780634f6ccce71461042857806352c18f861461044857806355f804b31461045b5780635c975abb1461047b57600080fd5b8063263f3e7e1461038b5780632f745c59146103ab578063310ed7f0146103cb5780633e7e8669146103de5780633f4ba83a1461040057600080fd5b80630f485c021161020e5780630f485c021461030f578063168162d21461033057806318160ddd146103435780631d3e8c401461035857806323b872dd1461037857600080fd5b806301ffc9a71461024b57806306fdde0314610280578063081812fc146102a2578063095ea7b3146102da57806309c3dd87146102ef575b600080fd5b34801561025757600080fd5b5061026b61026636600461307e565b610738565b60405190151581526020015b60405180910390f35b34801561028c57600080fd5b506102956107db565b60405161027791906130f3565b3480156102ae57600080fd5b506102c26102bd366004613106565b61086d565b6040516001600160a01b039091168152602001610277565b6102ed6102e8366004613136565b6108bf565b005b3480156102fb57600080fd5b5061029561030a366004613106565b61094d565b61032261031d366004613160565b610a32565b604051908152602001610277565b6102ed61033e3660046131a6565b610aa8565b34801561034f57600080fd5b50600554610322565b34801561036457600080fd5b506102ed610373366004613106565b610c76565b6102ed610386366004613209565b610c83565b34801561039757600080fd5b506103226103a6366004613106565b610cbf565b3480156103b757600080fd5b506103226103c6366004613136565b610d07565b6102ed6103d9366004613235565b610da8565b3480156103ea57600080fd5b5060025460405160ff9091168152602001610277565b34801561040c57600080fd5b506102ed610dbb565b6102ed610423366004613209565b610dcd565b34801561043457600080fd5b50610322610443366004613106565b610e09565b6102ed610456366004613261565b610e9a565b34801561046757600080fd5b506102ed6104763660046132ce565b610fff565b34801561048757600080fd5b50600954600160a01b900460ff1661026b565b3480156104a657600080fd5b506102c26104b5366004613106565b611014565b3480156104c657600080fd5b506102ed6104d5366004613340565b6110b0565b3480156104e657600080fd5b506103226104f5366004613340565b6110da565b34801561050657600080fd5b506102ed611162565b34801561051b57600080fd5b50600d54610322565b34801561053057600080fd5b50600a546001600160a01b03166102c2565b34801561054e57600080fd5b506008546102c2906001600160a01b031681565b34801561056e57600080fd5b506102ed611174565b6102ed610585366004613160565b611184565b34801561059657600080fd5b506009546001600160a01b03166102c2565b3480156105b457600080fd5b5061029561120b565b3480156105c957600080fd5b506103226105d8366004613106565b61121a565b3480156105e957600080fd5b506102ed6105f8366004613369565b611262565b6102ed61060b36600461340f565b611271565b34801561061c57600080fd5b5061029561062b366004613106565b6112ae565b34801561063c57600080fd5b5061032261064b3660046134ba565b611340565b34801561065c57600080fd5b50610295611374565b34801561067157600080fd5b5061026b6106803660046134e6565b6001600160a01b0391821660009081526007602090815260408083209390941682526002909201909152205460ff1690565b3480156106be57600080fd5b506102ed6106cd366004613340565b611461565b3480156106de57600080fd5b5061026b6106ed366004613106565b6000908152600b602052604090205460ff1690565b34801561070e57600080fd5b506102ed61071d366004613106565b6000908152600b60205260409020805460ff19166001179055565b60006001600160e01b031982166301ffc9a760e01b148061076957506001600160e01b03198216630354d60560e61b145b8061078457506001600160e01b031982166380ac58cd60e01b145b8061079f57506001600160e01b031982166370b0048160e11b145b806107ba57506001600160e01b0319821663780e9d6360e01b145b806107d557506001600160e01b03198216635b5e139f60e01b145b92915050565b6060600080546107ea90613510565b80601f016020809104026020016040519081016040528092919081815260200182805461081690613510565b80156108635780601f1061083857610100808354040283529160200191610863565b820191906000526020600020905b81548152906001019060200180831161084657829003601f168201915b5050505050905090565b6000610878826114da565b60008281526006602052604090205460058054909190811061089c5761089c61354a565b60009182526020909120600460069092020101546001600160a01b031692915050565b60006108ca82611014565b9050806001600160a01b0316836001600160a01b0316036109065760405162461bcd60e51b81526004016108fd90613560565b60405180910390fd5b336001600160a01b038216148061092257506109228133610680565b61093e5760405162461bcd60e51b81526004016108fd906135a2565b610948838361152b565b505050565b606060006109596115c2565b6008549091506001600160a01b03166109b957600081511161098a5760405180602001604052806000815250610a2b565b80610994846115d1565b6040516020016109a59291906135ff565b604051602081830303815290604052610a2b565b600854604051633601bfc560e11b8152600481018590526001600160a01b0390911690636c037f8a906024015b600060405180830381865afa158015610a03573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a2b919081019061363f565b9392505050565b6000610a3c6116d2565b600954600160b01b900460ff16610a955760405162461bcd60e51b815260206004820152601d60248201527f56616c756520646f6573206e6f7420616c6c6f77207472616e7366657200000060448201526064016108fd565b610aa084848461171f565b949350505050565b610ab06116d2565b844210610af15760405162461bcd60e51b815260206004820152600f60248201526e22bc3834b932b2103b37bab1b432b960891b60448201526064016108fd565b600d5460055410610b2f5760405162461bcd60e51b815260206004820152600860248201526714dbdb19081bdd5d60c21b60448201526064016108fd565b610b38336110da565b15610b765760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e481b5a5b9d195960921b60448201526064016108fd565b6000878152600b602052604090205460ff1615610bc45760405162461bcd60e51b815260206004820152600c60248201526b111d5c1b1a58d85d19481a5960a21b60448201526064016108fd565b6001600160a01b0384163314610c0c5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b21037bbb732b960991b60448201526064016108fd565b610c486040518060a0016040528089815260200160008152602001888152602001878152602001866001600160a01b0316815250848484611759565b610c5433600188611818565b50505060009485525050600b602052505060409020805460ff19166001179055565b610c7e611831565b600d55565b610c8b6116d2565b600954600160a81b900460ff16610cb45760405162461bcd60e51b81526004016108fd906136b6565b61094883838361188b565b6000610cca826114da565b600082815260066020526040902054600580549091908110610cee57610cee61354a565b9060005260206000209060060201600101549050919050565b6000610d12836110da565b8210610d6b5760405162461bcd60e51b815260206004820152602260248201527f455243333532353a206f776e657220696e646578206f7574206f6620626f756e604482015261647360f01b60648201526084016108fd565b6001600160a01b0383166000908152600760205260409020805483908110610d9557610d9561354a565b9060005260206000200154905092915050565b610db06116d2565b6109488383836118bc565b610dc3611831565b610dcb6118d2565b565b610dd56116d2565b600954600160a81b900460ff16610dfe5760405162461bcd60e51b81526004016108fd906136b6565b610948838383611927565b6000610e1460055490565b8210610e6e5760405162461bcd60e51b815260206004820152602360248201527f455243333532353a20676c6f62616c20696e646578206f7574206f6620626f756044820152626e647360e81b60648201526084016108fd565b60058281548110610e8157610e8161354a565b9060005260206000209060060201600001549050919050565b610ea26116d2565b844210610ee35760405162461bcd60e51b815260206004820152600f60248201526e22bc3834b932b2103b37bab1b432b960891b60448201526064016108fd565b6000888152600b602052604090205460ff1615610f315760405162461bcd60e51b815260206004820152600c60248201526b111d5c1b1a58d85d19481a5960a21b60448201526064016108fd565b6001600160a01b0384163314610f795760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b21037bbb732b960991b60448201526064016108fd565b60008611610fba5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b60448201526064016108fd565b610ff56040518060a001604052808a8152602001898152602001888152602001878152602001866001600160a01b0316815250848484611759565b610c548787611942565b611007611831565b600c610948828483613733565b600061101f826114da565b6000828152600660205260409020546005805490919081106110435761104361354a565b60009182526020909120600360069092020101546001600160a01b03169050806110ab5760405162461bcd60e51b8152602060048201526019602482015278115490cccd4c8d4e881a5b9d985b1a59081d1bdad95b881251603a1b60448201526064016108fd565b919050565b6110b8611831565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b0382166111465760405162461bcd60e51b815260206004820152602b60248201527f455243333532353a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b60648201526084016108fd565b506001600160a01b031660009081526007602052604090205490565b61116a611831565b610dcb6000611974565b61117c611831565b610dcb6119c6565b600061118f84611014565b9050806001600160a01b0316836001600160a01b0316036111c25760405162461bcd60e51b81526004016108fd90613560565b336001600160a01b03821614806111de57506111de8133610680565b6111fa5760405162461bcd60e51b81526004016108fd906135a2565b611205848484611a09565b50505050565b6060600180546107ea90613510565b6000611225826114da565b6000828152600660205260409020546005805490919081106112495761124961354a565b9060005260206000209060060201600201549050919050565b61126d338383611b41565b5050565b6112796116d2565b600954600160a81b900460ff166112a25760405162461bcd60e51b81526004016108fd906136b6565b61120584848484611c0b565b60606112b9826114da565b60006112c36115c2565b6008549091506001600160a01b031661130f5760008151116112f45760405180602001604052806000815250610a2b565b806112fe846115d1565b6040516020016109a59291906137f3565b6008546040516344a5a61760e11b8152600481018590526001600160a01b039091169063894b4c2e906024016109e6565b600061134b836114da565b5060009182526004602090815260408084206001600160a01b0393909316845291905290205490565b606060006113806115c2565b6008549091506001600160a01b03166113e05760008151116113b1576040518060200160405280600081525061145b565b806113bb30611c3d565b6040516020016113cc929190613822565b60405160208183030381529060405261145b565b600860009054906101000a90046001600160a01b03166001600160a01b031663725fa09c6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261145b919081019061363f565b91505090565b611469611831565b6001600160a01b0381166114ce5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108fd565b6114d781611974565b50565b6114e381611c53565b6114d75760405162461bcd60e51b8152602060048201526019602482015278115490cccd4c8d4e881a5b9d985b1a59081d1bdad95b881251603a1b60448201526064016108fd565b60008181526006602052604090205460058054849290811061154f5761154f61354a565b6000918252602090912060069091020160040180546001600160a01b0319166001600160a01b039283161790558190831661158982611014565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6060600c80546107ea90613510565b6060816000036115f85750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611622578061160c8161387c565b915061161b9050600a836138ab565b91506115fc565b60008167ffffffffffffffff81111561163d5761163d6133a0565b6040519080825280601f01601f191660200182016040528015611667576020820181803683370190505b5090505b8415610aa05761167c6001836138bf565b9150611689600a866138d6565b6116949060306138ea565b60f81b8183815181106116a9576116a961354a565b60200101906001600160f81b031916908160001a9053506116cb600a866138ab565b945061166b565b600954600160a01b900460ff1615610dcb5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016108fd565b600061172c338584611c9f565b600061173785611d2f565b905061174e848261174788610cbf565b6000611d39565b610aa0858285611e5e565b6000600161176686612109565b6040805160008152602081018083529290925260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156117b4573d6000803e3d6000fd5b5050604051601f190151600a549092506001600160a01b0380841691161490506118115760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b60448201526064016108fd565b5050505050565b60008061182361224d565b9050610aa085828686611d39565b6009546001600160a01b03163314610dcb5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108fd565b6118953382612264565b6118b15760405162461bcd60e51b81526004016108fd90613902565b6109488383836122cc565b6118c7338483611c9f565b610948838383611e5e565b6118da61242d565b6009805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b61094883838360405180602001604052806000815250611271565b61194b826114da565b600061195683611014565b9050600061196384610cbf565b905061196f8484612485565b611205565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6119ce6116d2565b6009805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861190a3390565b6001600160a01b038216611a725760405162461bcd60e51b815260206004820152602a60248201527f455243333532353a20617070726f76652076616c756520746f20746865207a65604482015269726f206164647265737360b01b60648201526084016108fd565b611a7c828461250a565b611ae257600083815260066020526040902054600580549091908110611aa457611aa461354a565b60009182526020808320600692909202909101600501805460018101825590835291200180546001600160a01b0319166001600160a01b0384161790555b60008381526004602090815260408083206001600160a01b038616808552908352928190208490555183815285917f621b050de0ad08b51d19b48b3e6df75348c4de6bdd93e81b252ca62e28265b1b91015b60405180910390a3505050565b816001600160a01b0316836001600160a01b031603611ba25760405162461bcd60e51b815260206004820152601a60248201527f455243333532353a20617070726f766520746f2063616c6c657200000000000060448201526064016108fd565b6001600160a01b0383811660008181526007602090815260408083209487168084526002909501825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101611b34565b611c153383612264565b611c315760405162461bcd60e51b81526004016108fd90613902565b611205848484846125dd565b60606107d56001600160a01b0383166014612650565b600554600090158015906107d55750600082815260066020526040902054600580548492908110611c8657611c8661354a565b9060005260206000209060060201600001541492915050565b6000611cab8385611340565b9050611cb78484612264565b158015611cc657506000198114155b156112055781811015611d1b5760405162461bcd60e51b815260206004820152601f60248201527f455243333532353a20696e73756666696369656e7420616c6c6f77616e63650060448201526064016108fd565b6112058385611d2a85856138bf565b611a09565b60006107d561224d565b6001600160a01b038416611d995760405162461bcd60e51b815260206004820152602160248201527f455243333532353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b60648201526084016108fd565b82600003611df35760405162461bcd60e51b815260206004820152602160248201527f455243333532353a2063616e6e6f74206d696e74207a65726f20746f6b656e496044820152601960fa1b60648201526084016108fd565b611dfc83611c53565b15611e495760405162461bcd60e51b815260206004820152601d60248201527f455243333532353a20746f6b656e20616c7265616479206d696e74656400000060448201526064016108fd565b611e548484846127ec565b61196f8382612485565b611e6783611c53565b611ec35760405162461bcd60e51b815260206004820152602760248201527f455243333532353a207472616e736665722066726f6d20696e76616c696420746044820152661bdad95b88125160ca1b60648201526084016108fd565b611ecc82611c53565b611f265760405162461bcd60e51b815260206004820152602560248201527f455243333532353a207472616e7366657220746f20696e76616c696420746f6b604482015264195b88125160da1b60648201526084016108fd565b600083815260066020526040812054600580549091908110611f4a57611f4a61354a565b9060005260206000209060060201905060006005600660008681526020019081526020016000205481548110611f8257611f8261354a565b906000526020600020906006020190508282600201541015611ff95760405162461bcd60e51b815260206004820152602a60248201527f455243333532353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b60648201526084016108fd565b80600101548260010154146120675760405162461bcd60e51b815260206004820152602e60248201527f455243333532353a207472616e7366657220746f20746f6b656e20776974682060448201526d191a5999995c995b9d081cdb1bdd60921b60648201526084016108fd565b8282600201600082825461207b91906138bf565b925050819055508281600201600082825461209691906138ea565b9091555050604051838152849086907f0b2aac84f3ec956911fd78eae5311062972ff949f38412e8da39069d9f068cc69060200160405180910390a36120ed858585604051806020016040528060008152506128b2565b6118115760405162461bcd60e51b81526004016108fd90613954565b6000612208604080518082018252600d81526c04c4f4f5461444f47204461707609c1b6020918201528151808301835260018152603160f81b9082015281517fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472818301527f7adf56923e686bb1b093759a744659a5bc83da4e64912930cd2c64f30774ef92818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201527ff2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a55860c0808301919091528351808303909101815260e0909101909252815191012090565b61221183612a36565b60405161190160f01b6020820152602281019290925260428201526062015b604051602081830303815290604052805190602001209050919050565b600061225d600380546001019055565b5060035490565b600061226f826114da565b600061227a83611014565b9050806001600160a01b0316846001600160a01b031614806122a157506122a18185610680565b80610aa05750836001600160a01b03166122ba8461086d565b6001600160a01b031614949350505050565b826001600160a01b03166122df82611014565b6001600160a01b0316146123415760405162461bcd60e51b8152602060048201526024808201527f455243333532353a207472616e736665722066726f6d20696e76616c6964206f6044820152633bb732b960e11b60648201526084016108fd565b6001600160a01b0382166123a55760405162461bcd60e51b815260206004820152602560248201527f455243333532353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b60648201526084016108fd565b60006123b082610cbf565b905060006123bd8361121a565b90506123ca60008461152b565b6123d383612ab1565b6123dd8584612b4d565b6123e78484612c6e565b82846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611811565b600954600160a01b900460ff16610dcb5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016108fd565b505050505050565b6000828152600660205260409020546005805483929081106124a9576124a961354a565b906000526020600020906006020160020160008282546124c991906138ea565b909155505060405181815282906000907f0b2aac84f3ec956911fd78eae5311062972ff949f38412e8da39069d9f068cc69060200160405180910390a35050565b60008181526006602052604081205460058054839290811061252e5761252e61354a565b6000918252602082206005600690920201015491505b818110156125d257600084815260066020526040902054600580546001600160a01b038816929081106125795761257961354a565b9060005260206000209060060201600501828154811061259b5761259b61354a565b6000918252602090912001546001600160a01b0316036125c0576001925050506107d5565b806125ca8161387c565b915050612544565b506000949350505050565b6125e88484846122cc565b6125f484848484612cf7565b6112055760405162461bcd60e51b815260206004820152602760248201527f455243333532353a207472616e7366657220746f206e6f6e204552433732315260448201526632b1b2b4bb32b960c91b60648201526084016108fd565b6060600061265f83600261399c565b61266a9060026138ea565b67ffffffffffffffff811115612682576126826133a0565b6040519080825280601f01601f1916602001820160405280156126ac576020820181803683370190505b509050600360fc1b816000815181106126c7576126c761354a565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106126f6576126f661354a565b60200101906001600160f81b031916908160001a905350600061271a84600261399c565b6127259060016138ea565b90505b600181111561279d576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106127595761275961354a565b1a60f81b82828151811061276f5761276f61354a565b60200101906001600160f81b031916908160001a90535060049490941c93612796816139bb565b9050612728565b508315610a2b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108fd565b6040805160c081018252838152602080820184905260008284018190526001600160a01b038716606084015260808301819052835181815291820190935260a0820152905061283a81612ea4565b6128448484612c6e565b60405183906001600160a01b038616906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4816000847fe4f48c240d3b994948aa54f3e2f5fca59263dfe1d52b6e4cf39a5d249b5ccb6560405160405180910390a450505050565b6000806128be85611014565b90506001600160a01b0381163b1515801561294257506040516301ffc9a760e01b8152629ce20b60e01b60048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa15801561291e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061294291906139d2565b15612a2c57604051629ce20b60e01b81526001600160a01b03821690629ce20b906129799033908a908a908a908a906004016139ef565b6020604051808303816000875af19250505080156129b4575060408051601f3d908101601f191682019092526129b191810190613a2d565b60015b612a11573d8080156129e2576040519150601f19603f3d011682016040523d82523d6000602084013e6129e7565b606091505b508051600003612a095760405162461bcd60e51b81526004016108fd90613954565b805181602001fd5b6001600160e01b031916629ce20b60e01b149150610aa09050565b6001915050610aa0565b8051602080830151604080850151606086015160808701519251600096612230967f4bd317336ea30fdfa31168cda381dacdf9ed1dd92eda94108d28629b6cf9b8c7969195919493920195865260208601949094526040850192909252606084015260808301526001600160a01b031660a082015260c00190565b600081815260066020526040812054600580549091908110612ad557612ad561354a565b600091825260208220600560069092020190810154909250905b81811015611205576000836005018281548110612b0e57612b0e61354a565b60009182526020808320909101548783526004825260408084206001600160a01b03909216845291528120555080612b458161387c565b915050612aef565b600081815260066020526040812054600580549091908110612b7157612b7161354a565b6000918252602080832060069290920290910160030180546001600160a01b0319166001600160a01b0394851617905591841681526007909152604081208054909190612bc0906001906138bf565b90506000826000018281548110612bd957612bd961354a565b90600052602060002001549050600083600101600086815260200190815260200160002054905081846000018281548110612c1657612c1661354a565b60009182526020808320909101929092558381526001860190915260408082208390558682528120558354849080612c5057612c50613a4a565b60019003818190600052602060002001600090559055505050505050565b600081815260066020526040902054600580548492908110612c9257612c9261354a565b6000918252602080832060069290920290910160030180546001600160a01b0319166001600160a01b03948516179055939091168152600780845260408083208054858552600182810188529285208190559286529082018155825292902090910155565b60006001600160a01b0384163b15158015612d7c57506040516301ffc9a760e01b8152630a85bd0160e11b60048201526001600160a01b038516906301ffc9a790602401602060405180830381865afa158015612d58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d7c91906139d2565b15612e9c57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612db3903390899088908890600401613a60565b6020604051808303816000875af1925050508015612dee575060408051601f3d908101601f19168201909252612deb91810190613a2d565b60015b612e82573d808015612e1c576040519150601f19603f3d011682016040523d82523d6000602084013e612e21565b606091505b508051600003612a095760405162461bcd60e51b815260206004820152602660248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201526531b2b4bb32b960d11b60648201526084016108fd565b6001600160e01b031916630a85bd0160e11b149050610aa0565b506001610aa0565b600580548251600090815260066020818152604080842085905560018501865594909252845192027f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db08101928355818501517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db1820155928401517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db284015560608401517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db3840180546001600160a01b039283166001600160a01b03199182161790915560808601517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db48601805491909316911617905560a084015180518594611205937f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db5909101920190828054828255906000526020600020908101928215613043579160200282015b8281111561304357825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061300e565b5061304f929150613053565b5090565b5b8082111561304f5760008155600101613054565b6001600160e01b0319811681146114d757600080fd5b60006020828403121561309057600080fd5b8135610a2b81613068565b60005b838110156130b657818101518382015260200161309e565b838111156112055750506000910152565b600081518084526130df81602086016020860161309b565b601f01601f19169290920160200192915050565b602081526000610a2b60208301846130c7565b60006020828403121561311857600080fd5b5035919050565b80356001600160a01b03811681146110ab57600080fd5b6000806040838503121561314957600080fd5b6131528361311f565b946020939093013593505050565b60008060006060848603121561317557600080fd5b833592506131856020850161311f565b9150604084013590509250925092565b803560ff811681146110ab57600080fd5b600080600080600080600060e0888a0312156131c157600080fd5b8735965060208801359550604088013594506131df6060890161311f565b93506131ed60808901613195565b925060a0880135915060c0880135905092959891949750929550565b60008060006060848603121561321e57600080fd5b6132278461311f565b92506131856020850161311f565b60008060006060848603121561324a57600080fd5b505081359360208301359350604090920135919050565b600080600080600080600080610100898b03121561327e57600080fd5b883597506020890135965060408901359550606089013594506132a360808a0161311f565b93506132b160a08a01613195565b925060c0890135915060e089013590509295985092959890939650565b600080602083850312156132e157600080fd5b823567ffffffffffffffff808211156132f957600080fd5b818501915085601f83011261330d57600080fd5b81358181111561331c57600080fd5b86602082850101111561332e57600080fd5b60209290920196919550909350505050565b60006020828403121561335257600080fd5b610a2b8261311f565b80151581146114d757600080fd5b6000806040838503121561337c57600080fd5b6133858361311f565b915060208301356133958161335b565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156133df576133df6133a0565b604052919050565b600067ffffffffffffffff821115613401576134016133a0565b50601f01601f191660200190565b6000806000806080858703121561342557600080fd5b61342e8561311f565b935061343c6020860161311f565b925060408501359150606085013567ffffffffffffffff81111561345f57600080fd5b8501601f8101871361347057600080fd5b803561348361347e826133e7565b6133b6565b81815288602083850101111561349857600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600080604083850312156134cd57600080fd5b823591506134dd6020840161311f565b90509250929050565b600080604083850312156134f957600080fd5b6135028361311f565b91506134dd6020840161311f565b600181811c9082168061352457607f821691505b60208210810361354457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60208082526022908201527f455243333532353a20617070726f76616c20746f2063757272656e74206f776e60408201526132b960f11b606082015260800190565b60208082526039908201527f455243333532353a20617070726f76652063616c6c6572206973206e6f74206f60408201527f776e6572206e6f7220617070726f76656420666f7220616c6c00000000000000606082015260800190565b6000835161361181846020880161309b565b64736c6f742f60d81b908301908152835161363381600584016020880161309b565b01600501949350505050565b60006020828403121561365157600080fd5b815167ffffffffffffffff81111561366857600080fd5b8201601f8101841361367957600080fd5b805161368761347e826133e7565b81815285602083850101111561369c57600080fd5b6136ad82602083016020860161309b565b95945050505050565b6020808252601d908201527f546f6b656e20646f6573206e6f7420616c6c6f77207472616e73666572000000604082015260600190565b601f82111561094857600081815260208120601f850160051c810160208610156137145750805b601f850160051c820191505b8181101561247d57828155600101613720565b67ffffffffffffffff83111561374b5761374b6133a0565b61375f836137598354613510565b836136ed565b6000601f841160018114613793576000851561377b5750838201355b600019600387901b1c1916600186901b178355611811565b600083815260209020601f19861690835b828110156137c457868501358255602094850194600190920191016137a4565b50868210156137e15760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6000835161380581846020880161309b565b83519083019061381981836020880161309b565b01949350505050565b6000835161383481846020880161309b565b68636f6e74726163742f60b81b908301908152835161385a81600984016020880161309b565b01600901949350505050565b634e487b7160e01b600052601160045260246000fd5b60006001820161388e5761388e613866565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826138ba576138ba613895565b500490565b6000828210156138d1576138d1613866565b500390565b6000826138e5576138e5613895565b500690565b600082198211156138fd576138fd613866565b500190565b60208082526032908201527f455243333532353a207472616e736665722063616c6c6572206973206e6f74206040820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b606082015260800190565b60208082526028908201527f455243333532353a207472616e7366657220746f206e6f6e20455243333532356040820152672932b1b2b4bb32b960c11b606082015260800190565b60008160001904831182151516156139b6576139b6613866565b500290565b6000816139ca576139ca613866565b506000190190565b6000602082840312156139e457600080fd5b8151610a2b8161335b565b60018060a01b038616815284602082015283604082015282606082015260a060808201526000613a2260a08301846130c7565b979650505050505050565b600060208284031215613a3f57600080fd5b8151610a2b81613068565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613a93908301846130c7565b969550505050505056fea2646970667358221220e2ad52a24bcfe504f6e72a3537011dff23006983c70992647239373d09abd19664736f6c634300080f0033
Deployed Bytecode
0x6080604052600436106102465760003560e01c80636352211e1161013957806395d89b41116100b6578063e345e0bc1161007a578063e345e0bc14610630578063e8a3d48514610650578063e985e9c514610665578063f2fde38b146106b2578063f7b6feab146106d2578063f7dba4d51461070257600080fd5b806395d89b41146105a85780639cc7f708146105bd578063a22cb465146105dd578063b88d4fde146105fd578063c87b56dd1461061057600080fd5b80637ac3c02f116100fd5780637ac3c02f14610524578063840f7113146105425780638456cb59146105625780638cb0a511146105775780638da5cb5b1461058a57600080fd5b80636352211e1461049a5780636c19e783146104ba57806370a08231146104da578063715018a6146104fa5780637789a00c1461050f57600080fd5b8063263f3e7e116101c757806342842e0e1161018b57806342842e0e146104155780634f6ccce71461042857806352c18f861461044857806355f804b31461045b5780635c975abb1461047b57600080fd5b8063263f3e7e1461038b5780632f745c59146103ab578063310ed7f0146103cb5780633e7e8669146103de5780633f4ba83a1461040057600080fd5b80630f485c021161020e5780630f485c021461030f578063168162d21461033057806318160ddd146103435780631d3e8c401461035857806323b872dd1461037857600080fd5b806301ffc9a71461024b57806306fdde0314610280578063081812fc146102a2578063095ea7b3146102da57806309c3dd87146102ef575b600080fd5b34801561025757600080fd5b5061026b61026636600461307e565b610738565b60405190151581526020015b60405180910390f35b34801561028c57600080fd5b506102956107db565b60405161027791906130f3565b3480156102ae57600080fd5b506102c26102bd366004613106565b61086d565b6040516001600160a01b039091168152602001610277565b6102ed6102e8366004613136565b6108bf565b005b3480156102fb57600080fd5b5061029561030a366004613106565b61094d565b61032261031d366004613160565b610a32565b604051908152602001610277565b6102ed61033e3660046131a6565b610aa8565b34801561034f57600080fd5b50600554610322565b34801561036457600080fd5b506102ed610373366004613106565b610c76565b6102ed610386366004613209565b610c83565b34801561039757600080fd5b506103226103a6366004613106565b610cbf565b3480156103b757600080fd5b506103226103c6366004613136565b610d07565b6102ed6103d9366004613235565b610da8565b3480156103ea57600080fd5b5060025460405160ff9091168152602001610277565b34801561040c57600080fd5b506102ed610dbb565b6102ed610423366004613209565b610dcd565b34801561043457600080fd5b50610322610443366004613106565b610e09565b6102ed610456366004613261565b610e9a565b34801561046757600080fd5b506102ed6104763660046132ce565b610fff565b34801561048757600080fd5b50600954600160a01b900460ff1661026b565b3480156104a657600080fd5b506102c26104b5366004613106565b611014565b3480156104c657600080fd5b506102ed6104d5366004613340565b6110b0565b3480156104e657600080fd5b506103226104f5366004613340565b6110da565b34801561050657600080fd5b506102ed611162565b34801561051b57600080fd5b50600d54610322565b34801561053057600080fd5b50600a546001600160a01b03166102c2565b34801561054e57600080fd5b506008546102c2906001600160a01b031681565b34801561056e57600080fd5b506102ed611174565b6102ed610585366004613160565b611184565b34801561059657600080fd5b506009546001600160a01b03166102c2565b3480156105b457600080fd5b5061029561120b565b3480156105c957600080fd5b506103226105d8366004613106565b61121a565b3480156105e957600080fd5b506102ed6105f8366004613369565b611262565b6102ed61060b36600461340f565b611271565b34801561061c57600080fd5b5061029561062b366004613106565b6112ae565b34801561063c57600080fd5b5061032261064b3660046134ba565b611340565b34801561065c57600080fd5b50610295611374565b34801561067157600080fd5b5061026b6106803660046134e6565b6001600160a01b0391821660009081526007602090815260408083209390941682526002909201909152205460ff1690565b3480156106be57600080fd5b506102ed6106cd366004613340565b611461565b3480156106de57600080fd5b5061026b6106ed366004613106565b6000908152600b602052604090205460ff1690565b34801561070e57600080fd5b506102ed61071d366004613106565b6000908152600b60205260409020805460ff19166001179055565b60006001600160e01b031982166301ffc9a760e01b148061076957506001600160e01b03198216630354d60560e61b145b8061078457506001600160e01b031982166380ac58cd60e01b145b8061079f57506001600160e01b031982166370b0048160e11b145b806107ba57506001600160e01b0319821663780e9d6360e01b145b806107d557506001600160e01b03198216635b5e139f60e01b145b92915050565b6060600080546107ea90613510565b80601f016020809104026020016040519081016040528092919081815260200182805461081690613510565b80156108635780601f1061083857610100808354040283529160200191610863565b820191906000526020600020905b81548152906001019060200180831161084657829003601f168201915b5050505050905090565b6000610878826114da565b60008281526006602052604090205460058054909190811061089c5761089c61354a565b60009182526020909120600460069092020101546001600160a01b031692915050565b60006108ca82611014565b9050806001600160a01b0316836001600160a01b0316036109065760405162461bcd60e51b81526004016108fd90613560565b60405180910390fd5b336001600160a01b038216148061092257506109228133610680565b61093e5760405162461bcd60e51b81526004016108fd906135a2565b610948838361152b565b505050565b606060006109596115c2565b6008549091506001600160a01b03166109b957600081511161098a5760405180602001604052806000815250610a2b565b80610994846115d1565b6040516020016109a59291906135ff565b604051602081830303815290604052610a2b565b600854604051633601bfc560e11b8152600481018590526001600160a01b0390911690636c037f8a906024015b600060405180830381865afa158015610a03573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a2b919081019061363f565b9392505050565b6000610a3c6116d2565b600954600160b01b900460ff16610a955760405162461bcd60e51b815260206004820152601d60248201527f56616c756520646f6573206e6f7420616c6c6f77207472616e7366657200000060448201526064016108fd565b610aa084848461171f565b949350505050565b610ab06116d2565b844210610af15760405162461bcd60e51b815260206004820152600f60248201526e22bc3834b932b2103b37bab1b432b960891b60448201526064016108fd565b600d5460055410610b2f5760405162461bcd60e51b815260206004820152600860248201526714dbdb19081bdd5d60c21b60448201526064016108fd565b610b38336110da565b15610b765760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e481b5a5b9d195960921b60448201526064016108fd565b6000878152600b602052604090205460ff1615610bc45760405162461bcd60e51b815260206004820152600c60248201526b111d5c1b1a58d85d19481a5960a21b60448201526064016108fd565b6001600160a01b0384163314610c0c5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b21037bbb732b960991b60448201526064016108fd565b610c486040518060a0016040528089815260200160008152602001888152602001878152602001866001600160a01b0316815250848484611759565b610c5433600188611818565b50505060009485525050600b602052505060409020805460ff19166001179055565b610c7e611831565b600d55565b610c8b6116d2565b600954600160a81b900460ff16610cb45760405162461bcd60e51b81526004016108fd906136b6565b61094883838361188b565b6000610cca826114da565b600082815260066020526040902054600580549091908110610cee57610cee61354a565b9060005260206000209060060201600101549050919050565b6000610d12836110da565b8210610d6b5760405162461bcd60e51b815260206004820152602260248201527f455243333532353a206f776e657220696e646578206f7574206f6620626f756e604482015261647360f01b60648201526084016108fd565b6001600160a01b0383166000908152600760205260409020805483908110610d9557610d9561354a565b9060005260206000200154905092915050565b610db06116d2565b6109488383836118bc565b610dc3611831565b610dcb6118d2565b565b610dd56116d2565b600954600160a81b900460ff16610dfe5760405162461bcd60e51b81526004016108fd906136b6565b610948838383611927565b6000610e1460055490565b8210610e6e5760405162461bcd60e51b815260206004820152602360248201527f455243333532353a20676c6f62616c20696e646578206f7574206f6620626f756044820152626e647360e81b60648201526084016108fd565b60058281548110610e8157610e8161354a565b9060005260206000209060060201600001549050919050565b610ea26116d2565b844210610ee35760405162461bcd60e51b815260206004820152600f60248201526e22bc3834b932b2103b37bab1b432b960891b60448201526064016108fd565b6000888152600b602052604090205460ff1615610f315760405162461bcd60e51b815260206004820152600c60248201526b111d5c1b1a58d85d19481a5960a21b60448201526064016108fd565b6001600160a01b0384163314610f795760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b21037bbb732b960991b60448201526064016108fd565b60008611610fba5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b60448201526064016108fd565b610ff56040518060a001604052808a8152602001898152602001888152602001878152602001866001600160a01b0316815250848484611759565b610c548787611942565b611007611831565b600c610948828483613733565b600061101f826114da565b6000828152600660205260409020546005805490919081106110435761104361354a565b60009182526020909120600360069092020101546001600160a01b03169050806110ab5760405162461bcd60e51b8152602060048201526019602482015278115490cccd4c8d4e881a5b9d985b1a59081d1bdad95b881251603a1b60448201526064016108fd565b919050565b6110b8611831565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b0382166111465760405162461bcd60e51b815260206004820152602b60248201527f455243333532353a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b60648201526084016108fd565b506001600160a01b031660009081526007602052604090205490565b61116a611831565b610dcb6000611974565b61117c611831565b610dcb6119c6565b600061118f84611014565b9050806001600160a01b0316836001600160a01b0316036111c25760405162461bcd60e51b81526004016108fd90613560565b336001600160a01b03821614806111de57506111de8133610680565b6111fa5760405162461bcd60e51b81526004016108fd906135a2565b611205848484611a09565b50505050565b6060600180546107ea90613510565b6000611225826114da565b6000828152600660205260409020546005805490919081106112495761124961354a565b9060005260206000209060060201600201549050919050565b61126d338383611b41565b5050565b6112796116d2565b600954600160a81b900460ff166112a25760405162461bcd60e51b81526004016108fd906136b6565b61120584848484611c0b565b60606112b9826114da565b60006112c36115c2565b6008549091506001600160a01b031661130f5760008151116112f45760405180602001604052806000815250610a2b565b806112fe846115d1565b6040516020016109a59291906137f3565b6008546040516344a5a61760e11b8152600481018590526001600160a01b039091169063894b4c2e906024016109e6565b600061134b836114da565b5060009182526004602090815260408084206001600160a01b0393909316845291905290205490565b606060006113806115c2565b6008549091506001600160a01b03166113e05760008151116113b1576040518060200160405280600081525061145b565b806113bb30611c3d565b6040516020016113cc929190613822565b60405160208183030381529060405261145b565b600860009054906101000a90046001600160a01b03166001600160a01b031663725fa09c6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261145b919081019061363f565b91505090565b611469611831565b6001600160a01b0381166114ce5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108fd565b6114d781611974565b50565b6114e381611c53565b6114d75760405162461bcd60e51b8152602060048201526019602482015278115490cccd4c8d4e881a5b9d985b1a59081d1bdad95b881251603a1b60448201526064016108fd565b60008181526006602052604090205460058054849290811061154f5761154f61354a565b6000918252602090912060069091020160040180546001600160a01b0319166001600160a01b039283161790558190831661158982611014565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6060600c80546107ea90613510565b6060816000036115f85750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611622578061160c8161387c565b915061161b9050600a836138ab565b91506115fc565b60008167ffffffffffffffff81111561163d5761163d6133a0565b6040519080825280601f01601f191660200182016040528015611667576020820181803683370190505b5090505b8415610aa05761167c6001836138bf565b9150611689600a866138d6565b6116949060306138ea565b60f81b8183815181106116a9576116a961354a565b60200101906001600160f81b031916908160001a9053506116cb600a866138ab565b945061166b565b600954600160a01b900460ff1615610dcb5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016108fd565b600061172c338584611c9f565b600061173785611d2f565b905061174e848261174788610cbf565b6000611d39565b610aa0858285611e5e565b6000600161176686612109565b6040805160008152602081018083529290925260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156117b4573d6000803e3d6000fd5b5050604051601f190151600a549092506001600160a01b0380841691161490506118115760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b60448201526064016108fd565b5050505050565b60008061182361224d565b9050610aa085828686611d39565b6009546001600160a01b03163314610dcb5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108fd565b6118953382612264565b6118b15760405162461bcd60e51b81526004016108fd90613902565b6109488383836122cc565b6118c7338483611c9f565b610948838383611e5e565b6118da61242d565b6009805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b61094883838360405180602001604052806000815250611271565b61194b826114da565b600061195683611014565b9050600061196384610cbf565b905061196f8484612485565b611205565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6119ce6116d2565b6009805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861190a3390565b6001600160a01b038216611a725760405162461bcd60e51b815260206004820152602a60248201527f455243333532353a20617070726f76652076616c756520746f20746865207a65604482015269726f206164647265737360b01b60648201526084016108fd565b611a7c828461250a565b611ae257600083815260066020526040902054600580549091908110611aa457611aa461354a565b60009182526020808320600692909202909101600501805460018101825590835291200180546001600160a01b0319166001600160a01b0384161790555b60008381526004602090815260408083206001600160a01b038616808552908352928190208490555183815285917f621b050de0ad08b51d19b48b3e6df75348c4de6bdd93e81b252ca62e28265b1b91015b60405180910390a3505050565b816001600160a01b0316836001600160a01b031603611ba25760405162461bcd60e51b815260206004820152601a60248201527f455243333532353a20617070726f766520746f2063616c6c657200000000000060448201526064016108fd565b6001600160a01b0383811660008181526007602090815260408083209487168084526002909501825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101611b34565b611c153383612264565b611c315760405162461bcd60e51b81526004016108fd90613902565b611205848484846125dd565b60606107d56001600160a01b0383166014612650565b600554600090158015906107d55750600082815260066020526040902054600580548492908110611c8657611c8661354a565b9060005260206000209060060201600001541492915050565b6000611cab8385611340565b9050611cb78484612264565b158015611cc657506000198114155b156112055781811015611d1b5760405162461bcd60e51b815260206004820152601f60248201527f455243333532353a20696e73756666696369656e7420616c6c6f77616e63650060448201526064016108fd565b6112058385611d2a85856138bf565b611a09565b60006107d561224d565b6001600160a01b038416611d995760405162461bcd60e51b815260206004820152602160248201527f455243333532353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b60648201526084016108fd565b82600003611df35760405162461bcd60e51b815260206004820152602160248201527f455243333532353a2063616e6e6f74206d696e74207a65726f20746f6b656e496044820152601960fa1b60648201526084016108fd565b611dfc83611c53565b15611e495760405162461bcd60e51b815260206004820152601d60248201527f455243333532353a20746f6b656e20616c7265616479206d696e74656400000060448201526064016108fd565b611e548484846127ec565b61196f8382612485565b611e6783611c53565b611ec35760405162461bcd60e51b815260206004820152602760248201527f455243333532353a207472616e736665722066726f6d20696e76616c696420746044820152661bdad95b88125160ca1b60648201526084016108fd565b611ecc82611c53565b611f265760405162461bcd60e51b815260206004820152602560248201527f455243333532353a207472616e7366657220746f20696e76616c696420746f6b604482015264195b88125160da1b60648201526084016108fd565b600083815260066020526040812054600580549091908110611f4a57611f4a61354a565b9060005260206000209060060201905060006005600660008681526020019081526020016000205481548110611f8257611f8261354a565b906000526020600020906006020190508282600201541015611ff95760405162461bcd60e51b815260206004820152602a60248201527f455243333532353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b60648201526084016108fd565b80600101548260010154146120675760405162461bcd60e51b815260206004820152602e60248201527f455243333532353a207472616e7366657220746f20746f6b656e20776974682060448201526d191a5999995c995b9d081cdb1bdd60921b60648201526084016108fd565b8282600201600082825461207b91906138bf565b925050819055508281600201600082825461209691906138ea565b9091555050604051838152849086907f0b2aac84f3ec956911fd78eae5311062972ff949f38412e8da39069d9f068cc69060200160405180910390a36120ed858585604051806020016040528060008152506128b2565b6118115760405162461bcd60e51b81526004016108fd90613954565b6000612208604080518082018252600d81526c04c4f4f5461444f47204461707609c1b6020918201528151808301835260018152603160f81b9082015281517fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472818301527f7adf56923e686bb1b093759a744659a5bc83da4e64912930cd2c64f30774ef92818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201527ff2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a55860c0808301919091528351808303909101815260e0909101909252815191012090565b61221183612a36565b60405161190160f01b6020820152602281019290925260428201526062015b604051602081830303815290604052805190602001209050919050565b600061225d600380546001019055565b5060035490565b600061226f826114da565b600061227a83611014565b9050806001600160a01b0316846001600160a01b031614806122a157506122a18185610680565b80610aa05750836001600160a01b03166122ba8461086d565b6001600160a01b031614949350505050565b826001600160a01b03166122df82611014565b6001600160a01b0316146123415760405162461bcd60e51b8152602060048201526024808201527f455243333532353a207472616e736665722066726f6d20696e76616c6964206f6044820152633bb732b960e11b60648201526084016108fd565b6001600160a01b0382166123a55760405162461bcd60e51b815260206004820152602560248201527f455243333532353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b60648201526084016108fd565b60006123b082610cbf565b905060006123bd8361121a565b90506123ca60008461152b565b6123d383612ab1565b6123dd8584612b4d565b6123e78484612c6e565b82846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611811565b600954600160a01b900460ff16610dcb5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016108fd565b505050505050565b6000828152600660205260409020546005805483929081106124a9576124a961354a565b906000526020600020906006020160020160008282546124c991906138ea565b909155505060405181815282906000907f0b2aac84f3ec956911fd78eae5311062972ff949f38412e8da39069d9f068cc69060200160405180910390a35050565b60008181526006602052604081205460058054839290811061252e5761252e61354a565b6000918252602082206005600690920201015491505b818110156125d257600084815260066020526040902054600580546001600160a01b038816929081106125795761257961354a565b9060005260206000209060060201600501828154811061259b5761259b61354a565b6000918252602090912001546001600160a01b0316036125c0576001925050506107d5565b806125ca8161387c565b915050612544565b506000949350505050565b6125e88484846122cc565b6125f484848484612cf7565b6112055760405162461bcd60e51b815260206004820152602760248201527f455243333532353a207472616e7366657220746f206e6f6e204552433732315260448201526632b1b2b4bb32b960c91b60648201526084016108fd565b6060600061265f83600261399c565b61266a9060026138ea565b67ffffffffffffffff811115612682576126826133a0565b6040519080825280601f01601f1916602001820160405280156126ac576020820181803683370190505b509050600360fc1b816000815181106126c7576126c761354a565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106126f6576126f661354a565b60200101906001600160f81b031916908160001a905350600061271a84600261399c565b6127259060016138ea565b90505b600181111561279d576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106127595761275961354a565b1a60f81b82828151811061276f5761276f61354a565b60200101906001600160f81b031916908160001a90535060049490941c93612796816139bb565b9050612728565b508315610a2b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108fd565b6040805160c081018252838152602080820184905260008284018190526001600160a01b038716606084015260808301819052835181815291820190935260a0820152905061283a81612ea4565b6128448484612c6e565b60405183906001600160a01b038616906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4816000847fe4f48c240d3b994948aa54f3e2f5fca59263dfe1d52b6e4cf39a5d249b5ccb6560405160405180910390a450505050565b6000806128be85611014565b90506001600160a01b0381163b1515801561294257506040516301ffc9a760e01b8152629ce20b60e01b60048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa15801561291e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061294291906139d2565b15612a2c57604051629ce20b60e01b81526001600160a01b03821690629ce20b906129799033908a908a908a908a906004016139ef565b6020604051808303816000875af19250505080156129b4575060408051601f3d908101601f191682019092526129b191810190613a2d565b60015b612a11573d8080156129e2576040519150601f19603f3d011682016040523d82523d6000602084013e6129e7565b606091505b508051600003612a095760405162461bcd60e51b81526004016108fd90613954565b805181602001fd5b6001600160e01b031916629ce20b60e01b149150610aa09050565b6001915050610aa0565b8051602080830151604080850151606086015160808701519251600096612230967f4bd317336ea30fdfa31168cda381dacdf9ed1dd92eda94108d28629b6cf9b8c7969195919493920195865260208601949094526040850192909252606084015260808301526001600160a01b031660a082015260c00190565b600081815260066020526040812054600580549091908110612ad557612ad561354a565b600091825260208220600560069092020190810154909250905b81811015611205576000836005018281548110612b0e57612b0e61354a565b60009182526020808320909101548783526004825260408084206001600160a01b03909216845291528120555080612b458161387c565b915050612aef565b600081815260066020526040812054600580549091908110612b7157612b7161354a565b6000918252602080832060069290920290910160030180546001600160a01b0319166001600160a01b0394851617905591841681526007909152604081208054909190612bc0906001906138bf565b90506000826000018281548110612bd957612bd961354a565b90600052602060002001549050600083600101600086815260200190815260200160002054905081846000018281548110612c1657612c1661354a565b60009182526020808320909101929092558381526001860190915260408082208390558682528120558354849080612c5057612c50613a4a565b60019003818190600052602060002001600090559055505050505050565b600081815260066020526040902054600580548492908110612c9257612c9261354a565b6000918252602080832060069290920290910160030180546001600160a01b0319166001600160a01b03948516179055939091168152600780845260408083208054858552600182810188529285208190559286529082018155825292902090910155565b60006001600160a01b0384163b15158015612d7c57506040516301ffc9a760e01b8152630a85bd0160e11b60048201526001600160a01b038516906301ffc9a790602401602060405180830381865afa158015612d58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d7c91906139d2565b15612e9c57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612db3903390899088908890600401613a60565b6020604051808303816000875af1925050508015612dee575060408051601f3d908101601f19168201909252612deb91810190613a2d565b60015b612e82573d808015612e1c576040519150601f19603f3d011682016040523d82523d6000602084013e612e21565b606091505b508051600003612a095760405162461bcd60e51b815260206004820152602660248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201526531b2b4bb32b960d11b60648201526084016108fd565b6001600160e01b031916630a85bd0160e11b149050610aa0565b506001610aa0565b600580548251600090815260066020818152604080842085905560018501865594909252845192027f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db08101928355818501517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db1820155928401517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db284015560608401517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db3840180546001600160a01b039283166001600160a01b03199182161790915560808601517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db48601805491909316911617905560a084015180518594611205937f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db5909101920190828054828255906000526020600020908101928215613043579160200282015b8281111561304357825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061300e565b5061304f929150613053565b5090565b5b8082111561304f5760008155600101613054565b6001600160e01b0319811681146114d757600080fd5b60006020828403121561309057600080fd5b8135610a2b81613068565b60005b838110156130b657818101518382015260200161309e565b838111156112055750506000910152565b600081518084526130df81602086016020860161309b565b601f01601f19169290920160200192915050565b602081526000610a2b60208301846130c7565b60006020828403121561311857600080fd5b5035919050565b80356001600160a01b03811681146110ab57600080fd5b6000806040838503121561314957600080fd5b6131528361311f565b946020939093013593505050565b60008060006060848603121561317557600080fd5b833592506131856020850161311f565b9150604084013590509250925092565b803560ff811681146110ab57600080fd5b600080600080600080600060e0888a0312156131c157600080fd5b8735965060208801359550604088013594506131df6060890161311f565b93506131ed60808901613195565b925060a0880135915060c0880135905092959891949750929550565b60008060006060848603121561321e57600080fd5b6132278461311f565b92506131856020850161311f565b60008060006060848603121561324a57600080fd5b505081359360208301359350604090920135919050565b600080600080600080600080610100898b03121561327e57600080fd5b883597506020890135965060408901359550606089013594506132a360808a0161311f565b93506132b160a08a01613195565b925060c0890135915060e089013590509295985092959890939650565b600080602083850312156132e157600080fd5b823567ffffffffffffffff808211156132f957600080fd5b818501915085601f83011261330d57600080fd5b81358181111561331c57600080fd5b86602082850101111561332e57600080fd5b60209290920196919550909350505050565b60006020828403121561335257600080fd5b610a2b8261311f565b80151581146114d757600080fd5b6000806040838503121561337c57600080fd5b6133858361311f565b915060208301356133958161335b565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156133df576133df6133a0565b604052919050565b600067ffffffffffffffff821115613401576134016133a0565b50601f01601f191660200190565b6000806000806080858703121561342557600080fd5b61342e8561311f565b935061343c6020860161311f565b925060408501359150606085013567ffffffffffffffff81111561345f57600080fd5b8501601f8101871361347057600080fd5b803561348361347e826133e7565b6133b6565b81815288602083850101111561349857600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600080604083850312156134cd57600080fd5b823591506134dd6020840161311f565b90509250929050565b600080604083850312156134f957600080fd5b6135028361311f565b91506134dd6020840161311f565b600181811c9082168061352457607f821691505b60208210810361354457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60208082526022908201527f455243333532353a20617070726f76616c20746f2063757272656e74206f776e60408201526132b960f11b606082015260800190565b60208082526039908201527f455243333532353a20617070726f76652063616c6c6572206973206e6f74206f60408201527f776e6572206e6f7220617070726f76656420666f7220616c6c00000000000000606082015260800190565b6000835161361181846020880161309b565b64736c6f742f60d81b908301908152835161363381600584016020880161309b565b01600501949350505050565b60006020828403121561365157600080fd5b815167ffffffffffffffff81111561366857600080fd5b8201601f8101841361367957600080fd5b805161368761347e826133e7565b81815285602083850101111561369c57600080fd5b6136ad82602083016020860161309b565b95945050505050565b6020808252601d908201527f546f6b656e20646f6573206e6f7420616c6c6f77207472616e73666572000000604082015260600190565b601f82111561094857600081815260208120601f850160051c810160208610156137145750805b601f850160051c820191505b8181101561247d57828155600101613720565b67ffffffffffffffff83111561374b5761374b6133a0565b61375f836137598354613510565b836136ed565b6000601f841160018114613793576000851561377b5750838201355b600019600387901b1c1916600186901b178355611811565b600083815260209020601f19861690835b828110156137c457868501358255602094850194600190920191016137a4565b50868210156137e15760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6000835161380581846020880161309b565b83519083019061381981836020880161309b565b01949350505050565b6000835161383481846020880161309b565b68636f6e74726163742f60b81b908301908152835161385a81600984016020880161309b565b01600901949350505050565b634e487b7160e01b600052601160045260246000fd5b60006001820161388e5761388e613866565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826138ba576138ba613895565b500490565b6000828210156138d1576138d1613866565b500390565b6000826138e5576138e5613895565b500690565b600082198211156138fd576138fd613866565b500190565b60208082526032908201527f455243333532353a207472616e736665722063616c6c6572206973206e6f74206040820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b606082015260800190565b60208082526028908201527f455243333532353a207472616e7366657220746f206e6f6e20455243333532356040820152672932b1b2b4bb32b960c11b606082015260800190565b60008160001904831182151516156139b6576139b6613866565b500290565b6000816139ca576139ca613866565b506000190190565b6000602082840312156139e457600080fd5b8151610a2b8161335b565b60018060a01b038616815284602082015283604082015282606082015260a060808201526000613a2260a08301846130c7565b979650505050505050565b600060208284031215613a3f57600080fd5b8151610a2b81613068565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613a93908301846130c7565b969550505050505056fea2646970667358221220e2ad52a24bcfe504f6e72a3537011dff23006983c70992647239373d09abd19664736f6c634300080f0033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.