Feature Tip: Add private address tag to any address under My Name Tag !
ERC-1155
Overview
Max Total Supply
1,126
Holders
647
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
ArtDubaiAlexisChristodoulou
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; /* ::: ::::::::: ::: :::::::: :+: :+: :+: :+: :+: :+: :+: :+: +:+ +:+ +:+ +:+ +:+ +:+ +:+ +#++:++#++: +#+ +:+ +#++:++#++: +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ #+# #+# #+# #+# #+# #+# #+# #+# ### ### ######### ### ### ######## UAE NFT - Art Dubai | Alexis Christodoulou All rights reserved 2023 Developed by DeployLabs.io ([email protected]) */ import "./ArtDubai.sol"; error Alexis__EmptyVouchersArray(); error Alexis__VoucherAlreadyUsed(); error Alexis__HashComparisonFailed(); error Alexis__SignatureExpired(); error Alexis__UntrustedSigner(); error Alexis__SignatureAlreadyUsed(); /** * @title UAE NFT - Art Dubai | Alexis Christodoulou * @author DeployLabs.io * * @dev This contract is a collection for Art Dubai by Alexis Christodoulou. */ contract ArtDubaiAlexisChristodoulou is ArtDubai { /** * @dev A signature package, that secures the minting of reward tokens. * * @param hash The hash of the minting operation. * @param signature The signature for the hash. * @param signatureValidUntil The timestamp until which the signature is valid. * @param nonce The nonce, that is used to prevent replay attacks. */ struct RewardSignaturePackage { bytes32 hash; bytes signature; uint32 signatureValidUntil; uint64 nonce; } /** * @dev A voucher, that can be used to mint reward tokens. * * @param collection The collection address. * @param tokenId The token ID. */ struct RewardVoucher { address collection; uint64 tokenId; } event RewardVoucherUsed(address indexed collection, uint256 indexed tokenId); uint8 private s_daytimeRewardTokenId; uint8 private s_nighttimeRewardTokenId; // Collection address to token ID to used/unused mapping(address => mapping(uint256 => bool)) private s_tokenIdsUsedForRewards; constructor() ArtDubai(0xaca187d2a59b04b4, 0x89994365E8538F61a906c84cb15B6d415051fed0) {} /** * @dev Mint reward tokens for the caller. * * @param signaturePackage The signature package. * @param rewardVouchers The reward vouchers to use. */ function mintRewardTokens( RewardSignaturePackage calldata signaturePackage, RewardVoucher[] calldata rewardVouchers ) external { if (rewardVouchers.length == 0) revert Alexis__EmptyVouchersArray(); uint8 tokenIdToMint = _itIsDaytime() ? s_daytimeRewardTokenId : s_nighttimeRewardTokenId; for (uint16 i = 0; i < rewardVouchers.length; i++) { RewardVoucher memory rewardVoucher = rewardVouchers[i]; if (s_tokenIdsUsedForRewards[rewardVoucher.collection][rewardVoucher.tokenId]) revert Alexis__VoucherAlreadyUsed(); s_tokenIdsUsedForRewards[rewardVoucher.collection][rewardVoucher.tokenId] = true; emit RewardVoucherUsed(rewardVoucher.collection, rewardVoucher.tokenId); } if (signaturePackage.signatureValidUntil < block.timestamp) revert Alexis__SignatureExpired(); if (!_isCorrectRewardMintOperationHash(signaturePackage, rewardVouchers, msg.sender)) revert Alexis__HashComparisonFailed(); if (!_isTrustedSigner(signaturePackage.hash, signaturePackage.signature)) revert Alexis__UntrustedSigner(); if (s_usedNonces[signaturePackage.nonce]) revert Alexis__SignatureAlreadyUsed(); s_numberMinted[tokenIdToMint][msg.sender] += uint16(rewardVouchers.length); s_usedNonces[signaturePackage.nonce] = true; _mint(msg.sender, tokenIdToMint, rewardVouchers.length, ""); } /** * @dev Specify which token IDs are going to be used as reward tokens. * * @param daytimeRewardTokenId The daytime reward token ID. * @param nighttimeRewardTokenId The nighttime reward token ID. */ function setRewardTokenIds( uint8 daytimeRewardTokenId, uint8 nighttimeRewardTokenId ) external onlyOwner { s_daytimeRewardTokenId = daytimeRewardTokenId; s_nighttimeRewardTokenId = nighttimeRewardTokenId; } /** * @dev Get the reward token ID. * * @return daytimeRewardTokenId The daytime reward token ID. * @return nighttimeRewardTokenId The nighttime reward token ID. */ function getRewardTokenIds() public view returns (uint8 daytimeRewardTokenId, uint8 nighttimeRewardTokenId) { daytimeRewardTokenId = s_daytimeRewardTokenId; nighttimeRewardTokenId = s_nighttimeRewardTokenId; } /// @inheritdoc ArtDubai function isTokenForSale(uint8 tokenId) public view override returns (bool isForSale) { isForSale = (tokenId != s_daytimeRewardTokenId) && (tokenId != s_nighttimeRewardTokenId) && super.isTokenForSale(tokenId); } /** * @dev Check if it's daytime in Dubai (GMT+4). * * @return isDaytime True if it's daytime in Dubai. */ function _itIsDaytime() internal view returns (bool isDaytime) { // Dubai is GMT+4, thus we add 14400 seconds to the current timestamp uint256 hour = ((block.timestamp + 14400) % 86400) / 3600; isDaytime = (hour >= 6) && (hour < 18); } /** * @dev Check whether a message hash is the one that has been signed. * * @param signaturePackage The signature package. * @param mintTo The address to mint to. * * @return isCorrectRewardMintOperationHash Whether the message hash matches the one that has been signed. */ function _isCorrectRewardMintOperationHash( RewardSignaturePackage calldata signaturePackage, RewardVoucher[] calldata rewardVouchers, address mintTo ) internal view returns (bool isCorrectRewardMintOperationHash) { bytes memory collectionBytes; bytes memory tokenIdBytes; for (uint16 i = 0; i < rewardVouchers.length; i++) { collectionBytes = abi.encodePacked(collectionBytes, rewardVouchers[i].collection); tokenIdBytes = abi.encodePacked(tokenIdBytes, rewardVouchers[i].tokenId); } bytes memory message = abi.encodePacked( i_hashSalt, mintTo, uint64(block.chainid), collectionBytes, tokenIdBytes, signaturePackage.signatureValidUntil, signaturePackage.nonce ); bytes32 messageHash = keccak256(message); isCorrectRewardMintOperationHash = messageHash == signaturePackage.hash; } }
// 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.8.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.0; import "./IERC1155.sol"; import "./IERC1155Receiver.sol"; import "./extensions/IERC1155MetadataURI.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 * * _Available since v3.1._ */ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { using Address for address; // Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) private _balances; // Mapping from account to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ constructor(string memory uri_) { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155).interfaceId || interfaceId == type(IERC1155MetadataURI).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256) public view virtual override returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: address zero is not a valid owner"); return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual override returns (uint256[] memory) { require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts[i], ids[i]); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not token owner or approved" ); _safeTransferFrom(from, to, id, amount, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not token owner or approved" ); _safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, to, ids, amounts, data); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; emit TransferSingle(operator, from, to, id, amount); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, ids, amounts, data); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; } emit TransferBatch(operator, from, to, ids, amounts); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the amounts in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); _balances[id][to] += amount; emit TransferSingle(operator, address(0), to, id, amount); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { _balances[ids[i]][to] += amounts[i]; } emit TransferBatch(operator, address(0), to, ids, amounts); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); } /** * @dev Destroys `amount` tokens of token type `id` from `from` * * Emits a {TransferSingle} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `amount` tokens of token type `id`. */ function _burn( address from, uint256 id, uint256 amount ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } emit TransferSingle(operator, from, address(0), id, amount); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. */ function _burnBatch( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); for (uint256 i = 0; i < ids.length; i++) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } } emit TransferBatch(operator, from, address(0), ids, amounts); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC1155: setting approval status for self"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `ids` and `amounts` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non-ERC1155Receiver implementer"); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non-ERC1155Receiver implementer"); } } } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155Supply.sol) pragma solidity ^0.8.0; import "../ERC1155.sol"; /** * @dev Extension of ERC1155 that adds tracking of total supply per id. * * Useful for scenarios where Fungible and Non-fungible tokens have to be * clearly identified. Note: While a totalSupply of 1 might mean the * corresponding is an NFT, there is no guarantees that no other token with the * same id are not going to be minted. */ abstract contract ERC1155Supply is ERC1155 { mapping(uint256 => uint256) private _totalSupply; /** * @dev Total amount of tokens in with a given id. */ function totalSupply(uint256 id) public view virtual returns (uint256) { return _totalSupply[id]; } /** * @dev Indicates whether any token exist with a given id, or not. */ function exists(uint256 id) public view virtual returns (bool) { return ERC1155Supply.totalSupply(id) > 0; } /** * @dev See {ERC1155-_beforeTokenTransfer}. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual override { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); if (from == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { _totalSupply[ids[i]] += amounts[i]; } } if (to == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 supply = _totalSupply[id]; require(supply >= amount, "ERC1155: burn amount exceeds totalSupply"); unchecked { _totalSupply[id] = supply - amount; } } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.0; import "../IERC1155.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ interface IERC1155MetadataURI is IERC1155 { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 (last updated v4.8.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// 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.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _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) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @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] = _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.17; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "./library/operator_filterer/DefaultOperatorFilterer.sol"; error ArtDubai__TokenNotForSale(); error ArtDubai__WrongEtherAmmount(); error ArtDubai__ExceedingMaxSupply(); error ArtDubai__ExceedingTokensPerWalletLimit(); error ArtDubai__ExceedingSignatureMaxQuantity(); error ArtDubai__HashComparisonFailed(); error ArtDubai__SignatureExpired(); error ArtDubai__UntrustedSigner(); error ArtDubai__SignatureAlreadyUsed(); error ArtDubai__InvalidInput(); error ArtDubai__NothingToWithdraw(); /** * @dev A struct, that contains the sale conditions for a token. * * @param supplyLimit The maximum amount of tokens that can be minted. * @param maxTokensPerWallet The maximum amount of tokens that can be minted per wallet. * @param weiTokenPrice The price of a token in wei. */ struct SaleConditions { uint16 supplyLimit; uint16 maxTokensPerWallet; uint256 weiTokenPrice; } /** * @dev A signature package, that secures the minting of tokens. * * @param hash The hash of the minting operation. * @param signature The signature for the hash. * @param signatureValidUntil The timestamp until which the signature is valid. * @param nonce The nonce, that is used to prevent replay attacks. * @param maxQuantity The maximum quantity of tokens that can be minted with this signature. */ struct SignaturePackage { bytes32 hash; bytes signature; uint32 signatureValidUntil; uint64 nonce; uint16 maxQuantity; } /** * @title Art Dubai * @author DeployLabs.io * * @dev This contract is used as a base contract for all Art Dubai collections. */ abstract contract ArtDubai is ERC1155, ERC1155Supply, Ownable, DefaultOperatorFilterer { bytes8 internal immutable i_hashSalt; address internal immutable i_signerAddress; mapping(uint64 => bool) internal s_usedNonces; mapping(uint8 => SaleConditions) internal s_saleConditions; mapping(uint8 => mapping(address => uint16)) internal s_numberMinted; string internal s_baseTokenUri; constructor(bytes8 hashSalt, address signerAddress) ERC1155("") { i_hashSalt = hashSalt; i_signerAddress = signerAddress; } /** * @dev Mint a token to a specified wallet. * * @param signaturePackage The signature package for security. * @param mintTo The address to mint the token to. * @param tokenId The id of the token to mint. * @param quantity The quantity of tokens to mint. */ function mint( SignaturePackage calldata signaturePackage, address mintTo, uint8 tokenId, uint16 quantity ) external payable { SaleConditions memory conditions = s_saleConditions[tokenId]; if (!isTokenForSale(tokenId)) revert ArtDubai__TokenNotForSale(); if (msg.value != conditions.weiTokenPrice * quantity) revert ArtDubai__WrongEtherAmmount(); if (totalSupply(tokenId) + quantity > conditions.supplyLimit) revert ArtDubai__ExceedingMaxSupply(); if (s_numberMinted[tokenId][mintTo] + quantity > conditions.maxTokensPerWallet) revert ArtDubai__ExceedingTokensPerWalletLimit(); if (quantity > signaturePackage.maxQuantity) revert ArtDubai__ExceedingSignatureMaxQuantity(); if (signaturePackage.signatureValidUntil < block.timestamp) revert ArtDubai__SignatureExpired(); if (!_isCorrectMintOperationHash(signaturePackage, tokenId, mintTo)) revert ArtDubai__HashComparisonFailed(); if (!_isTrustedSigner(signaturePackage.hash, signaturePackage.signature)) revert ArtDubai__UntrustedSigner(); if (s_usedNonces[signaturePackage.nonce]) revert ArtDubai__SignatureAlreadyUsed(); s_numberMinted[tokenId][mintTo] += quantity; s_usedNonces[signaturePackage.nonce] = true; _mint(mintTo, tokenId, quantity, ""); } /** * @dev Withdraw the balance of the contract. * * @param to The address to send the balance to. */ function withdraw(address payable to) external onlyOwner { uint256 balance = address(this).balance; if (balance == 0) revert ArtDubai__NothingToWithdraw(); if (to == address(0)) revert ArtDubai__InvalidInput(); to.transfer(balance); } /** * @dev Set base URI for token metadata. * * @param baseUri The base URI for token metadata. */ function setBaseUri(string calldata baseUri) external onlyOwner { s_baseTokenUri = baseUri; } /** * @dev Sets sale conditions for a set of tokens. * * @param tokenIds Token IDs * @param saleConditions Sale conditions for each token */ function setSaleConditions( uint8[] calldata tokenIds, SaleConditions[] calldata saleConditions ) external onlyOwner { if (tokenIds.length != saleConditions.length) revert ArtDubai__InvalidInput(); for (uint8 i = 0; i < tokenIds.length; i++) { s_saleConditions[tokenIds[i]] = saleConditions[i]; } } /** * @dev Gets sale conditions for a token. * * @param tokenId Token ID * * @return conditions Sale conditions. */ function getSaleConditions( uint8 tokenId ) external view returns (SaleConditions memory conditions) { conditions = s_saleConditions[tokenId]; } /** * @dev Get the number of tokens minted by a wallet. * * @param tokenId The id of the token. * @param wallet The wallet to check. * * @return countMinted The number of tokens minted by the wallet. */ function getMintedCount( uint8 tokenId, address wallet ) external view returns (uint16 countMinted) { countMinted = s_numberMinted[tokenId][wallet]; } // Overrides for marketplace restrictions. function setApprovalForAll( address operator, bool approved ) public override onlyAllowedOperatorApproval(operator) { super.setApprovalForAll(operator, approved); } function safeTransferFrom( address from, address to, uint256 tokenId, uint256 amount, bytes memory data ) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId, amount, data); } function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override onlyAllowedOperator(from) { super.safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Check, if a token is for sale. * * @param tokenId The id of the token. * * @return isForSale Whether the token is for sale. */ function isTokenForSale(uint8 tokenId) public view virtual returns (bool isForSale) { isForSale = s_saleConditions[tokenId].supplyLimit > 0; } /** * @dev Get data used to generate the signature. * * @return hashSalt The hash salt. * @return signerAddress The signer address. */ function getSignatureData() public view returns (bytes8 hashSalt, address signerAddress) { hashSalt = i_hashSalt; signerAddress = i_signerAddress; } /** * @dev Get the URI for a token. * * @param tokenId The token ID. * * @return uri The URI for the token. */ function uri(uint256 tokenId) public view virtual override returns (string memory) { return string(abi.encodePacked(s_baseTokenUri, Strings.toString(tokenId))); } // Override for ERC1155Supply. function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal override(ERC1155, ERC1155Supply) { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); } /** * @dev Check whether a message hash is the one that has been signed. * * @param signaturePackage The signature package. * @param tokenId The id of the token. * @param mintTo The address to mint to. * * @return isCorrectMintOperationHash Whether the message hash matches the one that has been signed. */ function _isCorrectMintOperationHash( SignaturePackage calldata signaturePackage, uint8 tokenId, address mintTo ) internal view returns (bool isCorrectMintOperationHash) { bytes memory message = abi.encodePacked( i_hashSalt, mintTo, uint64(block.chainid), tokenId, signaturePackage.maxQuantity, signaturePackage.signatureValidUntil, signaturePackage.nonce ); bytes32 messageHash = keccak256(message); isCorrectMintOperationHash = messageHash == signaturePackage.hash; } /** * @dev Check whether a message was signed by a trusted address. * * @param hash The hash of the message. * @param signature The signature of the message. * * @return isTrustedSigner Whether the message was signed by a trusted address. */ function _isTrustedSigner( bytes32 hash, bytes memory signature ) internal view returns (bool isTrustedSigner) { isTrustedSigner = i_signerAddress == ECDSA.recover(hash, signature); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {OperatorFilterer} from "./OperatorFilterer.sol"; /** * @title DefaultOperatorFilterer * @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription. */ abstract contract DefaultOperatorFilterer is OperatorFilterer { address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6); constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; interface IOperatorFilterRegistry { function isOperatorAllowed(address registrant, address operator) external view returns (bool); function register(address registrant) external; function registerAndSubscribe(address registrant, address subscription) external; function registerAndCopyEntries(address registrant, address registrantToCopy) external; function unregister(address addr) external; function updateOperator(address registrant, address operator, bool filtered) external; function updateOperators(address registrant, address[] calldata operators, bool filtered) external; function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external; function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external; function subscribe(address registrant, address registrantToSubscribe) external; function unsubscribe(address registrant, bool copyExistingEntries) external; function subscriptionOf(address addr) external returns (address registrant); function subscribers(address registrant) external returns (address[] memory); function subscriberAt(address registrant, uint256 index) external returns (address); function copyEntriesOf(address registrant, address registrantToCopy) external; function isOperatorFiltered(address registrant, address operator) external returns (bool); function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool); function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool); function filteredOperators(address addr) external returns (address[] memory); function filteredCodeHashes(address addr) external returns (bytes32[] memory); function filteredOperatorAt(address registrant, uint256 index) external returns (address); function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32); function isRegistered(address addr) external returns (bool); function codeHashOf(address addr) external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol"; /** * @title OperatorFilterer * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another * registrant's entries in the OperatorFilterRegistry. * @dev This smart contract is meant to be inherited by token contracts so they can use the following: * - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods. * - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods. */ abstract contract OperatorFilterer { error OperatorNotAllowed(address operator); IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY = IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E); constructor(address subscriptionOrRegistrantToCopy, bool subscribe) { // If an inheriting token contract is deployed to a network without the registry deployed, the modifier // will not revert, but the contract will need to be registered with the registry once it is deployed in // order for the modifier to filter addresses. if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) { if (subscribe) { OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy); } else { if (subscriptionOrRegistrantToCopy != address(0)) { OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy); } else { OPERATOR_FILTER_REGISTRY.register(address(this)); } } } } modifier onlyAllowedOperator(address from) virtual { // Allow spending tokens from addresses with balance // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred // from an EOA. if (from != msg.sender) { _checkFilterOperator(msg.sender); } _; } modifier onlyAllowedOperatorApproval(address operator) virtual { _checkFilterOperator(operator); _; } function _checkFilterOperator(address operator) internal view virtual { // Check registry code length to facilitate testing in environments without a deployed registry. if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) { if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) { revert OperatorNotAllowed(operator); } } } }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Alexis__EmptyVouchersArray","type":"error"},{"inputs":[],"name":"Alexis__HashComparisonFailed","type":"error"},{"inputs":[],"name":"Alexis__SignatureAlreadyUsed","type":"error"},{"inputs":[],"name":"Alexis__SignatureExpired","type":"error"},{"inputs":[],"name":"Alexis__UntrustedSigner","type":"error"},{"inputs":[],"name":"Alexis__VoucherAlreadyUsed","type":"error"},{"inputs":[],"name":"ArtDubai__ExceedingMaxSupply","type":"error"},{"inputs":[],"name":"ArtDubai__ExceedingSignatureMaxQuantity","type":"error"},{"inputs":[],"name":"ArtDubai__ExceedingTokensPerWalletLimit","type":"error"},{"inputs":[],"name":"ArtDubai__HashComparisonFailed","type":"error"},{"inputs":[],"name":"ArtDubai__InvalidInput","type":"error"},{"inputs":[],"name":"ArtDubai__NothingToWithdraw","type":"error"},{"inputs":[],"name":"ArtDubai__SignatureAlreadyUsed","type":"error"},{"inputs":[],"name":"ArtDubai__SignatureExpired","type":"error"},{"inputs":[],"name":"ArtDubai__TokenNotForSale","type":"error"},{"inputs":[],"name":"ArtDubai__UntrustedSigner","type":"error"},{"inputs":[],"name":"ArtDubai__WrongEtherAmmount","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","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":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"RewardVoucherUsed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tokenId","type":"uint8"},{"internalType":"address","name":"wallet","type":"address"}],"name":"getMintedCount","outputs":[{"internalType":"uint16","name":"countMinted","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardTokenIds","outputs":[{"internalType":"uint8","name":"daytimeRewardTokenId","type":"uint8"},{"internalType":"uint8","name":"nighttimeRewardTokenId","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tokenId","type":"uint8"}],"name":"getSaleConditions","outputs":[{"components":[{"internalType":"uint16","name":"supplyLimit","type":"uint16"},{"internalType":"uint16","name":"maxTokensPerWallet","type":"uint16"},{"internalType":"uint256","name":"weiTokenPrice","type":"uint256"}],"internalType":"struct SaleConditions","name":"conditions","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSignatureData","outputs":[{"internalType":"bytes8","name":"hashSalt","type":"bytes8"},{"internalType":"address","name":"signerAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tokenId","type":"uint8"}],"name":"isTokenForSale","outputs":[{"internalType":"bool","name":"isForSale","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint32","name":"signatureValidUntil","type":"uint32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint16","name":"maxQuantity","type":"uint16"}],"internalType":"struct SignaturePackage","name":"signaturePackage","type":"tuple"},{"internalType":"address","name":"mintTo","type":"address"},{"internalType":"uint8","name":"tokenId","type":"uint8"},{"internalType":"uint16","name":"quantity","type":"uint16"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint32","name":"signatureValidUntil","type":"uint32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct ArtDubaiAlexisChristodoulou.RewardSignaturePackage","name":"signaturePackage","type":"tuple"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint64","name":"tokenId","type":"uint64"}],"internalType":"struct ArtDubaiAlexisChristodoulou.RewardVoucher[]","name":"rewardVouchers","type":"tuple[]"}],"name":"mintRewardTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","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":"uint8","name":"daytimeRewardTokenId","type":"uint8"},{"internalType":"uint8","name":"nighttimeRewardTokenId","type":"uint8"}],"name":"setRewardTokenIds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8[]","name":"tokenIds","type":"uint8[]"},{"components":[{"internalType":"uint16","name":"supplyLimit","type":"uint16"},{"internalType":"uint16","name":"maxTokensPerWallet","type":"uint16"},{"internalType":"uint256","name":"weiTokenPrice","type":"uint256"}],"internalType":"struct SaleConditions[]","name":"saleConditions","type":"tuple[]"}],"name":"setSaleConditions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5067aca187d2a59b04b460c01b7389994365e8538f61a906c84cb15b6d415051fed0733cc6cdda760b79bafa08df41ecfa224f810dceb66001604051806020016040528060008152506200006b81620002fd60201b60201c565b506200008c620000806200031260201b60201c565b6200031a60201b60201c565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156200028157801562000147576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b81526004016200010d92919062000425565b600060405180830381600087803b1580156200012857600080fd5b505af11580156200013d573d6000803e3d6000fd5b5050505062000280565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161462000201576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b8152600401620001c792919062000425565b600060405180830381600087803b158015620001e257600080fd5b505af1158015620001f7573d6000803e3d6000fd5b505050506200027f565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b81526004016200024a919062000452565b600060405180830381600087803b1580156200026557600080fd5b505af11580156200027a573d6000803e3d6000fd5b505050505b5b5b50508177ffffffffffffffffffffffffffffffffffffffffffffffff191660808177ffffffffffffffffffffffffffffffffffffffffffffffff1916815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250505050620007d0565b80600290816200030e9190620006e9565b5050565b600033905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200040d82620003e0565b9050919050565b6200041f8162000400565b82525050565b60006040820190506200043c600083018562000414565b6200044b602083018462000414565b9392505050565b600060208201905062000469600083018462000414565b92915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620004f157607f821691505b602082108103620005075762000506620004a9565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620005717fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000532565b6200057d868362000532565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620005ca620005c4620005be8462000595565b6200059f565b62000595565b9050919050565b6000819050919050565b620005e683620005a9565b620005fe620005f582620005d1565b8484546200053f565b825550505050565b600090565b6200061562000606565b62000622818484620005db565b505050565b5b818110156200064a576200063e6000826200060b565b60018101905062000628565b5050565b601f821115620006995762000663816200050d565b6200066e8462000522565b810160208510156200067e578190505b620006966200068d8562000522565b83018262000627565b50505b505050565b600082821c905092915050565b6000620006be600019846008026200069e565b1980831691505092915050565b6000620006d98383620006ab565b9150826002028217905092915050565b620006f4826200046f565b67ffffffffffffffff81111562000710576200070f6200047a565b5b6200071c8254620004d8565b620007298282856200064e565b600060209050601f8311600181146200076157600084156200074c578287015190505b620007588582620006cb565b865550620007c8565b601f19841662000771866200050d565b60005b828110156200079b5784890151825560018201915060208501945060208101905062000774565b86831015620007bb5784890151620007b7601f891682620006ab565b8355505b6001600288020188555050505b505050505050565b60805160a051615d2e6200080b600039600081816115dd0152611d000152600081816115ba01528181611c3c015261214a0152615d2e6000f3fe6080604052600436106101655760003560e01c80638c02f79b116100d1578063bd85b0391161008a578063e985e9c511610064578063e985e9c514610552578063f006ad971461058f578063f242432a146105cc578063f2fde38b146105f557610165565b8063bd85b039146104c3578063bef98d4b14610500578063e5b8fb921461052957610165565b80638c02f79b146103c55780638da5cb5b146103ee578063900af1921461041957806390b7178e14610445578063a0bcfc7f14610471578063a22cb4651461049a57610165565b80634163933a116101235780634163933a146102c457806341f43434146102e05780634e1273f41461030b5780634f558e791461034857806351cff8d914610385578063715018a6146103ae57610165565b8062fdd58e1461016a57806301ffc9a7146101a75780630e89341c146101e457806314119bb714610221578063235f0e931461025e5780632eb2c2d61461029b575b600080fd5b34801561017657600080fd5b50610191600480360381019061018c9190613521565b61061e565b60405161019e9190613570565b60405180910390f35b3480156101b357600080fd5b506101ce60048036038101906101c991906135e3565b6106e6565b6040516101db919061362b565b60405180910390f35b3480156101f057600080fd5b5061020b60048036038101906102069190613646565b6107c8565b6040516102189190613703565b60405180910390f35b34801561022d57600080fd5b506102486004803603810190610243919061375e565b6107fc565b60405161025591906137f9565b60405180910390f35b34801561026a57600080fd5b5061028560048036038101906102809190613814565b610879565b6040516102929190613863565b60405180910390f35b3480156102a757600080fd5b506102c260048036038101906102bd9190613a7b565b6108e8565b005b6102de60048036038101906102d99190613b9a565b61093b565b005b3480156102ec57600080fd5b506102f5610e4c565b6040516103029190613c7c565b60405180910390f35b34801561031757600080fd5b50610332600480360381019061032d9190613d5a565b610e5e565b60405161033f9190613e81565b60405180910390f35b34801561035457600080fd5b5061036f600480360381019061036a9190613646565b610f77565b60405161037c919061362b565b60405180910390f35b34801561039157600080fd5b506103ac60048036038101906103a79190613ee1565b610f8b565b005b3480156103ba57600080fd5b506103c3611083565b005b3480156103d157600080fd5b506103ec60048036038101906103e79190613f88565b611097565b005b3480156103fa57600080fd5b5061040361158b565b6040516104109190614013565b60405180910390f35b34801561042557600080fd5b5061042e6115b5565b60405161043c929190614069565b60405180910390f35b34801561045157600080fd5b5061045a611602565b6040516104689291906140a1565b60405180910390f35b34801561047d57600080fd5b5061049860048036038101906104939190614120565b61162d565b005b3480156104a657600080fd5b506104c160048036038101906104bc9190614199565b61164b565b005b3480156104cf57600080fd5b506104ea60048036038101906104e59190613646565b611664565b6040516104f79190613570565b60405180910390f35b34801561050c57600080fd5b50610527600480360381019061052291906141d9565b611681565b005b34801561053557600080fd5b50610550600480360381019061054b91906142c5565b6116c3565b005b34801561055e57600080fd5b5061057960048036038101906105749190614346565b6117a3565b604051610586919061362b565b60405180910390f35b34801561059b57600080fd5b506105b660048036038101906105b1919061375e565b611837565b6040516105c3919061362b565b60405180910390f35b3480156105d857600080fd5b506105f360048036038101906105ee9190614386565b61188b565b005b34801561060157600080fd5b5061061c6004803603810190610617919061441d565b6118de565b005b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361068e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610685906144bc565b60405180910390fd5b60008083815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b60007fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107b157507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806107c157506107c082611961565b5b9050919050565b606060086107d5836119cb565b6040516020016107e6929190614610565b6040516020818303038152906040529050919050565b610804613450565b600660008360ff1660ff1681526020019081526020016000206040518060600160405290816000820160009054906101000a900461ffff1661ffff1661ffff1681526020016000820160029054906101000a900461ffff1661ffff1661ffff1681526020016001820154815250509050919050565b6000600760008460ff1660ff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff16905092915050565b843373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109265761092533611a99565b5b6109338686868686611b96565b505050505050565b6000600660008460ff1660ff1681526020019081526020016000206040518060600160405290816000820160009054906101000a900461ffff1661ffff1661ffff1681526020016000820160029054906101000a900461ffff1661ffff1661ffff16815260200160018201548152505090506109b683611837565b6109ec576040517fee19d49100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8161ffff168160400151610a009190614663565b3414610a38576040517f26c3439000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015161ffff168261ffff16610a528560ff16611664565b610a5c91906146a5565b1115610a94576040517fd8ea507600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015161ffff1682600760008660ff1660ff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff16610b0d91906146d9565b61ffff161115610b49576040517f5b3e6f0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846080016020810190610b5c919061470f565b61ffff168261ffff161115610b9d576040517f8d515e9c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42856040016020810190610bb19190614778565b63ffffffff161015610bef576040517f1eee9c0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610bfa858486611c37565b610c30576040517fff39ee9500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c908560000135868060200190610c4891906147b4565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611cdc565b610cc6576040517f1490dab400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60056000866060016020810190610cdd9190614857565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610d44576040517fa2a6490500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600760008560ff1660ff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff16610db791906146d9565b92506101000a81548161ffff021916908361ffff160217905550600160056000876060016020810190610dea9190614857565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550610e45848460ff168461ffff1660405180602001604052806000815250611d3e565b5050505050565b6daaeb6d7670e522a718067333cd4e81565b60608151835114610ea4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e9b906148f6565b60405180910390fd5b6000835167ffffffffffffffff811115610ec157610ec0613883565b5b604051908082528060200260200182016040528015610eef5781602001602082028036833780820191505090505b50905060005b8451811015610f6c57610f3c858281518110610f1457610f13614916565b5b6020026020010151858381518110610f2f57610f2e614916565b5b602002602001015161061e565b828281518110610f4f57610f4e614916565b5b60200260200101818152505080610f6590614945565b9050610ef5565b508091505092915050565b600080610f8383611664565b119050919050565b610f93611eee565b600047905060008103610fd2576040517f895dcf4500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611038576040517fcaa9014f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561107e573d6000803e3d6000fd5b505050565b61108b611eee565b6110956000611f6c565b565b600082829050036110d4576040517fd643e0ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006110de612032565b6110f757600960019054906101000a900460ff16611108565b600960009054906101000a900460ff165b905060005b838390508161ffff1610156112d957600084848361ffff1681811061113557611134614916565b5b90506040020180360381019061114b91906149e2565b9050600a6000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000826020015167ffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156111f4576040517fa342934900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600a6000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000836020015167ffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550806020015167ffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff167ffe6ae5739c1d6d64298f06f3740a387add6ff26d92ce81a5c93f02ee4226ab9960405160405180910390a35080806112d190614a0f565b91505061110d565b50428460400160208101906112ee9190614778565b63ffffffff16101561132c576040517fc4e9f92900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61133884848433612077565b61136e576040517f07f0245a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113ce846000013585806020019061138691906147b4565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611cdc565b611404576040517f03a5536400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005600085606001602081019061141b9190614857565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611482576040517f4ab4c93000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82829050600760008360ff1660ff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff166114f891906146d9565b92506101000a81548161ffff021916908361ffff16021790555060016005600086606001602081019061152b9190614857565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611585338260ff168585905060405180602001604052806000815250611d3e565b50505050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000807f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090509091565b600080600960009054906101000a900460ff169150600960019054906101000a900460ff1690509091565b611635611eee565b818160089182611646929190614bd1565b505050565b8161165581611a99565b61165f83836121db565b505050565b600060036000838152602001908152602001600020549050919050565b611689611eee565b81600960006101000a81548160ff021916908360ff16021790555080600960016101000a81548160ff021916908360ff1602179055505050565b6116cb611eee565b81819050848490501461170a576040517fcaa9014f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b848490508160ff16101561179c5782828260ff1681811061173157611730614916565b5b9050606002016006600087878560ff1681811061175157611750614916565b5b9050602002016020810190611766919061375e565b60ff1660ff16815260200190815260200160002081816117869190614e6f565b905050808061179490614e7d565b91505061170d565b5050505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000600960009054906101000a900460ff1660ff168260ff16141580156118735750600960019054906101000a900460ff1660ff168260ff1614155b80156118845750611883826121f1565b5b9050919050565b843373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146118c9576118c833611a99565b5b6118d6868686868661222b565b505050505050565b6118e6611eee565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611955576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161194c90614f18565b60405180910390fd5b61195e81611f6c565b50565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6060600060016119da846122cc565b01905060008167ffffffffffffffff8111156119f9576119f8613883565b5b6040519080825280601f01601f191660200182016040528015611a2b5781602001600182028036833780820191505090505b509050600082602001820190505b600115611a8e578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581611a8257611a81614f38565b5b04945060008503611a39575b819350505050919050565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611b93576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401611b10929190614f67565b602060405180830381865afa158015611b2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b519190614fa5565b611b9257806040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401611b899190614013565b60405180910390fd5b5b50565b611b9e61241f565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161480611be45750611be385611bde61241f565b6117a3565b5b611c23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1a90615044565b60405180910390fd5b611c308585858585612427565b5050505050565b6000807f0000000000000000000000000000000000000000000000000000000000000000834686886080016020810190611c71919061470f565b896040016020810190611c849190614778565b8a6060016020810190611c979190614857565b604051602001611cad97969594939291906151a5565b604051602081830303815290604052905060008180519060200120905085600001358114925050509392505050565b6000611ce88383612748565b73ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1614905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611dad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da490615298565b60405180910390fd5b6000611db761241f565b90506000611dc48561276f565b90506000611dd18561276f565b9050611de2836000898585896127e9565b8460008088815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611e4191906146a5565b925050819055508673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628989604051611ebf9291906152b8565b60405180910390a4611ed6836000898585896127ff565b611ee583600089898989612807565b50505050505050565b611ef661241f565b73ffffffffffffffffffffffffffffffffffffffff16611f1461158b565b73ffffffffffffffffffffffffffffffffffffffff1614611f6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f619061532d565b60405180910390fd5b565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080610e10620151806138404261204a91906146a5565b612054919061534d565b61205e919061537e565b9050600681101580156120715750601281105b91505090565b600060608060005b868690508161ffff161015612145578287878361ffff168181106120a6576120a5614916565b5b90506040020160000160208101906120be919061441d565b6040516020016120cf9291906153f6565b60405160208183030381529060405292508187878361ffff168181106120f8576120f7614916565b5b90506040020160200160208101906121109190614857565b60405160200161212192919061541e565b6040516020818303038152906040529150808061213d90614a0f565b91505061207f565b5060007f0000000000000000000000000000000000000000000000000000000000000000854685858c60400160208101906121809190614778565b8d60600160208101906121939190614857565b6040516020016121a99796959493929190615446565b604051602081830303815290604052905060008180519060200120905088600001358114945050505050949350505050565b6121ed6121e661241f565b83836129de565b5050565b600080600660008460ff1660ff16815260200190815260200160002060000160009054906101000a900461ffff1661ffff16119050919050565b61223361241f565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16148061227957506122788561227361241f565b6117a3565b5b6122b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122af90615044565b60405180910390fd5b6122c58585858585612b4a565b5050505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061232a577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816123205761231f614f38565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612367576d04ee2d6d415b85acef8100000000838161235d5761235c614f38565b5b0492506020810190505b662386f26fc10000831061239657662386f26fc10000838161238c5761238b614f38565b5b0492506010810190505b6305f5e10083106123bf576305f5e10083816123b5576123b4614f38565b5b0492506008810190505b61271083106123e45761271083816123da576123d9614f38565b5b0492506004810190505b6064831061240757606483816123fd576123fc614f38565b5b0492506002810190505b600a8310612416576001810190505b80915050919050565b600033905090565b815183511461246b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161246290615531565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036124da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124d1906155c3565b60405180910390fd5b60006124e461241f565b90506124f48187878787876127e9565b60005b84518110156126a557600085828151811061251557612514614916565b5b60200260200101519050600085838151811061253457612533614916565b5b60200260200101519050600080600084815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050818110156125d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125cc90615655565b60405180910390fd5b81810360008085815260200190815260200160002060008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508160008085815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461268a91906146a5565b925050819055505050508061269e90614945565b90506124f7565b508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161271c929190615675565b60405180910390a46127328187878787876127ff565b612740818787878787612de5565b505050505050565b60008060006127578585612fbc565b915091506127648161300d565b819250505092915050565b60606000600167ffffffffffffffff81111561278e5761278d613883565b5b6040519080825280602002602001820160405280156127bc5781602001602082028036833780820191505090505b50905082816000815181106127d4576127d3614916565b5b60200260200101818152505080915050919050565b6127f7868686868686613173565b505050505050565b505050505050565b6128268473ffffffffffffffffffffffffffffffffffffffff16613343565b156129d6578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b815260040161286c9594939291906156f6565b6020604051808303816000875af19250505080156128a857506040513d601f19601f820116820180604052508101906128a59190615765565b60015b61294d576128b461579f565b806308c379a00361291057506128c86157c1565b806128d35750612912565b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129079190613703565b60405180910390fd5b505b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612944906158c3565b60405180910390fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146129d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129cb90615955565b60405180910390fd5b505b505050505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612a4c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a43906159e7565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612b3d919061362b565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612bb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb0906155c3565b60405180910390fd5b6000612bc361241f565b90506000612bd08561276f565b90506000612bdd8561276f565b9050612bed8389898585896127e9565b600080600088815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905085811015612c84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c7b90615655565b60405180910390fd5b85810360008089815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508560008089815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612d3991906146a5565b925050819055508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628a8a604051612db69291906152b8565b60405180910390a4612dcc848a8a86868a6127ff565b612dda848a8a8a8a8a612807565b505050505050505050565b612e048473ffffffffffffffffffffffffffffffffffffffff16613343565b15612fb4578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b8152600401612e4a959493929190615a07565b6020604051808303816000875af1925050508015612e8657506040513d601f19601f82011682018060405250810190612e839190615765565b60015b612f2b57612e9261579f565b806308c379a003612eee5750612ea66157c1565b80612eb15750612ef0565b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ee59190613703565b60405180910390fd5b505b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f22906158c3565b60405180910390fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612fb2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fa990615955565b60405180910390fd5b505b505050505050565b6000806041835103612ffd5760008060006020860151925060408601519150606086015160001a9050612ff187828585613366565b94509450505050613006565b60006002915091505b9250929050565b6000600481111561302157613020615a6f565b5b81600481111561303457613033615a6f565b5b0315613170576001600481111561304e5761304d615a6f565b5b81600481111561306157613060615a6f565b5b036130a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161309890615aea565b60405180910390fd5b600260048111156130b5576130b4615a6f565b5b8160048111156130c8576130c7615a6f565b5b03613108576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130ff90615b56565b60405180910390fd5b6003600481111561311c5761311b615a6f565b5b81600481111561312f5761312e615a6f565b5b0361316f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161316690615be8565b60405180910390fd5b5b50565b613181868686868686613448565b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036132325760005b8351811015613230578281815181106131d4576131d3614916565b5b6020026020010151600360008684815181106131f3576131f2614916565b5b60200260200101518152602001908152602001600020600082825461321891906146a5565b925050819055508061322990614945565b90506131b8565b505b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361333b5760005b835181101561333957600084828151811061328757613286614916565b5b6020026020010151905060008483815181106132a6576132a5614916565b5b602002602001015190506000600360008481526020019081526020016000205490508181101561330b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161330290615c7a565b60405180910390fd5b81810360036000858152602001908152602001600020819055505050508061333290614945565b9050613269565b505b505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156133a157600060039150915061343f565b6000600187878787604051600081526020016040526040516133c69493929190615cb3565b6020604051602081039080840390855afa1580156133e8573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036134365760006001925092505061343f565b80600092509250505b94509492505050565b505050505050565b6040518060600160405280600061ffff168152602001600061ffff168152602001600081525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006134b88261348d565b9050919050565b6134c8816134ad565b81146134d357600080fd5b50565b6000813590506134e5816134bf565b92915050565b6000819050919050565b6134fe816134eb565b811461350957600080fd5b50565b60008135905061351b816134f5565b92915050565b6000806040838503121561353857613537613483565b5b6000613546858286016134d6565b92505060206135578582860161350c565b9150509250929050565b61356a816134eb565b82525050565b60006020820190506135856000830184613561565b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6135c08161358b565b81146135cb57600080fd5b50565b6000813590506135dd816135b7565b92915050565b6000602082840312156135f9576135f8613483565b5b6000613607848285016135ce565b91505092915050565b60008115159050919050565b61362581613610565b82525050565b6000602082019050613640600083018461361c565b92915050565b60006020828403121561365c5761365b613483565b5b600061366a8482850161350c565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156136ad578082015181840152602081019050613692565b60008484015250505050565b6000601f19601f8301169050919050565b60006136d582613673565b6136df818561367e565b93506136ef81856020860161368f565b6136f8816136b9565b840191505092915050565b6000602082019050818103600083015261371d81846136ca565b905092915050565b600060ff82169050919050565b61373b81613725565b811461374657600080fd5b50565b60008135905061375881613732565b92915050565b60006020828403121561377457613773613483565b5b600061378284828501613749565b91505092915050565b600061ffff82169050919050565b6137a28161378b565b82525050565b6137b1816134eb565b82525050565b6060820160008201516137cd6000850182613799565b5060208201516137e06020850182613799565b5060408201516137f360408501826137a8565b50505050565b600060608201905061380e60008301846137b7565b92915050565b6000806040838503121561382b5761382a613483565b5b600061383985828601613749565b925050602061384a858286016134d6565b9150509250929050565b61385d8161378b565b82525050565b60006020820190506138786000830184613854565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6138bb826136b9565b810181811067ffffffffffffffff821117156138da576138d9613883565b5b80604052505050565b60006138ed613479565b90506138f982826138b2565b919050565b600067ffffffffffffffff82111561391957613918613883565b5b602082029050602081019050919050565b600080fd5b600061394261393d846138fe565b6138e3565b905080838252602082019050602084028301858111156139655761396461392a565b5b835b8181101561398e578061397a888261350c565b845260208401935050602081019050613967565b5050509392505050565b600082601f8301126139ad576139ac61387e565b5b81356139bd84826020860161392f565b91505092915050565b600080fd5b600067ffffffffffffffff8211156139e6576139e5613883565b5b6139ef826136b9565b9050602081019050919050565b82818337600083830152505050565b6000613a1e613a19846139cb565b6138e3565b905082815260208101848484011115613a3a57613a396139c6565b5b613a458482856139fc565b509392505050565b600082601f830112613a6257613a6161387e565b5b8135613a72848260208601613a0b565b91505092915050565b600080600080600060a08688031215613a9757613a96613483565b5b6000613aa5888289016134d6565b9550506020613ab6888289016134d6565b945050604086013567ffffffffffffffff811115613ad757613ad6613488565b5b613ae388828901613998565b935050606086013567ffffffffffffffff811115613b0457613b03613488565b5b613b1088828901613998565b925050608086013567ffffffffffffffff811115613b3157613b30613488565b5b613b3d88828901613a4d565b9150509295509295909350565b600080fd5b600060a08284031215613b6557613b64613b4a565b5b81905092915050565b613b778161378b565b8114613b8257600080fd5b50565b600081359050613b9481613b6e565b92915050565b60008060008060808587031215613bb457613bb3613483565b5b600085013567ffffffffffffffff811115613bd257613bd1613488565b5b613bde87828801613b4f565b9450506020613bef878288016134d6565b9350506040613c0087828801613749565b9250506060613c1187828801613b85565b91505092959194509250565b6000819050919050565b6000613c42613c3d613c388461348d565b613c1d565b61348d565b9050919050565b6000613c5482613c27565b9050919050565b6000613c6682613c49565b9050919050565b613c7681613c5b565b82525050565b6000602082019050613c916000830184613c6d565b92915050565b600067ffffffffffffffff821115613cb257613cb1613883565b5b602082029050602081019050919050565b6000613cd6613cd184613c97565b6138e3565b90508083825260208201905060208402830185811115613cf957613cf861392a565b5b835b81811015613d225780613d0e88826134d6565b845260208401935050602081019050613cfb565b5050509392505050565b600082601f830112613d4157613d4061387e565b5b8135613d51848260208601613cc3565b91505092915050565b60008060408385031215613d7157613d70613483565b5b600083013567ffffffffffffffff811115613d8f57613d8e613488565b5b613d9b85828601613d2c565b925050602083013567ffffffffffffffff811115613dbc57613dbb613488565b5b613dc885828601613998565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000613e0a83836137a8565b60208301905092915050565b6000602082019050919050565b6000613e2e82613dd2565b613e388185613ddd565b9350613e4383613dee565b8060005b83811015613e74578151613e5b8882613dfe565b9750613e6683613e16565b925050600181019050613e47565b5085935050505092915050565b60006020820190508181036000830152613e9b8184613e23565b905092915050565b6000613eae8261348d565b9050919050565b613ebe81613ea3565b8114613ec957600080fd5b50565b600081359050613edb81613eb5565b92915050565b600060208284031215613ef757613ef6613483565b5b6000613f0584828501613ecc565b91505092915050565b600060808284031215613f2457613f23613b4a565b5b81905092915050565b600080fd5b60008083601f840112613f4857613f4761387e565b5b8235905067ffffffffffffffff811115613f6557613f64613f2d565b5b602083019150836040820283011115613f8157613f8061392a565b5b9250929050565b600080600060408486031215613fa157613fa0613483565b5b600084013567ffffffffffffffff811115613fbf57613fbe613488565b5b613fcb86828701613f0e565b935050602084013567ffffffffffffffff811115613fec57613feb613488565b5b613ff886828701613f32565b92509250509250925092565b61400d816134ad565b82525050565b60006020820190506140286000830184614004565b92915050565b60007fffffffffffffffff00000000000000000000000000000000000000000000000082169050919050565b6140638161402e565b82525050565b600060408201905061407e600083018561405a565b61408b6020830184614004565b9392505050565b61409b81613725565b82525050565b60006040820190506140b66000830185614092565b6140c36020830184614092565b9392505050565b60008083601f8401126140e0576140df61387e565b5b8235905067ffffffffffffffff8111156140fd576140fc613f2d565b5b6020830191508360018202830111156141195761411861392a565b5b9250929050565b6000806020838503121561413757614136613483565b5b600083013567ffffffffffffffff81111561415557614154613488565b5b614161858286016140ca565b92509250509250929050565b61417681613610565b811461418157600080fd5b50565b6000813590506141938161416d565b92915050565b600080604083850312156141b0576141af613483565b5b60006141be858286016134d6565b92505060206141cf85828601614184565b9150509250929050565b600080604083850312156141f0576141ef613483565b5b60006141fe85828601613749565b925050602061420f85828601613749565b9150509250929050565b60008083601f84011261422f5761422e61387e565b5b8235905067ffffffffffffffff81111561424c5761424b613f2d565b5b6020830191508360208202830111156142685761426761392a565b5b9250929050565b60008083601f8401126142855761428461387e565b5b8235905067ffffffffffffffff8111156142a2576142a1613f2d565b5b6020830191508360608202830111156142be576142bd61392a565b5b9250929050565b600080600080604085870312156142df576142de613483565b5b600085013567ffffffffffffffff8111156142fd576142fc613488565b5b61430987828801614219565b9450945050602085013567ffffffffffffffff81111561432c5761432b613488565b5b6143388782880161426f565b925092505092959194509250565b6000806040838503121561435d5761435c613483565b5b600061436b858286016134d6565b925050602061437c858286016134d6565b9150509250929050565b600080600080600060a086880312156143a2576143a1613483565b5b60006143b0888289016134d6565b95505060206143c1888289016134d6565b94505060406143d28882890161350c565b93505060606143e38882890161350c565b925050608086013567ffffffffffffffff81111561440457614403613488565b5b61441088828901613a4d565b9150509295509295909350565b60006020828403121561443357614432613483565b5b6000614441848285016134d6565b91505092915050565b7f455243313135353a2061646472657373207a65726f206973206e6f742061207660008201527f616c6964206f776e657200000000000000000000000000000000000000000000602082015250565b60006144a6602a8361367e565b91506144b18261444a565b604082019050919050565b600060208201905081810360008301526144d581614499565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061452357607f821691505b602082108103614536576145356144dc565b5b50919050565b600081905092915050565b60008190508160005260206000209050919050565b600081546145698161450b565b614573818661453c565b9450600182166000811461458e57600181146145a3576145d6565b60ff19831686528115158202860193506145d6565b6145ac85614547565b60005b838110156145ce578154818901526001820191506020810190506145af565b838801955050505b50505092915050565b60006145ea82613673565b6145f4818561453c565b935061460481856020860161368f565b80840191505092915050565b600061461c828561455c565b915061462882846145df565b91508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061466e826134eb565b9150614679836134eb565b9250828202614687816134eb565b9150828204841483151761469e5761469d614634565b5b5092915050565b60006146b0826134eb565b91506146bb836134eb565b92508282019050808211156146d3576146d2614634565b5b92915050565b60006146e48261378b565b91506146ef8361378b565b9250828201905061ffff81111561470957614708614634565b5b92915050565b60006020828403121561472557614724613483565b5b600061473384828501613b85565b91505092915050565b600063ffffffff82169050919050565b6147558161473c565b811461476057600080fd5b50565b6000813590506147728161474c565b92915050565b60006020828403121561478e5761478d613483565b5b600061479c84828501614763565b91505092915050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126147d1576147d06147a5565b5b80840192508235915067ffffffffffffffff8211156147f3576147f26147aa565b5b60208301925060018202360383131561480f5761480e6147af565b5b509250929050565b600067ffffffffffffffff82169050919050565b61483481614817565b811461483f57600080fd5b50565b6000813590506148518161482b565b92915050565b60006020828403121561486d5761486c613483565b5b600061487b84828501614842565b91505092915050565b7f455243313135353a206163636f756e747320616e6420696473206c656e67746860008201527f206d69736d617463680000000000000000000000000000000000000000000000602082015250565b60006148e060298361367e565b91506148eb82614884565b604082019050919050565b6000602082019050818103600083015261490f816148d3565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000614950826134eb565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361498257614981614634565b5b600182019050919050565b600080fd5b6000604082840312156149a8576149a761498d565b5b6149b260406138e3565b905060006149c2848285016134d6565b60008301525060206149d684828501614842565b60208301525092915050565b6000604082840312156149f8576149f7613483565b5b6000614a0684828501614992565b91505092915050565b6000614a1a8261378b565b915061ffff8203614a2e57614a2d614634565b5b600182019050919050565b600082905092915050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614a917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614a54565b614a9b8683614a54565b95508019841693508086168417925050509392505050565b6000614ace614ac9614ac4846134eb565b613c1d565b6134eb565b9050919050565b6000819050919050565b614ae883614ab3565b614afc614af482614ad5565b848454614a61565b825550505050565b600090565b614b11614b04565b614b1c818484614adf565b505050565b5b81811015614b4057614b35600082614b09565b600181019050614b22565b5050565b601f821115614b8557614b5681614547565b614b5f84614a44565b81016020851015614b6e578190505b614b82614b7a85614a44565b830182614b21565b50505b505050565b600082821c905092915050565b6000614ba860001984600802614b8a565b1980831691505092915050565b6000614bc18383614b97565b9150826002028217905092915050565b614bdb8383614a39565b67ffffffffffffffff811115614bf457614bf3613883565b5b614bfe825461450b565b614c09828285614b44565b6000601f831160018114614c385760008415614c26578287013590505b614c308582614bb5565b865550614c98565b601f198416614c4686614547565b60005b82811015614c6e57848901358255600182019150602085019450602081019050614c49565b86831015614c8b5784890135614c87601f891682614b97565b8355505b6001600288020188555050505b50505050505050565b60008135614cae81613b6e565b80915050919050565b60008160001b9050919050565b600061ffff614cd284614cb7565b9350801983169250808416831791505092915050565b6000614d03614cfe614cf98461378b565b613c1d565b61378b565b9050919050565b6000819050919050565b614d1d82614ce8565b614d30614d2982614d0a565b8354614cc4565b8255505050565b60008160101b9050919050565b600063ffff0000614d5484614d37565b9350801983169250808416831791505092915050565b614d7382614ce8565b614d86614d7f82614d0a565b8354614d44565b8255505050565b60008135614d9a816134f5565b80915050919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff614dcf84614cb7565b9350801983169250808416831791505092915050565b614dee82614ab3565b614e01614dfa82614ad5565b8354614da3565b8255505050565b600081016000830180614e1a81614ca1565b9050614e268184614d14565b505050600081016020830180614e3b81614ca1565b9050614e478184614d6a565b505050600181016040830180614e5c81614d8d565b9050614e688184614de5565b5050505050565b614e798282614e08565b5050565b6000614e8882613725565b915060ff8203614e9b57614e9a614634565b5b600182019050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614f0260268361367e565b9150614f0d82614ea6565b604082019050919050565b60006020820190508181036000830152614f3181614ef5565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000604082019050614f7c6000830185614004565b614f896020830184614004565b9392505050565b600081519050614f9f8161416d565b92915050565b600060208284031215614fbb57614fba613483565b5b6000614fc984828501614f90565b91505092915050565b7f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60008201527f6572206f7220617070726f766564000000000000000000000000000000000000602082015250565b600061502e602e8361367e565b915061503982614fd2565b604082019050919050565b6000602082019050818103600083015261505d81615021565b9050919050565b6000819050919050565b61507f61507a8261402e565b615064565b82525050565b60008160601b9050919050565b600061509d82615085565b9050919050565b60006150af82615092565b9050919050565b6150c76150c2826134ad565b6150a4565b82525050565b60008160c01b9050919050565b60006150e5826150cd565b9050919050565b6150fd6150f882614817565b6150da565b82525050565b60008160f81b9050919050565b600061511b82615103565b9050919050565b61513361512e82613725565b615110565b82525050565b60008160f01b9050919050565b600061515182615139565b9050919050565b6151696151648261378b565b615146565b82525050565b60008160e01b9050919050565b60006151878261516f565b9050919050565b61519f61519a8261473c565b61517c565b82525050565b60006151b1828a61506e565b6008820191506151c182896150b6565b6014820191506151d182886150ec565b6008820191506151e18287615122565b6001820191506151f18286615158565b600282019150615201828561518e565b60048201915061521182846150ec565b60088201915081905098975050505050505050565b7f455243313135353a206d696e7420746f20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b600061528260218361367e565b915061528d82615226565b604082019050919050565b600060208201905081810360008301526152b181615275565b9050919050565b60006040820190506152cd6000830185613561565b6152da6020830184613561565b9392505050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061531760208361367e565b9150615322826152e1565b602082019050919050565b600060208201905081810360008301526153468161530a565b9050919050565b6000615358826134eb565b9150615363836134eb565b92508261537357615372614f38565b5b828206905092915050565b6000615389826134eb565b9150615394836134eb565b9250826153a4576153a3614f38565b5b828204905092915050565b600081519050919050565b600081905092915050565b60006153d0826153af565b6153da81856153ba565b93506153ea81856020860161368f565b80840191505092915050565b600061540282856153c5565b915061540e82846150b6565b6014820191508190509392505050565b600061542a82856153c5565b915061543682846150ec565b6008820191508190509392505050565b6000615452828a61506e565b60088201915061546282896150b6565b60148201915061547282886150ec565b60088201915061548282876153c5565b915061548e82866153c5565b915061549a828561518e565b6004820191506154aa82846150ec565b60088201915081905098975050505050505050565b7f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060008201527f6d69736d61746368000000000000000000000000000000000000000000000000602082015250565b600061551b60288361367e565b9150615526826154bf565b604082019050919050565b6000602082019050818103600083015261554a8161550e565b9050919050565b7f455243313135353a207472616e7366657220746f20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b60006155ad60258361367e565b91506155b882615551565b604082019050919050565b600060208201905081810360008301526155dc816155a0565b9050919050565b7f455243313135353a20696e73756666696369656e742062616c616e636520666f60008201527f72207472616e7366657200000000000000000000000000000000000000000000602082015250565b600061563f602a8361367e565b915061564a826155e3565b604082019050919050565b6000602082019050818103600083015261566e81615632565b9050919050565b6000604082019050818103600083015261568f8185613e23565b905081810360208301526156a38184613e23565b90509392505050565b600082825260208201905092915050565b60006156c8826153af565b6156d281856156ac565b93506156e281856020860161368f565b6156eb816136b9565b840191505092915050565b600060a08201905061570b6000830188614004565b6157186020830187614004565b6157256040830186613561565b6157326060830185613561565b818103608083015261574481846156bd565b90509695505050505050565b60008151905061575f816135b7565b92915050565b60006020828403121561577b5761577a613483565b5b600061578984828501615750565b91505092915050565b60008160e01c9050919050565b600060033d11156157be5760046000803e6157bb600051615792565b90505b90565b600060443d1061584e576157d3613479565b60043d036004823e80513d602482011167ffffffffffffffff821117156157fb57505061584e565b808201805167ffffffffffffffff811115615819575050505061584e565b80602083010160043d03850181111561583657505050505061584e565b615845826020018501866138b2565b82955050505050505b90565b7f455243313135353a207472616e7366657220746f206e6f6e2d4552433131353560008201527f526563656976657220696d706c656d656e746572000000000000000000000000602082015250565b60006158ad60348361367e565b91506158b882615851565b604082019050919050565b600060208201905081810360008301526158dc816158a0565b9050919050565b7f455243313135353a204552433131353552656365697665722072656a6563746560008201527f6420746f6b656e73000000000000000000000000000000000000000000000000602082015250565b600061593f60288361367e565b915061594a826158e3565b604082019050919050565b6000602082019050818103600083015261596e81615932565b9050919050565b7f455243313135353a2073657474696e6720617070726f76616c2073746174757360008201527f20666f722073656c660000000000000000000000000000000000000000000000602082015250565b60006159d160298361367e565b91506159dc82615975565b604082019050919050565b60006020820190508181036000830152615a00816159c4565b9050919050565b600060a082019050615a1c6000830188614004565b615a296020830187614004565b8181036040830152615a3b8186613e23565b90508181036060830152615a4f8185613e23565b90508181036080830152615a6381846156bd565b90509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b6000615ad460188361367e565b9150615adf82615a9e565b602082019050919050565b60006020820190508181036000830152615b0381615ac7565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000615b40601f8361367e565b9150615b4b82615b0a565b602082019050919050565b60006020820190508181036000830152615b6f81615b33565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000615bd260228361367e565b9150615bdd82615b76565b604082019050919050565b60006020820190508181036000830152615c0181615bc5565b9050919050565b7f455243313135353a206275726e20616d6f756e74206578636565647320746f7460008201527f616c537570706c79000000000000000000000000000000000000000000000000602082015250565b6000615c6460288361367e565b9150615c6f82615c08565b604082019050919050565b60006020820190508181036000830152615c9381615c57565b9050919050565b6000819050919050565b615cad81615c9a565b82525050565b6000608082019050615cc86000830187615ca4565b615cd56020830186614092565b615ce26040830185615ca4565b615cef6060830184615ca4565b9594505050505056fea2646970667358221220c9dfde0ff34e49c0f79766f3537319a7bdae6e7ea5ef9392a08a1db0aadf2ebc64736f6c63430008110033
Deployed Bytecode
0x6080604052600436106101655760003560e01c80638c02f79b116100d1578063bd85b0391161008a578063e985e9c511610064578063e985e9c514610552578063f006ad971461058f578063f242432a146105cc578063f2fde38b146105f557610165565b8063bd85b039146104c3578063bef98d4b14610500578063e5b8fb921461052957610165565b80638c02f79b146103c55780638da5cb5b146103ee578063900af1921461041957806390b7178e14610445578063a0bcfc7f14610471578063a22cb4651461049a57610165565b80634163933a116101235780634163933a146102c457806341f43434146102e05780634e1273f41461030b5780634f558e791461034857806351cff8d914610385578063715018a6146103ae57610165565b8062fdd58e1461016a57806301ffc9a7146101a75780630e89341c146101e457806314119bb714610221578063235f0e931461025e5780632eb2c2d61461029b575b600080fd5b34801561017657600080fd5b50610191600480360381019061018c9190613521565b61061e565b60405161019e9190613570565b60405180910390f35b3480156101b357600080fd5b506101ce60048036038101906101c991906135e3565b6106e6565b6040516101db919061362b565b60405180910390f35b3480156101f057600080fd5b5061020b60048036038101906102069190613646565b6107c8565b6040516102189190613703565b60405180910390f35b34801561022d57600080fd5b506102486004803603810190610243919061375e565b6107fc565b60405161025591906137f9565b60405180910390f35b34801561026a57600080fd5b5061028560048036038101906102809190613814565b610879565b6040516102929190613863565b60405180910390f35b3480156102a757600080fd5b506102c260048036038101906102bd9190613a7b565b6108e8565b005b6102de60048036038101906102d99190613b9a565b61093b565b005b3480156102ec57600080fd5b506102f5610e4c565b6040516103029190613c7c565b60405180910390f35b34801561031757600080fd5b50610332600480360381019061032d9190613d5a565b610e5e565b60405161033f9190613e81565b60405180910390f35b34801561035457600080fd5b5061036f600480360381019061036a9190613646565b610f77565b60405161037c919061362b565b60405180910390f35b34801561039157600080fd5b506103ac60048036038101906103a79190613ee1565b610f8b565b005b3480156103ba57600080fd5b506103c3611083565b005b3480156103d157600080fd5b506103ec60048036038101906103e79190613f88565b611097565b005b3480156103fa57600080fd5b5061040361158b565b6040516104109190614013565b60405180910390f35b34801561042557600080fd5b5061042e6115b5565b60405161043c929190614069565b60405180910390f35b34801561045157600080fd5b5061045a611602565b6040516104689291906140a1565b60405180910390f35b34801561047d57600080fd5b5061049860048036038101906104939190614120565b61162d565b005b3480156104a657600080fd5b506104c160048036038101906104bc9190614199565b61164b565b005b3480156104cf57600080fd5b506104ea60048036038101906104e59190613646565b611664565b6040516104f79190613570565b60405180910390f35b34801561050c57600080fd5b50610527600480360381019061052291906141d9565b611681565b005b34801561053557600080fd5b50610550600480360381019061054b91906142c5565b6116c3565b005b34801561055e57600080fd5b5061057960048036038101906105749190614346565b6117a3565b604051610586919061362b565b60405180910390f35b34801561059b57600080fd5b506105b660048036038101906105b1919061375e565b611837565b6040516105c3919061362b565b60405180910390f35b3480156105d857600080fd5b506105f360048036038101906105ee9190614386565b61188b565b005b34801561060157600080fd5b5061061c6004803603810190610617919061441d565b6118de565b005b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361068e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610685906144bc565b60405180910390fd5b60008083815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b60007fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107b157507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806107c157506107c082611961565b5b9050919050565b606060086107d5836119cb565b6040516020016107e6929190614610565b6040516020818303038152906040529050919050565b610804613450565b600660008360ff1660ff1681526020019081526020016000206040518060600160405290816000820160009054906101000a900461ffff1661ffff1661ffff1681526020016000820160029054906101000a900461ffff1661ffff1661ffff1681526020016001820154815250509050919050565b6000600760008460ff1660ff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff16905092915050565b843373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109265761092533611a99565b5b6109338686868686611b96565b505050505050565b6000600660008460ff1660ff1681526020019081526020016000206040518060600160405290816000820160009054906101000a900461ffff1661ffff1661ffff1681526020016000820160029054906101000a900461ffff1661ffff1661ffff16815260200160018201548152505090506109b683611837565b6109ec576040517fee19d49100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8161ffff168160400151610a009190614663565b3414610a38576040517f26c3439000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015161ffff168261ffff16610a528560ff16611664565b610a5c91906146a5565b1115610a94576040517fd8ea507600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015161ffff1682600760008660ff1660ff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff16610b0d91906146d9565b61ffff161115610b49576040517f5b3e6f0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846080016020810190610b5c919061470f565b61ffff168261ffff161115610b9d576040517f8d515e9c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42856040016020810190610bb19190614778565b63ffffffff161015610bef576040517f1eee9c0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610bfa858486611c37565b610c30576040517fff39ee9500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c908560000135868060200190610c4891906147b4565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611cdc565b610cc6576040517f1490dab400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60056000866060016020810190610cdd9190614857565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610d44576040517fa2a6490500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600760008560ff1660ff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff16610db791906146d9565b92506101000a81548161ffff021916908361ffff160217905550600160056000876060016020810190610dea9190614857565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550610e45848460ff168461ffff1660405180602001604052806000815250611d3e565b5050505050565b6daaeb6d7670e522a718067333cd4e81565b60608151835114610ea4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e9b906148f6565b60405180910390fd5b6000835167ffffffffffffffff811115610ec157610ec0613883565b5b604051908082528060200260200182016040528015610eef5781602001602082028036833780820191505090505b50905060005b8451811015610f6c57610f3c858281518110610f1457610f13614916565b5b6020026020010151858381518110610f2f57610f2e614916565b5b602002602001015161061e565b828281518110610f4f57610f4e614916565b5b60200260200101818152505080610f6590614945565b9050610ef5565b508091505092915050565b600080610f8383611664565b119050919050565b610f93611eee565b600047905060008103610fd2576040517f895dcf4500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611038576040517fcaa9014f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561107e573d6000803e3d6000fd5b505050565b61108b611eee565b6110956000611f6c565b565b600082829050036110d4576040517fd643e0ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006110de612032565b6110f757600960019054906101000a900460ff16611108565b600960009054906101000a900460ff165b905060005b838390508161ffff1610156112d957600084848361ffff1681811061113557611134614916565b5b90506040020180360381019061114b91906149e2565b9050600a6000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000826020015167ffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156111f4576040517fa342934900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600a6000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000836020015167ffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550806020015167ffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff167ffe6ae5739c1d6d64298f06f3740a387add6ff26d92ce81a5c93f02ee4226ab9960405160405180910390a35080806112d190614a0f565b91505061110d565b50428460400160208101906112ee9190614778565b63ffffffff16101561132c576040517fc4e9f92900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61133884848433612077565b61136e576040517f07f0245a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113ce846000013585806020019061138691906147b4565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611cdc565b611404576040517f03a5536400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005600085606001602081019061141b9190614857565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611482576040517f4ab4c93000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82829050600760008360ff1660ff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff166114f891906146d9565b92506101000a81548161ffff021916908361ffff16021790555060016005600086606001602081019061152b9190614857565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611585338260ff168585905060405180602001604052806000815250611d3e565b50505050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000807faca187d2a59b04b400000000000000000000000000000000000000000000000091507f00000000000000000000000089994365e8538f61a906c84cb15b6d415051fed090509091565b600080600960009054906101000a900460ff169150600960019054906101000a900460ff1690509091565b611635611eee565b818160089182611646929190614bd1565b505050565b8161165581611a99565b61165f83836121db565b505050565b600060036000838152602001908152602001600020549050919050565b611689611eee565b81600960006101000a81548160ff021916908360ff16021790555080600960016101000a81548160ff021916908360ff1602179055505050565b6116cb611eee565b81819050848490501461170a576040517fcaa9014f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b848490508160ff16101561179c5782828260ff1681811061173157611730614916565b5b9050606002016006600087878560ff1681811061175157611750614916565b5b9050602002016020810190611766919061375e565b60ff1660ff16815260200190815260200160002081816117869190614e6f565b905050808061179490614e7d565b91505061170d565b5050505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000600960009054906101000a900460ff1660ff168260ff16141580156118735750600960019054906101000a900460ff1660ff168260ff1614155b80156118845750611883826121f1565b5b9050919050565b843373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146118c9576118c833611a99565b5b6118d6868686868661222b565b505050505050565b6118e6611eee565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611955576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161194c90614f18565b60405180910390fd5b61195e81611f6c565b50565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6060600060016119da846122cc565b01905060008167ffffffffffffffff8111156119f9576119f8613883565b5b6040519080825280601f01601f191660200182016040528015611a2b5781602001600182028036833780820191505090505b509050600082602001820190505b600115611a8e578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581611a8257611a81614f38565b5b04945060008503611a39575b819350505050919050565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611b93576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401611b10929190614f67565b602060405180830381865afa158015611b2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b519190614fa5565b611b9257806040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401611b899190614013565b60405180910390fd5b5b50565b611b9e61241f565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161480611be45750611be385611bde61241f565b6117a3565b5b611c23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1a90615044565b60405180910390fd5b611c308585858585612427565b5050505050565b6000807faca187d2a59b04b4000000000000000000000000000000000000000000000000834686886080016020810190611c71919061470f565b896040016020810190611c849190614778565b8a6060016020810190611c979190614857565b604051602001611cad97969594939291906151a5565b604051602081830303815290604052905060008180519060200120905085600001358114925050509392505050565b6000611ce88383612748565b73ffffffffffffffffffffffffffffffffffffffff167f00000000000000000000000089994365e8538f61a906c84cb15b6d415051fed073ffffffffffffffffffffffffffffffffffffffff1614905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611dad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da490615298565b60405180910390fd5b6000611db761241f565b90506000611dc48561276f565b90506000611dd18561276f565b9050611de2836000898585896127e9565b8460008088815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611e4191906146a5565b925050819055508673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628989604051611ebf9291906152b8565b60405180910390a4611ed6836000898585896127ff565b611ee583600089898989612807565b50505050505050565b611ef661241f565b73ffffffffffffffffffffffffffffffffffffffff16611f1461158b565b73ffffffffffffffffffffffffffffffffffffffff1614611f6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f619061532d565b60405180910390fd5b565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080610e10620151806138404261204a91906146a5565b612054919061534d565b61205e919061537e565b9050600681101580156120715750601281105b91505090565b600060608060005b868690508161ffff161015612145578287878361ffff168181106120a6576120a5614916565b5b90506040020160000160208101906120be919061441d565b6040516020016120cf9291906153f6565b60405160208183030381529060405292508187878361ffff168181106120f8576120f7614916565b5b90506040020160200160208101906121109190614857565b60405160200161212192919061541e565b6040516020818303038152906040529150808061213d90614a0f565b91505061207f565b5060007faca187d2a59b04b4000000000000000000000000000000000000000000000000854685858c60400160208101906121809190614778565b8d60600160208101906121939190614857565b6040516020016121a99796959493929190615446565b604051602081830303815290604052905060008180519060200120905088600001358114945050505050949350505050565b6121ed6121e661241f565b83836129de565b5050565b600080600660008460ff1660ff16815260200190815260200160002060000160009054906101000a900461ffff1661ffff16119050919050565b61223361241f565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16148061227957506122788561227361241f565b6117a3565b5b6122b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122af90615044565b60405180910390fd5b6122c58585858585612b4a565b5050505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061232a577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816123205761231f614f38565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612367576d04ee2d6d415b85acef8100000000838161235d5761235c614f38565b5b0492506020810190505b662386f26fc10000831061239657662386f26fc10000838161238c5761238b614f38565b5b0492506010810190505b6305f5e10083106123bf576305f5e10083816123b5576123b4614f38565b5b0492506008810190505b61271083106123e45761271083816123da576123d9614f38565b5b0492506004810190505b6064831061240757606483816123fd576123fc614f38565b5b0492506002810190505b600a8310612416576001810190505b80915050919050565b600033905090565b815183511461246b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161246290615531565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036124da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124d1906155c3565b60405180910390fd5b60006124e461241f565b90506124f48187878787876127e9565b60005b84518110156126a557600085828151811061251557612514614916565b5b60200260200101519050600085838151811061253457612533614916565b5b60200260200101519050600080600084815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050818110156125d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125cc90615655565b60405180910390fd5b81810360008085815260200190815260200160002060008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508160008085815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461268a91906146a5565b925050819055505050508061269e90614945565b90506124f7565b508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161271c929190615675565b60405180910390a46127328187878787876127ff565b612740818787878787612de5565b505050505050565b60008060006127578585612fbc565b915091506127648161300d565b819250505092915050565b60606000600167ffffffffffffffff81111561278e5761278d613883565b5b6040519080825280602002602001820160405280156127bc5781602001602082028036833780820191505090505b50905082816000815181106127d4576127d3614916565b5b60200260200101818152505080915050919050565b6127f7868686868686613173565b505050505050565b505050505050565b6128268473ffffffffffffffffffffffffffffffffffffffff16613343565b156129d6578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b815260040161286c9594939291906156f6565b6020604051808303816000875af19250505080156128a857506040513d601f19601f820116820180604052508101906128a59190615765565b60015b61294d576128b461579f565b806308c379a00361291057506128c86157c1565b806128d35750612912565b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129079190613703565b60405180910390fd5b505b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612944906158c3565b60405180910390fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146129d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129cb90615955565b60405180910390fd5b505b505050505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612a4c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a43906159e7565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612b3d919061362b565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612bb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb0906155c3565b60405180910390fd5b6000612bc361241f565b90506000612bd08561276f565b90506000612bdd8561276f565b9050612bed8389898585896127e9565b600080600088815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905085811015612c84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c7b90615655565b60405180910390fd5b85810360008089815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508560008089815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612d3991906146a5565b925050819055508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628a8a604051612db69291906152b8565b60405180910390a4612dcc848a8a86868a6127ff565b612dda848a8a8a8a8a612807565b505050505050505050565b612e048473ffffffffffffffffffffffffffffffffffffffff16613343565b15612fb4578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b8152600401612e4a959493929190615a07565b6020604051808303816000875af1925050508015612e8657506040513d601f19601f82011682018060405250810190612e839190615765565b60015b612f2b57612e9261579f565b806308c379a003612eee5750612ea66157c1565b80612eb15750612ef0565b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ee59190613703565b60405180910390fd5b505b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f22906158c3565b60405180910390fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612fb2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fa990615955565b60405180910390fd5b505b505050505050565b6000806041835103612ffd5760008060006020860151925060408601519150606086015160001a9050612ff187828585613366565b94509450505050613006565b60006002915091505b9250929050565b6000600481111561302157613020615a6f565b5b81600481111561303457613033615a6f565b5b0315613170576001600481111561304e5761304d615a6f565b5b81600481111561306157613060615a6f565b5b036130a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161309890615aea565b60405180910390fd5b600260048111156130b5576130b4615a6f565b5b8160048111156130c8576130c7615a6f565b5b03613108576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130ff90615b56565b60405180910390fd5b6003600481111561311c5761311b615a6f565b5b81600481111561312f5761312e615a6f565b5b0361316f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161316690615be8565b60405180910390fd5b5b50565b613181868686868686613448565b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036132325760005b8351811015613230578281815181106131d4576131d3614916565b5b6020026020010151600360008684815181106131f3576131f2614916565b5b60200260200101518152602001908152602001600020600082825461321891906146a5565b925050819055508061322990614945565b90506131b8565b505b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361333b5760005b835181101561333957600084828151811061328757613286614916565b5b6020026020010151905060008483815181106132a6576132a5614916565b5b602002602001015190506000600360008481526020019081526020016000205490508181101561330b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161330290615c7a565b60405180910390fd5b81810360036000858152602001908152602001600020819055505050508061333290614945565b9050613269565b505b505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156133a157600060039150915061343f565b6000600187878787604051600081526020016040526040516133c69493929190615cb3565b6020604051602081039080840390855afa1580156133e8573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036134365760006001925092505061343f565b80600092509250505b94509492505050565b505050505050565b6040518060600160405280600061ffff168152602001600061ffff168152602001600081525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006134b88261348d565b9050919050565b6134c8816134ad565b81146134d357600080fd5b50565b6000813590506134e5816134bf565b92915050565b6000819050919050565b6134fe816134eb565b811461350957600080fd5b50565b60008135905061351b816134f5565b92915050565b6000806040838503121561353857613537613483565b5b6000613546858286016134d6565b92505060206135578582860161350c565b9150509250929050565b61356a816134eb565b82525050565b60006020820190506135856000830184613561565b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6135c08161358b565b81146135cb57600080fd5b50565b6000813590506135dd816135b7565b92915050565b6000602082840312156135f9576135f8613483565b5b6000613607848285016135ce565b91505092915050565b60008115159050919050565b61362581613610565b82525050565b6000602082019050613640600083018461361c565b92915050565b60006020828403121561365c5761365b613483565b5b600061366a8482850161350c565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156136ad578082015181840152602081019050613692565b60008484015250505050565b6000601f19601f8301169050919050565b60006136d582613673565b6136df818561367e565b93506136ef81856020860161368f565b6136f8816136b9565b840191505092915050565b6000602082019050818103600083015261371d81846136ca565b905092915050565b600060ff82169050919050565b61373b81613725565b811461374657600080fd5b50565b60008135905061375881613732565b92915050565b60006020828403121561377457613773613483565b5b600061378284828501613749565b91505092915050565b600061ffff82169050919050565b6137a28161378b565b82525050565b6137b1816134eb565b82525050565b6060820160008201516137cd6000850182613799565b5060208201516137e06020850182613799565b5060408201516137f360408501826137a8565b50505050565b600060608201905061380e60008301846137b7565b92915050565b6000806040838503121561382b5761382a613483565b5b600061383985828601613749565b925050602061384a858286016134d6565b9150509250929050565b61385d8161378b565b82525050565b60006020820190506138786000830184613854565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6138bb826136b9565b810181811067ffffffffffffffff821117156138da576138d9613883565b5b80604052505050565b60006138ed613479565b90506138f982826138b2565b919050565b600067ffffffffffffffff82111561391957613918613883565b5b602082029050602081019050919050565b600080fd5b600061394261393d846138fe565b6138e3565b905080838252602082019050602084028301858111156139655761396461392a565b5b835b8181101561398e578061397a888261350c565b845260208401935050602081019050613967565b5050509392505050565b600082601f8301126139ad576139ac61387e565b5b81356139bd84826020860161392f565b91505092915050565b600080fd5b600067ffffffffffffffff8211156139e6576139e5613883565b5b6139ef826136b9565b9050602081019050919050565b82818337600083830152505050565b6000613a1e613a19846139cb565b6138e3565b905082815260208101848484011115613a3a57613a396139c6565b5b613a458482856139fc565b509392505050565b600082601f830112613a6257613a6161387e565b5b8135613a72848260208601613a0b565b91505092915050565b600080600080600060a08688031215613a9757613a96613483565b5b6000613aa5888289016134d6565b9550506020613ab6888289016134d6565b945050604086013567ffffffffffffffff811115613ad757613ad6613488565b5b613ae388828901613998565b935050606086013567ffffffffffffffff811115613b0457613b03613488565b5b613b1088828901613998565b925050608086013567ffffffffffffffff811115613b3157613b30613488565b5b613b3d88828901613a4d565b9150509295509295909350565b600080fd5b600060a08284031215613b6557613b64613b4a565b5b81905092915050565b613b778161378b565b8114613b8257600080fd5b50565b600081359050613b9481613b6e565b92915050565b60008060008060808587031215613bb457613bb3613483565b5b600085013567ffffffffffffffff811115613bd257613bd1613488565b5b613bde87828801613b4f565b9450506020613bef878288016134d6565b9350506040613c0087828801613749565b9250506060613c1187828801613b85565b91505092959194509250565b6000819050919050565b6000613c42613c3d613c388461348d565b613c1d565b61348d565b9050919050565b6000613c5482613c27565b9050919050565b6000613c6682613c49565b9050919050565b613c7681613c5b565b82525050565b6000602082019050613c916000830184613c6d565b92915050565b600067ffffffffffffffff821115613cb257613cb1613883565b5b602082029050602081019050919050565b6000613cd6613cd184613c97565b6138e3565b90508083825260208201905060208402830185811115613cf957613cf861392a565b5b835b81811015613d225780613d0e88826134d6565b845260208401935050602081019050613cfb565b5050509392505050565b600082601f830112613d4157613d4061387e565b5b8135613d51848260208601613cc3565b91505092915050565b60008060408385031215613d7157613d70613483565b5b600083013567ffffffffffffffff811115613d8f57613d8e613488565b5b613d9b85828601613d2c565b925050602083013567ffffffffffffffff811115613dbc57613dbb613488565b5b613dc885828601613998565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000613e0a83836137a8565b60208301905092915050565b6000602082019050919050565b6000613e2e82613dd2565b613e388185613ddd565b9350613e4383613dee565b8060005b83811015613e74578151613e5b8882613dfe565b9750613e6683613e16565b925050600181019050613e47565b5085935050505092915050565b60006020820190508181036000830152613e9b8184613e23565b905092915050565b6000613eae8261348d565b9050919050565b613ebe81613ea3565b8114613ec957600080fd5b50565b600081359050613edb81613eb5565b92915050565b600060208284031215613ef757613ef6613483565b5b6000613f0584828501613ecc565b91505092915050565b600060808284031215613f2457613f23613b4a565b5b81905092915050565b600080fd5b60008083601f840112613f4857613f4761387e565b5b8235905067ffffffffffffffff811115613f6557613f64613f2d565b5b602083019150836040820283011115613f8157613f8061392a565b5b9250929050565b600080600060408486031215613fa157613fa0613483565b5b600084013567ffffffffffffffff811115613fbf57613fbe613488565b5b613fcb86828701613f0e565b935050602084013567ffffffffffffffff811115613fec57613feb613488565b5b613ff886828701613f32565b92509250509250925092565b61400d816134ad565b82525050565b60006020820190506140286000830184614004565b92915050565b60007fffffffffffffffff00000000000000000000000000000000000000000000000082169050919050565b6140638161402e565b82525050565b600060408201905061407e600083018561405a565b61408b6020830184614004565b9392505050565b61409b81613725565b82525050565b60006040820190506140b66000830185614092565b6140c36020830184614092565b9392505050565b60008083601f8401126140e0576140df61387e565b5b8235905067ffffffffffffffff8111156140fd576140fc613f2d565b5b6020830191508360018202830111156141195761411861392a565b5b9250929050565b6000806020838503121561413757614136613483565b5b600083013567ffffffffffffffff81111561415557614154613488565b5b614161858286016140ca565b92509250509250929050565b61417681613610565b811461418157600080fd5b50565b6000813590506141938161416d565b92915050565b600080604083850312156141b0576141af613483565b5b60006141be858286016134d6565b92505060206141cf85828601614184565b9150509250929050565b600080604083850312156141f0576141ef613483565b5b60006141fe85828601613749565b925050602061420f85828601613749565b9150509250929050565b60008083601f84011261422f5761422e61387e565b5b8235905067ffffffffffffffff81111561424c5761424b613f2d565b5b6020830191508360208202830111156142685761426761392a565b5b9250929050565b60008083601f8401126142855761428461387e565b5b8235905067ffffffffffffffff8111156142a2576142a1613f2d565b5b6020830191508360608202830111156142be576142bd61392a565b5b9250929050565b600080600080604085870312156142df576142de613483565b5b600085013567ffffffffffffffff8111156142fd576142fc613488565b5b61430987828801614219565b9450945050602085013567ffffffffffffffff81111561432c5761432b613488565b5b6143388782880161426f565b925092505092959194509250565b6000806040838503121561435d5761435c613483565b5b600061436b858286016134d6565b925050602061437c858286016134d6565b9150509250929050565b600080600080600060a086880312156143a2576143a1613483565b5b60006143b0888289016134d6565b95505060206143c1888289016134d6565b94505060406143d28882890161350c565b93505060606143e38882890161350c565b925050608086013567ffffffffffffffff81111561440457614403613488565b5b61441088828901613a4d565b9150509295509295909350565b60006020828403121561443357614432613483565b5b6000614441848285016134d6565b91505092915050565b7f455243313135353a2061646472657373207a65726f206973206e6f742061207660008201527f616c6964206f776e657200000000000000000000000000000000000000000000602082015250565b60006144a6602a8361367e565b91506144b18261444a565b604082019050919050565b600060208201905081810360008301526144d581614499565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061452357607f821691505b602082108103614536576145356144dc565b5b50919050565b600081905092915050565b60008190508160005260206000209050919050565b600081546145698161450b565b614573818661453c565b9450600182166000811461458e57600181146145a3576145d6565b60ff19831686528115158202860193506145d6565b6145ac85614547565b60005b838110156145ce578154818901526001820191506020810190506145af565b838801955050505b50505092915050565b60006145ea82613673565b6145f4818561453c565b935061460481856020860161368f565b80840191505092915050565b600061461c828561455c565b915061462882846145df565b91508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061466e826134eb565b9150614679836134eb565b9250828202614687816134eb565b9150828204841483151761469e5761469d614634565b5b5092915050565b60006146b0826134eb565b91506146bb836134eb565b92508282019050808211156146d3576146d2614634565b5b92915050565b60006146e48261378b565b91506146ef8361378b565b9250828201905061ffff81111561470957614708614634565b5b92915050565b60006020828403121561472557614724613483565b5b600061473384828501613b85565b91505092915050565b600063ffffffff82169050919050565b6147558161473c565b811461476057600080fd5b50565b6000813590506147728161474c565b92915050565b60006020828403121561478e5761478d613483565b5b600061479c84828501614763565b91505092915050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126147d1576147d06147a5565b5b80840192508235915067ffffffffffffffff8211156147f3576147f26147aa565b5b60208301925060018202360383131561480f5761480e6147af565b5b509250929050565b600067ffffffffffffffff82169050919050565b61483481614817565b811461483f57600080fd5b50565b6000813590506148518161482b565b92915050565b60006020828403121561486d5761486c613483565b5b600061487b84828501614842565b91505092915050565b7f455243313135353a206163636f756e747320616e6420696473206c656e67746860008201527f206d69736d617463680000000000000000000000000000000000000000000000602082015250565b60006148e060298361367e565b91506148eb82614884565b604082019050919050565b6000602082019050818103600083015261490f816148d3565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000614950826134eb565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361498257614981614634565b5b600182019050919050565b600080fd5b6000604082840312156149a8576149a761498d565b5b6149b260406138e3565b905060006149c2848285016134d6565b60008301525060206149d684828501614842565b60208301525092915050565b6000604082840312156149f8576149f7613483565b5b6000614a0684828501614992565b91505092915050565b6000614a1a8261378b565b915061ffff8203614a2e57614a2d614634565b5b600182019050919050565b600082905092915050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614a917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614a54565b614a9b8683614a54565b95508019841693508086168417925050509392505050565b6000614ace614ac9614ac4846134eb565b613c1d565b6134eb565b9050919050565b6000819050919050565b614ae883614ab3565b614afc614af482614ad5565b848454614a61565b825550505050565b600090565b614b11614b04565b614b1c818484614adf565b505050565b5b81811015614b4057614b35600082614b09565b600181019050614b22565b5050565b601f821115614b8557614b5681614547565b614b5f84614a44565b81016020851015614b6e578190505b614b82614b7a85614a44565b830182614b21565b50505b505050565b600082821c905092915050565b6000614ba860001984600802614b8a565b1980831691505092915050565b6000614bc18383614b97565b9150826002028217905092915050565b614bdb8383614a39565b67ffffffffffffffff811115614bf457614bf3613883565b5b614bfe825461450b565b614c09828285614b44565b6000601f831160018114614c385760008415614c26578287013590505b614c308582614bb5565b865550614c98565b601f198416614c4686614547565b60005b82811015614c6e57848901358255600182019150602085019450602081019050614c49565b86831015614c8b5784890135614c87601f891682614b97565b8355505b6001600288020188555050505b50505050505050565b60008135614cae81613b6e565b80915050919050565b60008160001b9050919050565b600061ffff614cd284614cb7565b9350801983169250808416831791505092915050565b6000614d03614cfe614cf98461378b565b613c1d565b61378b565b9050919050565b6000819050919050565b614d1d82614ce8565b614d30614d2982614d0a565b8354614cc4565b8255505050565b60008160101b9050919050565b600063ffff0000614d5484614d37565b9350801983169250808416831791505092915050565b614d7382614ce8565b614d86614d7f82614d0a565b8354614d44565b8255505050565b60008135614d9a816134f5565b80915050919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff614dcf84614cb7565b9350801983169250808416831791505092915050565b614dee82614ab3565b614e01614dfa82614ad5565b8354614da3565b8255505050565b600081016000830180614e1a81614ca1565b9050614e268184614d14565b505050600081016020830180614e3b81614ca1565b9050614e478184614d6a565b505050600181016040830180614e5c81614d8d565b9050614e688184614de5565b5050505050565b614e798282614e08565b5050565b6000614e8882613725565b915060ff8203614e9b57614e9a614634565b5b600182019050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614f0260268361367e565b9150614f0d82614ea6565b604082019050919050565b60006020820190508181036000830152614f3181614ef5565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000604082019050614f7c6000830185614004565b614f896020830184614004565b9392505050565b600081519050614f9f8161416d565b92915050565b600060208284031215614fbb57614fba613483565b5b6000614fc984828501614f90565b91505092915050565b7f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60008201527f6572206f7220617070726f766564000000000000000000000000000000000000602082015250565b600061502e602e8361367e565b915061503982614fd2565b604082019050919050565b6000602082019050818103600083015261505d81615021565b9050919050565b6000819050919050565b61507f61507a8261402e565b615064565b82525050565b60008160601b9050919050565b600061509d82615085565b9050919050565b60006150af82615092565b9050919050565b6150c76150c2826134ad565b6150a4565b82525050565b60008160c01b9050919050565b60006150e5826150cd565b9050919050565b6150fd6150f882614817565b6150da565b82525050565b60008160f81b9050919050565b600061511b82615103565b9050919050565b61513361512e82613725565b615110565b82525050565b60008160f01b9050919050565b600061515182615139565b9050919050565b6151696151648261378b565b615146565b82525050565b60008160e01b9050919050565b60006151878261516f565b9050919050565b61519f61519a8261473c565b61517c565b82525050565b60006151b1828a61506e565b6008820191506151c182896150b6565b6014820191506151d182886150ec565b6008820191506151e18287615122565b6001820191506151f18286615158565b600282019150615201828561518e565b60048201915061521182846150ec565b60088201915081905098975050505050505050565b7f455243313135353a206d696e7420746f20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b600061528260218361367e565b915061528d82615226565b604082019050919050565b600060208201905081810360008301526152b181615275565b9050919050565b60006040820190506152cd6000830185613561565b6152da6020830184613561565b9392505050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061531760208361367e565b9150615322826152e1565b602082019050919050565b600060208201905081810360008301526153468161530a565b9050919050565b6000615358826134eb565b9150615363836134eb565b92508261537357615372614f38565b5b828206905092915050565b6000615389826134eb565b9150615394836134eb565b9250826153a4576153a3614f38565b5b828204905092915050565b600081519050919050565b600081905092915050565b60006153d0826153af565b6153da81856153ba565b93506153ea81856020860161368f565b80840191505092915050565b600061540282856153c5565b915061540e82846150b6565b6014820191508190509392505050565b600061542a82856153c5565b915061543682846150ec565b6008820191508190509392505050565b6000615452828a61506e565b60088201915061546282896150b6565b60148201915061547282886150ec565b60088201915061548282876153c5565b915061548e82866153c5565b915061549a828561518e565b6004820191506154aa82846150ec565b60088201915081905098975050505050505050565b7f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060008201527f6d69736d61746368000000000000000000000000000000000000000000000000602082015250565b600061551b60288361367e565b9150615526826154bf565b604082019050919050565b6000602082019050818103600083015261554a8161550e565b9050919050565b7f455243313135353a207472616e7366657220746f20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b60006155ad60258361367e565b91506155b882615551565b604082019050919050565b600060208201905081810360008301526155dc816155a0565b9050919050565b7f455243313135353a20696e73756666696369656e742062616c616e636520666f60008201527f72207472616e7366657200000000000000000000000000000000000000000000602082015250565b600061563f602a8361367e565b915061564a826155e3565b604082019050919050565b6000602082019050818103600083015261566e81615632565b9050919050565b6000604082019050818103600083015261568f8185613e23565b905081810360208301526156a38184613e23565b90509392505050565b600082825260208201905092915050565b60006156c8826153af565b6156d281856156ac565b93506156e281856020860161368f565b6156eb816136b9565b840191505092915050565b600060a08201905061570b6000830188614004565b6157186020830187614004565b6157256040830186613561565b6157326060830185613561565b818103608083015261574481846156bd565b90509695505050505050565b60008151905061575f816135b7565b92915050565b60006020828403121561577b5761577a613483565b5b600061578984828501615750565b91505092915050565b60008160e01c9050919050565b600060033d11156157be5760046000803e6157bb600051615792565b90505b90565b600060443d1061584e576157d3613479565b60043d036004823e80513d602482011167ffffffffffffffff821117156157fb57505061584e565b808201805167ffffffffffffffff811115615819575050505061584e565b80602083010160043d03850181111561583657505050505061584e565b615845826020018501866138b2565b82955050505050505b90565b7f455243313135353a207472616e7366657220746f206e6f6e2d4552433131353560008201527f526563656976657220696d706c656d656e746572000000000000000000000000602082015250565b60006158ad60348361367e565b91506158b882615851565b604082019050919050565b600060208201905081810360008301526158dc816158a0565b9050919050565b7f455243313135353a204552433131353552656365697665722072656a6563746560008201527f6420746f6b656e73000000000000000000000000000000000000000000000000602082015250565b600061593f60288361367e565b915061594a826158e3565b604082019050919050565b6000602082019050818103600083015261596e81615932565b9050919050565b7f455243313135353a2073657474696e6720617070726f76616c2073746174757360008201527f20666f722073656c660000000000000000000000000000000000000000000000602082015250565b60006159d160298361367e565b91506159dc82615975565b604082019050919050565b60006020820190508181036000830152615a00816159c4565b9050919050565b600060a082019050615a1c6000830188614004565b615a296020830187614004565b8181036040830152615a3b8186613e23565b90508181036060830152615a4f8185613e23565b90508181036080830152615a6381846156bd565b90509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b6000615ad460188361367e565b9150615adf82615a9e565b602082019050919050565b60006020820190508181036000830152615b0381615ac7565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000615b40601f8361367e565b9150615b4b82615b0a565b602082019050919050565b60006020820190508181036000830152615b6f81615b33565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000615bd260228361367e565b9150615bdd82615b76565b604082019050919050565b60006020820190508181036000830152615c0181615bc5565b9050919050565b7f455243313135353a206275726e20616d6f756e74206578636565647320746f7460008201527f616c537570706c79000000000000000000000000000000000000000000000000602082015250565b6000615c6460288361367e565b9150615c6f82615c08565b604082019050919050565b60006020820190508181036000830152615c9381615c57565b9050919050565b6000819050919050565b615cad81615c9a565b82525050565b6000608082019050615cc86000830187615ca4565b615cd56020830186614092565b615ce26040830185615ca4565b615cef6060830184615ca4565b9594505050505056fea2646970667358221220c9dfde0ff34e49c0f79766f3537319a7bdae6e7ea5ef9392a08a1db0aadf2ebc64736f6c63430008110033
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.