Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- SimpleShop
- Optimization enabled
- false
- Compiler version
- v0.8.20+commit.a1b79de6
- EVM Version
- paris
- Verified at
- 2024-06-01T15:57:35.330483Z
Constructor Arguments
0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000e486f706576657273652053686f70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002053656c6c207072696d6974697665204e465420666f7220486f70657665727365
Arg [0] (string) : Hopeverse Shop
Arg [1] (string) : Sell primitive NFT for Hopeverse
contracts/Craftable/SimpleShop.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "../base/TokenOperatableTemplateContract.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; contract SimpleShop is TokenOperatableTemplateContract { using Math for uint256; using ERC165Checker for address; struct Product { address token_address; uint256 token_id; bool as_multitoken; } mapping(uint256 => Product) private products; mapping(uint256 => uint256) private availables; uint256 private _productIds; event OnProductDefined(uint256 indexed product_id,Product product); event OnProductUpdated(uint256 indexed product_id,Product product); event OnProductPurchased(uint256 indexed product_id,Product product,uint256 amount); constructor(string memory name_,string memory description_) TokenOperatableTemplateContract(name_,description_) { } function get_last_template_id() public view virtual override returns (uint256) {return _productIds;} function onUndefineTemplate(uint256 product_id) internal virtual override{ delete products[product_id]; } function define_product(string memory name,string memory desc,address token_address,uint256 token_id,uint256 price,bool start_enabled,address merchant,address currency,uint256 initial_stock) external onlyOwner returns (uint256){ require(bytes(name).length > 0,"NO_PRD_NAME"); (bool result,uint256 prd_id) = _productIds.tryAdd(1); require(result,"TPL_ID_OVERFLOW"); _productIds = prd_id; _fill_template_metadata(prd_id,name,desc,price,start_enabled,merchant,currency); bool as_multitoken = _check_product_token(token_address,token_id); products[prd_id] = Product(token_address,token_id,as_multitoken); availables[prd_id] = initial_stock; emit OnProductDefined(prd_id, products[prd_id]); return prd_id; } function udpate_template_product(uint256 product_id,address token_address,uint256 token_id) external onlyOwner { require(is_defined(product_id),"NO_PRD_DEFINED"); bool as_multitoken = _check_product_token(token_address,token_id); products[product_id] = Product(token_address,token_id,as_multitoken); emit OnProductUpdated(product_id,products[product_id]); } function get_product(uint256 product_id) external view returns (address,uint256,bool){ Product memory prd = products[product_id]; return (prd.token_address,prd.token_id,prd.as_multitoken); } function _check_product_token(address token_address,uint256 token_id) internal view returns(bool){ bool is_erc1155 = _is_operatable_erc1155(token_address); bool is_erc721 = _is_operatable_erc721(token_address); require(is_erc1155 || is_erc721,"O_BAD_TOKEN"); if(is_erc1155){ IOperatableERC1155Token asErc1155 = IOperatableERC1155Token(token_address); require(asErc1155.isTokenDefined(token_id),"NO_TOKEN_ID"); } return is_erc1155; } function _check_valid(uint256 prd_id) internal view { Product memory prd = products[prd_id]; if(prd.as_multitoken){ IOperatableERC1155Token asErc1155 = IOperatableERC1155Token(prd.token_address); require(asErc1155.isTokenDefined(prd.token_id),"NO_TOKEN_ID"); } } function get_available(uint256 product_id) public view returns (uint256) { return availables[product_id]; } function refill_stock(uint256 product_id,uint256 add_amount) external onlyOperator { (bool result,uint256 newAvailable) = availables[product_id].tryAdd(add_amount); require(result,"STOCK_OVERFLOW"); availables[product_id] = newAvailable; } function purchase(uint256 product_id,uint256 amount) external payable{ require((amount > 0),"ZERO_APPLY_COUNT"); require(is_enabled(product_id),"PRD_NOT_ONSALE"); require(availables[product_id] >= amount,"OUT_OF_STOCK"); _check_valid(product_id); Product memory product = products[product_id]; if(product.as_multitoken) { IOperatableERC1155Token asErc1155 = IOperatableERC1155Token(product.token_address); asErc1155.mintNFTFor(msg.sender, product.token_id,amount); } else { IOperatableERC721Token asErc721 = IOperatableERC721Token(product.token_address); asErc721.mintNFTsFor(msg.sender, amount); } consume_operation_cost(product_id,amount); (bool result,uint256 remain) = availables[product_id].trySub(amount); require(result,"REMIN_UNDERFLOW"); availables[product_id] = remain; } }
@openzeppelin/contracts/access/Ownable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../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. * * The initial owner is set to the address provided by the deployer. 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; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @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 { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling 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 { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _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); } }
@openzeppelin/contracts/access/Ownable2Step.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {Ownable} from "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
@openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) 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 FailedInnerCall(); } } }
@openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
@openzeppelin/contracts/utils/introspection/ERC165Checker.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165Checker.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Library used to query support of an interface declared via {IERC165}. * * Note that these functions return the actual result of the query: they do not * `revert` if an interface is not supported. It is up to the caller to decide * what to do in these cases. */ library ERC165Checker { // As per the EIP-165 spec, no interface should ever match 0xffffffff bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff; /** * @dev Returns true if `account` supports the {IERC165} interface. */ function supportsERC165(address account) internal view returns (bool) { // Any contract that implements ERC165 must explicitly indicate support of // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid return supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) && !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID); } /** * @dev Returns true if `account` supports the interface defined by * `interfaceId`. Support for {IERC165} itself is queried automatically. * * See {IERC165-supportsInterface}. */ function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { // query support of both ERC165 as per the spec and support of _interfaceId return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId); } /** * @dev Returns a boolean array where each value corresponds to the * interfaces passed in and whether they're supported or not. This allows * you to batch check interfaces for a contract where your expectation * is that some interfaces may not be supported. * * See {IERC165-supportsInterface}. */ function getSupportedInterfaces( address account, bytes4[] memory interfaceIds ) internal view returns (bool[] memory) { // an array of booleans corresponding to interfaceIds and whether they're supported or not bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length); // query support of ERC165 itself if (supportsERC165(account)) { // query support of each interface in interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]); } } return interfaceIdsSupported; } /** * @dev Returns true if `account` supports all the interfaces defined in * `interfaceIds`. Support for {IERC165} itself is queried automatically. * * Batch-querying can lead to gas savings by skipping repeated checks for * {IERC165} support. * * See {IERC165-supportsInterface}. */ function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { // query support of ERC165 itself if (!supportsERC165(account)) { return false; } // query support of each interface in interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) { return false; } } // all interfaces supported return true; } /** * @notice Query if a contract implements an interface, does not check ERC165 support * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return true if the contract at account indicates support of the interface with * identifier interfaceId, false otherwise * @dev Assumes that account contains a contract that supports ERC165, otherwise * the behavior of this method is undefined. This precondition can be checked * with {supportsERC165}. * * Some precompiled contracts will falsely indicate support for a given interface, so caution * should be exercised when using this function. * * Interface identification is specified in ERC-165. */ function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) { // prepare call bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId)); // perform static call bool success; uint256 returnSize; uint256 returnValue; assembly { success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20) returnSize := returndatasize() returnValue := mload(0x00) } return success && returnSize >= 0x20 && returnValue > 0; } }
@openzeppelin/contracts/utils/introspection/IERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @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); }
@openzeppelin/contracts/utils/math/Math.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @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 towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (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 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 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. uint256 twos = denominator & (0 - denominator); 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 (unsignedRoundsUp(rounding) && 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 * towards zero. * * 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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * 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 + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * 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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * 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 256, 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 + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
contracts/Interfaces/IOperatableERC1155Token.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface IOperatableERC1155Token { //Get Contract Level metadata uri - See https://docs.opensea.io/docs/contract-level-metadata function contractURI() external view returns (string memory); //Set Contract Level metadata uri - See https://docs.opensea.io/docs/contract-level-metadata function setContractURI(string memory contractURI_) external; function lastTokenIds() external view returns (uint256); //Return token ids and amount. function ownedTokenOf(address _addr) external view returns(uint256[] memory,uint256[] memory); function canMintForAmount(uint256 tokenId,uint256 tokmentAmount) external view returns(bool); function canMintBulkForAmount(uint256[] memory tokenIds,uint256[] memory tokmentAmounts) external view returns(bool); //Mint nft for some user by contact owner. use for bleeding/crafting or mint NFT from App function mintNFTsFor(address _addr,uint256[] memory tokenIds,uint256[] memory amounts) external; //Burn nft for some user by contact owner. use for crafting or burn NFT from App function burnNFTsFor(address _addr,uint256[] memory tokenIds,uint256[] memory amounts) external; //Mint nft for some user by contact owner. use for bleeding/crafting or mint NFT from App function mintNFTFor(address _addr,uint256 tokenId,uint256 amount) external; //Burn nft for some user by contact owner. use for crafting or burn NFT from App function burnNFTFor(address _addr,uint256 tokenId,uint256 amount) external; //Get total supply of Token function totalSupply(uint256 tokenId) external view returns(uint256); //Token id is defined or not function isTokenDefined(uint256 token_id) external view returns (bool); }
contracts/Interfaces/IOperatableERC721Token.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @dev Interface of use for all of ScrewUp NFT token. */ interface IOperatableERC721Token { //Get Contract Level metadata uri - See https://docs.opensea.io/docs/contract-level-metadata function contractURI() external view returns (string memory); //Set Contract Level metadata uri - See https://docs.opensea.io/docs/contract-level-metadata function setContractURI(string memory contractURI_) external; //Get all of items for address. function ownedTokenOf(address _addr) external view returns (uint256[] memory); //Check address is really own item. function isOwnedToken(address _addr,uint256 tokenId) external view returns(bool); //Update token URI for token Id function updateTokenURI(uint256 tokenId,string memory tokenURI) external; //Mint nft (unreveal only) for some user by contact owner. use for bleeding or mint NFT from App function mintNFTsFor(address addr,uint256 amount) external; //Mint nft for some user by contact owner. use for bleeding or mint NFT from App function mintNFTFor(address addr,string memory tokenURI) external; //Mint nft for some user by contact owner. use for bleeding or mint NFT from App function burnNFTFor(address addr,uint256 tokenId) external; //Update display name of token when unreveal. function getUnrevealName() external view returns (string memory); //Update token uri of token when unreveal. function getUnrevealTokenUri() external view returns (string memory); function getUnrevealMetadata() external view returns (string memory,string memory); }
contracts/Interfaces/ITokenOperatableTemplate.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ITokenOperatableTemplate { function get_name() external view returns (string memory); function get_description() external view returns (string memory); function get_template_metadata(uint256 template_id) external view returns (string memory,string memory,uint256,bool,address); function is_template_defined(uint256 template_id) external view returns (bool); function is_template_enabled(uint256 template_id) external view returns (bool); }
contracts/base/TokenOperatableTemplateContract.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/Ownable2Step.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../Interfaces/ITokenOperatableTemplate.sol"; import "../Interfaces/IOperatableERC1155Token.sol"; import "../Interfaces/IOperatableERC721Token.sol"; abstract contract TokenOperatableTemplateContract is Ownable2Step,ITokenOperatableTemplate { using Math for uint256; using ERC165Checker for address; string private name; string private description; mapping(uint256 => string) private template_names; mapping(uint256 => string) private template_descs; mapping(uint256 => uint256) private operation_prices; mapping(uint256 => bool) private template_enabled; //For some reason in marketing we have template specific merchant if not set just use merchant address. mapping(uint256 => address) private template_merchants; mapping(uint256 => address) private template_currencies; address private merchant_address; address private currency_address = address(0); mapping(address => bool) private _operators; error OperatorAccount(address account); constructor(string memory name_,string memory description_) Ownable(msg.sender) { name = name_; description = description_; merchant_address = msg.sender; } event OnTemplateUndefined(uint256 template_id); function set_currency(address addr) external onlyOperator { require(addr == address(0) || addr.supportsInterface(type(IERC20).interfaceId),"UNSUPPORT_CURRENCY"); currency_address = addr; } function set_merchant(address merchant) external onlyOperator { require((merchant_address != merchant) && (merchant != address(0)),"INVALID_MERCHANT"); merchant_address = merchant; } function get_last_template_id() public view virtual returns (uint256) {return 0;} function get_currency_address(uint256 template_id) public view returns (address){ address addr = template_currencies[template_id]; return addr != address(0) ? addr : currency_address; } function get_merchant_address(uint256 template_id) public view returns(address){ address addr = template_merchants[template_id]; return addr != address(0) ? addr : merchant_address; } function undefine_templates(uint256[] memory template_ids) external onlyOperator { for(uint256 i = 0; i < template_ids.length; i++) _undefine_template(template_ids[i]); } function update_template_names(uint256[] memory template_ids,string[] memory template_names_) external onlyOperator { require(template_ids.length == template_names_.length,"PARAM_DIM_MISMATCH"); for(uint256 i = 0; i < template_ids.length; i++) _udpate_template_name(template_ids[i],template_names_[i]); } function update_template_descs(uint256[] memory template_ids,string[] memory descs) external onlyOperator { require(template_ids.length == descs.length,"PARAM_DIM_MISMATCH"); for(uint256 i = 0; i < template_ids.length; i++) _update_template_desc(template_ids[i],descs[i]); } function update_operation_prices(uint256[] memory template_ids,uint256[] memory prices) external onlyOperator { require(template_ids.length == prices.length,"PARAM_DIM_MISMATCH"); for(uint256 i = 0; i < template_ids.length; i++) _update_operation_price(template_ids[i],prices[i]); } function update_template_merchants(uint256[] memory template_ids,address[] memory merchants) external onlyOperator { require(template_ids.length == merchants.length,"PARAM_DIM_MISMATCH"); for(uint256 i = 0; i < template_ids.length; i++) _update_template_merchant(template_ids[i],merchants[i]); } function update_template_currencies(uint256[] memory template_ids,address[] memory currencies) external onlyOperator { require(template_ids.length == currencies.length,"PARAM_DIM_MISMATCH"); for(uint256 i = 0; i < template_ids.length; i++) _update_template_currency(template_ids[i],currencies[i]); } function enable_templates(uint256[] memory template_ids,bool[] memory enables) external onlyOperator { require(template_ids.length == enables.length,"PARAM_DIM_MISMATCH"); for(uint256 i = 0; i < template_ids.length; i++) _enable_template(template_ids[i],enables[i]); } function is_defined(uint256 template_id) public view returns(bool) {return (bytes(template_names[template_id]).length > 0);} function is_enabled(uint256 template_id) public view returns(bool) {return template_enabled[template_id];} function _undefine_template(uint256 template_id) internal { require(is_defined(template_id),"NO_TPL_DEFINED"); _clear_template_metadata(template_id); onUndefineTemplate(template_id); emit OnTemplateUndefined(template_id); } function _fill_template_metadata(uint256 template_id,string memory name_,string memory desc,uint256 op_price,bool start_enabled,address merchant,address currency) internal{ template_names[template_id] = name_; template_descs[template_id] = desc; operation_prices[template_id] = op_price; template_enabled[template_id] = start_enabled; template_merchants[template_id] = merchant; template_currencies[template_id] = currency; } function _clear_template_metadata(uint256 template_id) internal{ delete template_names[template_id]; delete template_descs[template_id]; delete operation_prices[template_id]; delete template_enabled[template_id]; delete template_merchants[template_id]; delete template_currencies[template_id]; } function _udpate_template_name(uint256 template_id,string memory name_) internal{ require(bytes(template_names[template_id]).length > 0,"NO_TPL_DEFINED"); require(bytes(name_).length > 0,"NO_TPL_NAME"); template_names[template_id] = name_; } function _update_template_desc(uint256 template_id,string memory desc) internal { require(is_defined(template_id),"NO_TPL_DEFINED"); template_descs[template_id] = desc; } function _update_operation_price(uint256 template_id,uint256 price) internal { require(is_defined(template_id),"NO_TPL_DEFINED"); operation_prices[template_id] = price; } function _update_template_merchant(uint256 template_id,address merchant) internal { require(is_defined(template_id),"NO_TPL_DEFINED"); require(merchant != address(0),"NULL_ADDRESS"); template_merchants[template_id] = merchant; } function _update_template_currency(uint256 template_id,address currency) internal { require(is_defined(template_id),"NO_TPL_DEFINED"); require(currency != address(0),"NULL_ADDRESS"); template_currencies[template_id] = currency; } function _enable_template(uint256 template_id,bool enabled) internal { require(is_defined(template_id),"NO_TPL_DEFINED"); template_enabled[template_id] = enabled; } function consume_operation_cost(uint256 template_id,uint256 applyCount) internal { require(applyCount > 0,"ZERO_APPLYCOUNT"); uint256 op_price = operation_prices[template_id]; if(op_price == 0) return; address _merchant_addr = get_merchant_address(template_id); require(_merchant_addr != address(0),"NO_MERCHANT_ADDR"); (bool total_op_cost_result,uint256 total_op_cost) = op_price.tryMul(applyCount); require(total_op_cost_result,"OP_COST_OVERFLOW"); address _currency_addr = get_currency_address(template_id); if(_currency_addr != address(0)){ uint256 available_balance = IERC20(_currency_addr).balanceOf(msg.sender); require(available_balance >= total_op_cost,"UNSUFFICIENT_BALANCE"); IERC20(_currency_addr).transferFrom(msg.sender, _merchant_addr, total_op_cost); if(msg.value > 0) payable(msg.sender).transfer(msg.value); } else{ require(msg.value >= total_op_cost,"UNSUFFICIENT_BALANCE"); uint256 remain_value = msg.value - total_op_cost; payable(_merchant_addr).transfer(total_op_cost); payable(msg.sender).transfer(remain_value); } } function isTemplateValid(uint256) internal virtual returns (bool) {return false;} function onUndefineTemplate(uint256) internal virtual {} function get_template_metadata(uint256 template_id) external view virtual override returns (string memory,string memory,uint256,bool,address){ return (template_names[template_id],template_descs[template_id],operation_prices[template_id],template_enabled[template_id],get_merchant_address(template_id)); } function is_template_defined(uint256 template_id) external view virtual override returns (bool){return is_defined(template_id);} function is_template_enabled(uint256 template_id) external view virtual override returns (bool){return template_enabled[template_id];} function get_name() external view virtual override returns (string memory){return name;} function get_description() external view virtual override returns (string memory){return description;} function set_operator(address addr,bool set) external virtual onlyOwner { require(addr != address(0),"Null Address allowed"); _operators[addr] = set; } function as_operator(address addr) public view virtual returns(bool) { return _operators[addr]; } modifier onlyOperator() { _checkIsOperator(); _; } function _check_operator(address addr) internal view virtual returns(bool) { return _operators[addr]; } function _checkIsOperator() internal view virtual { address _sender = _msgSender(); if ((owner() != _sender) && (!_check_operator(_sender))) { revert OperatorAccount(_sender); } } function _is_operatable_erc1155(address addr) internal view returns(bool) { return (addr != address(0)) && addr.supportsInterface(type(IOperatableERC1155Token).interfaceId); } function _is_operatable_erc721(address addr) internal view returns (bool){ return (addr != address(0)) && addr.supportsInterface(type(IOperatableERC721Token).interfaceId); } }
Compiler Settings
{"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":false},"libraries":{},"evmVersion":"paris"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"string","name":"name_","internalType":"string"},{"type":"string","name":"description_","internalType":"string"}]},{"type":"error","name":"OperatorAccount","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"event","name":"OnProductDefined","inputs":[{"type":"uint256","name":"product_id","internalType":"uint256","indexed":true},{"type":"tuple","name":"product","internalType":"struct SimpleShop.Product","indexed":false,"components":[{"type":"address","name":"token_address","internalType":"address"},{"type":"uint256","name":"token_id","internalType":"uint256"},{"type":"bool","name":"as_multitoken","internalType":"bool"}]}],"anonymous":false},{"type":"event","name":"OnProductPurchased","inputs":[{"type":"uint256","name":"product_id","internalType":"uint256","indexed":true},{"type":"tuple","name":"product","internalType":"struct SimpleShop.Product","indexed":false,"components":[{"type":"address","name":"token_address","internalType":"address"},{"type":"uint256","name":"token_id","internalType":"uint256"},{"type":"bool","name":"as_multitoken","internalType":"bool"}]},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OnProductUpdated","inputs":[{"type":"uint256","name":"product_id","internalType":"uint256","indexed":true},{"type":"tuple","name":"product","internalType":"struct SimpleShop.Product","indexed":false,"components":[{"type":"address","name":"token_address","internalType":"address"},{"type":"uint256","name":"token_id","internalType":"uint256"},{"type":"bool","name":"as_multitoken","internalType":"bool"}]}],"anonymous":false},{"type":"event","name":"OnTemplateUndefined","inputs":[{"type":"uint256","name":"template_id","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"as_operator","inputs":[{"type":"address","name":"addr","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"define_product","inputs":[{"type":"string","name":"name","internalType":"string"},{"type":"string","name":"desc","internalType":"string"},{"type":"address","name":"token_address","internalType":"address"},{"type":"uint256","name":"token_id","internalType":"uint256"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"bool","name":"start_enabled","internalType":"bool"},{"type":"address","name":"merchant","internalType":"address"},{"type":"address","name":"currency","internalType":"address"},{"type":"uint256","name":"initial_stock","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"enable_templates","inputs":[{"type":"uint256[]","name":"template_ids","internalType":"uint256[]"},{"type":"bool[]","name":"enables","internalType":"bool[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"get_available","inputs":[{"type":"uint256","name":"product_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"get_currency_address","inputs":[{"type":"uint256","name":"template_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"get_description","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"get_last_template_id","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"get_merchant_address","inputs":[{"type":"uint256","name":"template_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"get_name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"bool","name":"","internalType":"bool"}],"name":"get_product","inputs":[{"type":"uint256","name":"product_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"},{"type":"string","name":"","internalType":"string"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"bool","name":"","internalType":"bool"},{"type":"address","name":"","internalType":"address"}],"name":"get_template_metadata","inputs":[{"type":"uint256","name":"template_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"is_defined","inputs":[{"type":"uint256","name":"template_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"is_enabled","inputs":[{"type":"uint256","name":"template_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"is_template_defined","inputs":[{"type":"uint256","name":"template_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"is_template_enabled","inputs":[{"type":"uint256","name":"template_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pendingOwner","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"purchase","inputs":[{"type":"uint256","name":"product_id","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"refill_stock","inputs":[{"type":"uint256","name":"product_id","internalType":"uint256"},{"type":"uint256","name":"add_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"set_currency","inputs":[{"type":"address","name":"addr","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"set_merchant","inputs":[{"type":"address","name":"merchant","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"set_operator","inputs":[{"type":"address","name":"addr","internalType":"address"},{"type":"bool","name":"set","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"udpate_template_product","inputs":[{"type":"uint256","name":"product_id","internalType":"uint256"},{"type":"address","name":"token_address","internalType":"address"},{"type":"uint256","name":"token_id","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"undefine_templates","inputs":[{"type":"uint256[]","name":"template_ids","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"update_operation_prices","inputs":[{"type":"uint256[]","name":"template_ids","internalType":"uint256[]"},{"type":"uint256[]","name":"prices","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"update_template_currencies","inputs":[{"type":"uint256[]","name":"template_ids","internalType":"uint256[]"},{"type":"address[]","name":"currencies","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"update_template_descs","inputs":[{"type":"uint256[]","name":"template_ids","internalType":"uint256[]"},{"type":"string[]","name":"descs","internalType":"string[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"update_template_merchants","inputs":[{"type":"uint256[]","name":"template_ids","internalType":"uint256[]"},{"type":"address[]","name":"merchants","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"update_template_names","inputs":[{"type":"uint256[]","name":"template_ids","internalType":"uint256[]"},{"type":"string[]","name":"template_names_","internalType":"string[]"}]}]
Contract Creation Code
0x60806040526000600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200005357600080fd5b506040516200545538038062005455833981810160405281019062000079919062000402565b818133600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000f15760006040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620000e89190620004cc565b60405180910390fd5b62000102816200017260201b60201c565b50816002908162000114919062000734565b50806003908162000126919062000734565b5033600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050506200081b565b600160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055620001a881620001ab60201b60201c565b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620002d8826200028d565b810181811067ffffffffffffffff82111715620002fa57620002f96200029e565b5b80604052505050565b60006200030f6200026f565b90506200031d8282620002cd565b919050565b600067ffffffffffffffff82111562000340576200033f6200029e565b5b6200034b826200028d565b9050602081019050919050565b60005b83811015620003785780820151818401526020810190506200035b565b60008484015250505050565b60006200039b620003958462000322565b62000303565b905082815260208101848484011115620003ba57620003b962000288565b5b620003c784828562000358565b509392505050565b600082601f830112620003e757620003e662000283565b5b8151620003f984826020860162000384565b91505092915050565b600080604083850312156200041c576200041b62000279565b5b600083015167ffffffffffffffff8111156200043d576200043c6200027e565b5b6200044b85828601620003cf565b925050602083015167ffffffffffffffff8111156200046f576200046e6200027e565b5b6200047d85828601620003cf565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620004b48262000487565b9050919050565b620004c681620004a7565b82525050565b6000602082019050620004e36000830184620004bb565b92915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200053c57607f821691505b602082108103620005525762000551620004f4565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620005bc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200057d565b620005c886836200057d565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620006156200060f6200060984620005e0565b620005ea565b620005e0565b9050919050565b6000819050919050565b6200063183620005f4565b6200064962000640826200061c565b8484546200058a565b825550505050565b600090565b6200066062000651565b6200066d81848462000626565b505050565b5b8181101562000695576200068960008262000656565b60018101905062000673565b5050565b601f821115620006e457620006ae8162000558565b620006b9846200056d565b81016020851015620006c9578190505b620006e1620006d8856200056d565b83018262000672565b50505b505050565b600082821c905092915050565b60006200070960001984600802620006e9565b1980831691505092915050565b6000620007248383620006f6565b9150826002028217905092915050565b6200073f82620004e9565b67ffffffffffffffff8111156200075b576200075a6200029e565b5b62000767825462000523565b6200077482828562000699565b600060209050601f831160018114620007ac576000841562000797578287015190505b620007a3858262000716565b86555062000813565b601f198416620007bc8662000558565b60005b82811015620007e657848901518255600182019150602085019450602081019050620007bf565b8683101562000806578489015162000802601f891682620006f6565b8355505b6001600288020188555050505b505050505050565b614c2a806200082b6000396000f3fe6080604052600436106101e35760003560e01c806376967cbf11610102578063d5cb87a111610095578063e30c397811610064578063e30c3978146106f5578063e55661bd14610720578063e65deceb1461075d578063f2fde38b1461079a576101e3565b8063d5cb87a114610611578063dd99b73d1461063a578063dda0da001461067b578063df8e759a146106b8576101e3565b8063a3066e43116100d1578063a3066e4314610545578063b8c7871a1461056e578063ba848608146105ab578063bb21ac54146105e8576101e3565b806376967cbf146104af57806379ba5097146104d8578063839d7f11146104ef5780638da5cb5b1461051a576101e3565b80633b9ebeec1161017a5780636f11432d116101495780636f11432d1461041457806370876c9814610453578063715018a61461046f57806371e09bd314610486576101e3565b80633b9ebeec1461036e5780633f84dc1b146103975780635458c28e146103c25780636586bb70146103eb576101e3565b80631a7db56e116101b65780631a7db56e146102b4578063284293cf146102dd57806330546c9b1461031a5780633a525c2914610343576101e3565b80630f6bec9a146101e85780630fe421591461021157806310010ae81461023a57806319df118214610277575b600080fd5b3480156101f457600080fd5b5061020f600480360381019061020a91906132c0565b6107c3565b005b34801561021d57600080fd5b50610238600480360381019061023391906133ce565b610871565b005b34801561024657600080fd5b50610261600480360381019061025c919061340e565b610943565b60405161026e919061344a565b60405180910390f35b34801561028357600080fd5b5061029e6004803603810190610299919061340e565b610960565b6040516102ab9190613474565b60405180910390f35b3480156102c057600080fd5b506102db60048036038101906102d69190613552565b61098a565b005b3480156102e957600080fd5b5061030460048036038101906102ff919061340e565b610a38565b6040516103119190613474565b60405180910390f35b34801561032657600080fd5b50610341600480360381019061033c91906135ca565b610a62565b005b34801561034f57600080fd5b50610358610ab0565b6040516103659190613692565b60405180910390f35b34801561037a57600080fd5b5061039560048036038101906103909190613777565b610b42565b005b3480156103a357600080fd5b506103ac610bf0565b6040516103b9919061344a565b60405180910390f35b3480156103ce57600080fd5b506103e960048036038101906103e49190613552565b610bfa565b005b3480156103f757600080fd5b50610412600480360381019061040d91906137ef565b610ca8565b005b34801561042057600080fd5b5061043b6004803603810190610436919061340e565b610dbe565b60405161044a9392919061382b565b60405180910390f35b61046d60048036038101906104689190613862565b610e7c565b005b34801561047b57600080fd5b5061048461119d565b005b34801561049257600080fd5b506104ad60048036038101906104a89190613862565b6111b1565b005b3480156104bb57600080fd5b506104d660048036038101906104d19190613a38565b611244565b005b3480156104e457600080fd5b506104ed6112f2565b005b3480156104fb57600080fd5b50610504611381565b6040516105119190613692565b60405180910390f35b34801561052657600080fd5b5061052f611413565b60405161053c9190613ab0565b60405180910390f35b34801561055157600080fd5b5061056c60048036038101906105679190613a38565b61143c565b005b34801561057a57600080fd5b506105956004803603810190610590919061340e565b6114ea565b6040516105a29190613474565b60405180910390f35b3480156105b757600080fd5b506105d260048036038101906105cd91906137ef565b611515565b6040516105df9190613474565b60405180910390f35b3480156105f457600080fd5b5061060f600480360381019061060a91906137ef565b61156b565b005b34801561061d57600080fd5b5061063860048036038101906106339190613acb565b611676565b005b34801561064657600080fd5b50610661600480360381019061065c919061340e565b6117de565b604051610672959493929190613b1e565b60405180910390f35b34801561068757600080fd5b506106a2600480360381019061069d919061340e565b611975565b6040516106af9190613474565b60405180910390f35b3480156106c457600080fd5b506106df60048036038101906106da919061340e565b611987565b6040516106ec9190613ab0565b60405180910390f35b34801561070157600080fd5b5061070a611a26565b6040516107179190613ab0565b60405180910390f35b34801561072c57600080fd5b506107476004803603810190610742919061340e565b611a50565b6040516107549190613ab0565b60405180910390f35b34801561076957600080fd5b50610784600480360381019061077f9190613b7f565b611aef565b604051610791919061344a565b60405180910390f35b3480156107a657600080fd5b506107c160048036038101906107bc91906137ef565b611ced565b005b6107cb611d9a565b805182511461080f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080690613ccd565b60405180910390fd5b60005b825181101561086c5761085983828151811061083157610830613ced565b5b602002602001015183838151811061084c5761084b613ced565b5b6020026020010151611e34565b808061086490613d4b565b915050610812565b505050565b610879611e98565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036108e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108df90613ddf565b60405180910390fd5b80600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000600e6000838152602001908152602001600020549050919050565b60006007600083815260200190815260200160002060009054906101000a900460ff169050919050565b610992611d9a565b80518251146109d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109cd90613ccd565b60405180910390fd5b60005b8251811015610a3357610a208382815181106109f8576109f7613ced565b5b6020026020010151838381518110610a1357610a12613ced565b5b6020026020010151611f1f565b8080610a2b90613d4b565b9150506109d9565b505050565b60006007600083815260200190815260200160002060009054906101000a900460ff169050919050565b610a6a611d9a565b60005b8151811015610aac57610a99828281518110610a8c57610a8b613ced565b5b602002602001015161202c565b8080610aa490613d4b565b915050610a6d565b5050565b606060028054610abf90613e2e565b80601f0160208091040260200160405190810160405280929190818152602001828054610aeb90613e2e565b8015610b385780601f10610b0d57610100808354040283529160200191610b38565b820191906000526020600020905b815481529060010190602001808311610b1b57829003601f168201915b5050505050905090565b610b4a611d9a565b8051825114610b8e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b8590613ccd565b60405180910390fd5b60005b8251811015610beb57610bd8838281518110610bb057610baf613ced565b5b6020026020010151838381518110610bcb57610bca613ced565b5b60200260200101516120c0565b8080610be390613d4b565b915050610b91565b505050565b6000600f54905090565b610c02611d9a565b8051825114610c46576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3d90613ccd565b60405180910390fd5b60005b8251811015610ca357610c90838281518110610c6857610c67613ced565b5b6020026020010151838381518110610c8357610c82613ced565b5b6020026020010151612137565b8080610c9b90613d4b565b915050610c49565b505050565b610cb0611d9a565b8073ffffffffffffffffffffffffffffffffffffffff16600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614158015610d3b5750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b610d7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7190613eab565b60405180910390fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080600080600d60008681526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481526020016002820160009054906101000a900460ff1615151515815250509050806000015181602001518260400151935093509350509193909250565b60008111610ebf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb690613f17565b60405180910390fd5b610ec882610960565b610f07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610efe90613f83565b60405180910390fd5b80600e6000848152602001908152602001600020541015610f5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f5490613fef565b60405180910390fd5b610f6682612244565b6000600d60008481526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481526020016002820160009054906101000a900460ff161515151581525050905080604001511561108f576000816000015190508073ffffffffffffffffffffffffffffffffffffffff166325f5e8ee338460200151866040518463ffffffff1660e01b81526004016110579392919061400f565b600060405180830381600087803b15801561107157600080fd5b505af1158015611085573d6000803e3d6000fd5b5050505050611107565b6000816000015190508073ffffffffffffffffffffffffffffffffffffffff1663f0a8587b33856040518363ffffffff1660e01b81526004016110d3929190614046565b600060405180830381600087803b1580156110ed57600080fd5b505af1158015611101573d6000803e3d6000fd5b50505050505b61111183836123b7565b60008061113a84600e6000888152602001908152602001600020546127bd90919063ffffffff16565b915091508161117e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611175906140bb565b60405180910390fd5b80600e6000878152602001908152602001600020819055505050505050565b6111a5611e98565b6111af60006127e5565b565b6111b9611d9a565b6000806111e283600e60008781526020019081526020016000205461281690919063ffffffff16565b9150915081611226576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161121d90614127565b60405180910390fd5b80600e60008681526020019081526020016000208190555050505050565b61124c611d9a565b8051825114611290576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128790613ccd565b60405180910390fd5b60005b82518110156112ed576112da8382815181106112b2576112b1613ced565b5b60200260200101518383815181106112cd576112cc613ced565b5b6020026020010151612845565b80806112e590613d4b565b915050611293565b505050565b60006112fc612910565b90508073ffffffffffffffffffffffffffffffffffffffff1661131d611a26565b73ffffffffffffffffffffffffffffffffffffffff161461137557806040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161136c9190613ab0565b60405180910390fd5b61137e816127e5565b50565b60606003805461139090613e2e565b80601f01602080910402602001604051908101604052809291908181526020018280546113bc90613e2e565b80156114095780601f106113de57610100808354040283529160200191611409565b820191906000526020600020905b8154815290600101906020018083116113ec57829003601f168201915b5050505050905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611444611d9a565b8051825114611488576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161147f90613ccd565b60405180910390fd5b60005b82518110156114e5576114d28382815181106114aa576114a9613ced565b5b60200260200101518383815181106114c5576114c4613ced565b5b6020026020010151612918565b80806114dd90613d4b565b91505061148b565b505050565b60008060046000848152602001908152602001600020805461150b90613e2e565b9050119050919050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b611573611d9a565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806115f357506115f27f36372b07000000000000000000000000000000000000000000000000000000008273ffffffffffffffffffffffffffffffffffffffff1661298590919063ffffffff16565b5b611632576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161162990614193565b60405180910390fd5b80600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61167e611e98565b611687836114ea565b6116c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116bd906141ff565b60405180910390fd5b60006116d283836129aa565b905060405180606001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001821515815250600d600086815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001015560408201518160020160006101000a81548160ff021916908315150217905550905050837ff8be7536636830fa5411abf57f748eee1c95eab766b4c467aaca8f030b213fb7600d60008781526020019081526020016000206040516117d09190614343565b60405180910390a250505050565b606080600080600060046000878152602001908152602001600020600560008881526020019081526020016000206006600089815260200190815260200160002054600760008a815260200190815260200160002060009054906101000a900460ff1661184a8a611987565b84805461185690613e2e565b80601f016020809104026020016040519081016040528092919081815260200182805461188290613e2e565b80156118cf5780601f106118a4576101008083540402835291602001916118cf565b820191906000526020600020905b8154815290600101906020018083116118b257829003601f168201915b505050505094508380546118e290613e2e565b80601f016020809104026020016040519081016040528092919081815260200182805461190e90613e2e565b801561195b5780601f106119305761010080835404028352916020019161195b565b820191906000526020600020905b81548152906001019060200180831161193e57829003601f168201915b505050505093509450945094509450945091939590929450565b6000611980826114ea565b9050919050565b6000806008600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a1c57600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611a1e565b805b915050919050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806009600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ae557600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611ae7565b805b915050919050565b6000611af9611e98565b60008a5111611b3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b34906143aa565b60405180910390fd5b600080611b566001600f5461281690919063ffffffff16565b9150915081611b9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b9190614416565b60405180910390fd5b80600f81905550611bb0818d8d8b8b8b8b612ade565b6000611bbc8b8b6129aa565b905060405180606001604052808c73ffffffffffffffffffffffffffffffffffffffff1681526020018b8152602001821515815250600d600084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001015560408201518160020160006101000a81548160ff02191690831515021790555090505084600e600084815260200190815260200160002081905550817ff3736c52e82baf0a7809d035d2cb086da7ecc38af53628ad048adff1af85da41600d6000858152602001908152602001600020604051611cd29190614343565b60405180910390a28193505050509998505050505050505050565b611cf5611e98565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16611d55611413565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000611da4612910565b90508073ffffffffffffffffffffffffffffffffffffffff16611dc5611413565b73ffffffffffffffffffffffffffffffffffffffff1614158015611def5750611ded81612c10565b155b15611e3157806040517f8a08cbf5000000000000000000000000000000000000000000000000000000008152600401611e289190613ab0565b60405180910390fd5b50565b611e3d826114ea565b611e7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7390614482565b60405180910390fd5b8060066000848152602001908152602001600020819055505050565b611ea0612910565b73ffffffffffffffffffffffffffffffffffffffff16611ebe611413565b73ffffffffffffffffffffffffffffffffffffffff1614611f1d57611ee1612910565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611f149190613ab0565b60405180910390fd5b565b611f28826114ea565b611f67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f5e90614482565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611fd6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fcd906144ee565b60405180910390fd5b806008600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b612035816114ea565b612074576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206b90614482565b60405180910390fd5b61207d81612c66565b61208681612d4d565b7f63990d06670189d4fb8d01ea4be2772448398bd273ca4e119185ef26ee5007b7816040516120b5919061344a565b60405180910390a150565b6120c9826114ea565b612108576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120ff90614482565b60405180910390fd5b806007600084815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b612140826114ea565b61217f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161217690614482565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036121ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e5906144ee565b60405180910390fd5b806009600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000600d60008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481526020016002820160009054906101000a900460ff16151515158152505090508060400151156123b3576000816000015190508073ffffffffffffffffffffffffffffffffffffffff1663b419c80783602001516040518263ffffffff1660e01b8152600401612331919061344a565b602060405180830381865afa15801561234e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123729190614523565b6123b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123a89061459c565b60405180910390fd5b505b5050565b600081116123fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123f190614608565b60405180910390fd5b6000600660008481526020019081526020016000205490506000810361242057506127b9565b600061242b84611987565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361249c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161249390614674565b60405180910390fd5b6000806124b28585612da990919063ffffffff16565b91509150816124f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124ed906146e0565b60405180910390fd5b600061250187611a50565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146126d05760008173ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b81526004016125729190613ab0565b602060405180830381865afa15801561258f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b39190614715565b9050828110156125f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125ef9061478e565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166323b872dd3387866040518463ffffffff1660e01b8152600401612635939291906147ae565b6020604051808303816000875af1158015612654573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126789190614523565b5060003411156126ca573373ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501580156126c8573d6000803e3d6000fd5b505b506127b3565b81341015612713576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161270a9061478e565b60405180910390fd5b6000823461272191906147e5565b90508473ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015612769573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156127b0573d6000803e3d6000fd5b50505b50505050505b5050565b600080838311156127d457600080915091506127de565b6001838503915091505b9250929050565b600160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905561281381612dfc565b50565b600080600083850190508481101561283557600080925092505061283e565b60018192509250505b9250929050565b600060046000848152602001908152602001600020805461286590613e2e565b9050116128a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289e90614482565b60405180910390fd5b60008151116128eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128e290614865565b60405180910390fd5b8060046000848152602001908152602001600020908161290b9190614a31565b505050565b600033905090565b612921826114ea565b612960576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161295790614482565b60405180910390fd5b806005600084815260200190815260200160002090816129809190614a31565b505050565b600061299083612ec0565b80156129a257506129a18383612f0d565b5b905092915050565b6000806129b684612fac565b905060006129c385613036565b905081806129ce5750805b612a0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a0490614b4f565b60405180910390fd5b8115612ad35760008590508073ffffffffffffffffffffffffffffffffffffffff1663b419c807866040518263ffffffff1660e01b8152600401612a51919061344a565b602060405180830381865afa158015612a6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a929190614523565b612ad1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac89061459c565b60405180910390fd5b505b819250505092915050565b85600460008981526020019081526020016000209081612afe9190614a31565b5084600560008981526020019081526020016000209081612b1f9190614a31565b50836006600089815260200190815260200160002081905550826007600089815260200190815260200160002060006101000a81548160ff021916908315150217905550816008600089815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806009600089815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050505050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600460008281526020019081526020016000206000612c8591906130c0565b600560008281526020019081526020016000206000612ca491906130c0565b60066000828152602001908152602001600020600090556007600082815260200190815260200160002060006101000a81549060ff02191690556008600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550565b600d6000828152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560018201600090556002820160006101000a81549060ff0219169055505050565b60008060008403612dc1576001600091509150612df5565b6000838502905083858281612dd957612dd8614b6f565b5b0414612dec576000809250925050612df5565b60018192509250505b9250929050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000612eec827f01ffc9a700000000000000000000000000000000000000000000000000000000612f0d565b8015612f065750612f048263ffffffff60e01b612f0d565b155b9050919050565b60008082604051602401612f219190614bd9565b6040516020818303038152906040526301ffc9a760e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000806000602060008551602087018a617530fa92503d91506000519050828015612f94575060208210155b8015612fa05750600081115b94505050505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415801561302f575061302e7ff4e25cdb000000000000000000000000000000000000000000000000000000008373ffffffffffffffffffffffffffffffffffffffff1661298590919063ffffffff16565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156130b957506130b87f87c91820000000000000000000000000000000000000000000000000000000008373ffffffffffffffffffffffffffffffffffffffff1661298590919063ffffffff16565b5b9050919050565b5080546130cc90613e2e565b6000825580601f106130de57506130fd565b601f0160209004906000526020600020908101906130fc9190613100565b5b50565b5b80821115613119576000816000905550600101613101565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61317f82613136565b810181811067ffffffffffffffff8211171561319e5761319d613147565b5b80604052505050565b60006131b161311d565b90506131bd8282613176565b919050565b600067ffffffffffffffff8211156131dd576131dc613147565b5b602082029050602081019050919050565b600080fd5b6000819050919050565b613206816131f3565b811461321157600080fd5b50565b600081359050613223816131fd565b92915050565b600061323c613237846131c2565b6131a7565b9050808382526020820190506020840283018581111561325f5761325e6131ee565b5b835b8181101561328857806132748882613214565b845260208401935050602081019050613261565b5050509392505050565b600082601f8301126132a7576132a6613131565b5b81356132b7848260208601613229565b91505092915050565b600080604083850312156132d7576132d6613127565b5b600083013567ffffffffffffffff8111156132f5576132f461312c565b5b61330185828601613292565b925050602083013567ffffffffffffffff8111156133225761332161312c565b5b61332e85828601613292565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061336382613338565b9050919050565b61337381613358565b811461337e57600080fd5b50565b6000813590506133908161336a565b92915050565b60008115159050919050565b6133ab81613396565b81146133b657600080fd5b50565b6000813590506133c8816133a2565b92915050565b600080604083850312156133e5576133e4613127565b5b60006133f385828601613381565b9250506020613404858286016133b9565b9150509250929050565b60006020828403121561342457613423613127565b5b600061343284828501613214565b91505092915050565b613444816131f3565b82525050565b600060208201905061345f600083018461343b565b92915050565b61346e81613396565b82525050565b60006020820190506134896000830184613465565b92915050565b600067ffffffffffffffff8211156134aa576134a9613147565b5b602082029050602081019050919050565b60006134ce6134c98461348f565b6131a7565b905080838252602082019050602084028301858111156134f1576134f06131ee565b5b835b8181101561351a57806135068882613381565b8452602084019350506020810190506134f3565b5050509392505050565b600082601f83011261353957613538613131565b5b81356135498482602086016134bb565b91505092915050565b6000806040838503121561356957613568613127565b5b600083013567ffffffffffffffff8111156135875761358661312c565b5b61359385828601613292565b925050602083013567ffffffffffffffff8111156135b4576135b361312c565b5b6135c085828601613524565b9150509250929050565b6000602082840312156135e0576135df613127565b5b600082013567ffffffffffffffff8111156135fe576135fd61312c565b5b61360a84828501613292565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561364d578082015181840152602081019050613632565b60008484015250505050565b600061366482613613565b61366e818561361e565b935061367e81856020860161362f565b61368781613136565b840191505092915050565b600060208201905081810360008301526136ac8184613659565b905092915050565b600067ffffffffffffffff8211156136cf576136ce613147565b5b602082029050602081019050919050565b60006136f36136ee846136b4565b6131a7565b90508083825260208201905060208402830185811115613716576137156131ee565b5b835b8181101561373f578061372b88826133b9565b845260208401935050602081019050613718565b5050509392505050565b600082601f83011261375e5761375d613131565b5b813561376e8482602086016136e0565b91505092915050565b6000806040838503121561378e5761378d613127565b5b600083013567ffffffffffffffff8111156137ac576137ab61312c565b5b6137b885828601613292565b925050602083013567ffffffffffffffff8111156137d9576137d861312c565b5b6137e585828601613749565b9150509250929050565b60006020828403121561380557613804613127565b5b600061381384828501613381565b91505092915050565b61382581613358565b82525050565b6000606082019050613840600083018661381c565b61384d602083018561343b565b61385a6040830184613465565b949350505050565b6000806040838503121561387957613878613127565b5b600061388785828601613214565b925050602061389885828601613214565b9150509250929050565b600067ffffffffffffffff8211156138bd576138bc613147565b5b602082029050602081019050919050565b600080fd5b600067ffffffffffffffff8211156138ee576138ed613147565b5b6138f782613136565b9050602081019050919050565b82818337600083830152505050565b6000613926613921846138d3565b6131a7565b905082815260208101848484011115613942576139416138ce565b5b61394d848285613904565b509392505050565b600082601f83011261396a57613969613131565b5b813561397a848260208601613913565b91505092915050565b6000613996613991846138a2565b6131a7565b905080838252602082019050602084028301858111156139b9576139b86131ee565b5b835b81811015613a0057803567ffffffffffffffff8111156139de576139dd613131565b5b8086016139eb8982613955565b855260208501945050506020810190506139bb565b5050509392505050565b600082601f830112613a1f57613a1e613131565b5b8135613a2f848260208601613983565b91505092915050565b60008060408385031215613a4f57613a4e613127565b5b600083013567ffffffffffffffff811115613a6d57613a6c61312c565b5b613a7985828601613292565b925050602083013567ffffffffffffffff811115613a9a57613a9961312c565b5b613aa685828601613a0a565b9150509250929050565b6000602082019050613ac5600083018461381c565b92915050565b600080600060608486031215613ae457613ae3613127565b5b6000613af286828701613214565b9350506020613b0386828701613381565b9250506040613b1486828701613214565b9150509250925092565b600060a0820190508181036000830152613b388188613659565b90508181036020830152613b4c8187613659565b9050613b5b604083018661343b565b613b686060830185613465565b613b75608083018461381c565b9695505050505050565b60008060008060008060008060006101208a8c031215613ba257613ba1613127565b5b60008a013567ffffffffffffffff811115613bc057613bbf61312c565b5b613bcc8c828d01613955565b99505060208a013567ffffffffffffffff811115613bed57613bec61312c565b5b613bf98c828d01613955565b9850506040613c0a8c828d01613381565b9750506060613c1b8c828d01613214565b9650506080613c2c8c828d01613214565b95505060a0613c3d8c828d016133b9565b94505060c0613c4e8c828d01613381565b93505060e0613c5f8c828d01613381565b925050610100613c718c828d01613214565b9150509295985092959850929598565b7f504152414d5f44494d5f4d49534d415443480000000000000000000000000000600082015250565b6000613cb760128361361e565b9150613cc282613c81565b602082019050919050565b60006020820190508181036000830152613ce681613caa565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613d56826131f3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d8857613d87613d1c565b5b600182019050919050565b7f4e756c6c204164647265737320616c6c6f776564000000000000000000000000600082015250565b6000613dc960148361361e565b9150613dd482613d93565b602082019050919050565b60006020820190508181036000830152613df881613dbc565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613e4657607f821691505b602082108103613e5957613e58613dff565b5b50919050565b7f494e56414c49445f4d45524348414e5400000000000000000000000000000000600082015250565b6000613e9560108361361e565b9150613ea082613e5f565b602082019050919050565b60006020820190508181036000830152613ec481613e88565b9050919050565b7f5a45524f5f4150504c595f434f554e5400000000000000000000000000000000600082015250565b6000613f0160108361361e565b9150613f0c82613ecb565b602082019050919050565b60006020820190508181036000830152613f3081613ef4565b9050919050565b7f5052445f4e4f545f4f4e53414c45000000000000000000000000000000000000600082015250565b6000613f6d600e8361361e565b9150613f7882613f37565b602082019050919050565b60006020820190508181036000830152613f9c81613f60565b9050919050565b7f4f55545f4f465f53544f434b0000000000000000000000000000000000000000600082015250565b6000613fd9600c8361361e565b9150613fe482613fa3565b602082019050919050565b6000602082019050818103600083015261400881613fcc565b9050919050565b6000606082019050614024600083018661381c565b614031602083018561343b565b61403e604083018461343b565b949350505050565b600060408201905061405b600083018561381c565b614068602083018461343b565b9392505050565b7f52454d494e5f554e444552464c4f570000000000000000000000000000000000600082015250565b60006140a5600f8361361e565b91506140b08261406f565b602082019050919050565b600060208201905081810360008301526140d481614098565b9050919050565b7f53544f434b5f4f564552464c4f57000000000000000000000000000000000000600082015250565b6000614111600e8361361e565b915061411c826140db565b602082019050919050565b6000602082019050818103600083015261414081614104565b9050919050565b7f554e535550504f52545f43555252454e43590000000000000000000000000000600082015250565b600061417d60128361361e565b915061418882614147565b602082019050919050565b600060208201905081810360008301526141ac81614170565b9050919050565b7f4e4f5f5052445f444546494e4544000000000000000000000000000000000000600082015250565b60006141e9600e8361361e565b91506141f4826141b3565b602082019050919050565b60006020820190508181036000830152614218816141dc565b9050919050565b60008160001c9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061425f61425a8361421f565b61422c565b9050919050565b61426f81613358565b82525050565b6000819050919050565b600061429261428d8361421f565b614275565b9050919050565b6142a2816131f3565b82525050565b600060ff82169050919050565b60006142c86142c38361421f565b6142a8565b9050919050565b6142d881613396565b82525050565b6060820160008083015490506142f38161424c565b6143006000860182614266565b50600183015490506143118161427f565b61431e6020860182614299565b506002830154905061432f816142b5565b61433c60408601826142cf565b5050505050565b600060608201905061435860008301846142de565b92915050565b7f4e4f5f5052445f4e414d45000000000000000000000000000000000000000000600082015250565b6000614394600b8361361e565b915061439f8261435e565b602082019050919050565b600060208201905081810360008301526143c381614387565b9050919050565b7f54504c5f49445f4f564552464c4f570000000000000000000000000000000000600082015250565b6000614400600f8361361e565b915061440b826143ca565b602082019050919050565b6000602082019050818103600083015261442f816143f3565b9050919050565b7f4e4f5f54504c5f444546494e4544000000000000000000000000000000000000600082015250565b600061446c600e8361361e565b915061447782614436565b602082019050919050565b6000602082019050818103600083015261449b8161445f565b9050919050565b7f4e554c4c5f414444524553530000000000000000000000000000000000000000600082015250565b60006144d8600c8361361e565b91506144e3826144a2565b602082019050919050565b60006020820190508181036000830152614507816144cb565b9050919050565b60008151905061451d816133a2565b92915050565b60006020828403121561453957614538613127565b5b60006145478482850161450e565b91505092915050565b7f4e4f5f544f4b454e5f4944000000000000000000000000000000000000000000600082015250565b6000614586600b8361361e565b915061459182614550565b602082019050919050565b600060208201905081810360008301526145b581614579565b9050919050565b7f5a45524f5f4150504c59434f554e540000000000000000000000000000000000600082015250565b60006145f2600f8361361e565b91506145fd826145bc565b602082019050919050565b60006020820190508181036000830152614621816145e5565b9050919050565b7f4e4f5f4d45524348414e545f4144445200000000000000000000000000000000600082015250565b600061465e60108361361e565b915061466982614628565b602082019050919050565b6000602082019050818103600083015261468d81614651565b9050919050565b7f4f505f434f53545f4f564552464c4f5700000000000000000000000000000000600082015250565b60006146ca60108361361e565b91506146d582614694565b602082019050919050565b600060208201905081810360008301526146f9816146bd565b9050919050565b60008151905061470f816131fd565b92915050565b60006020828403121561472b5761472a613127565b5b600061473984828501614700565b91505092915050565b7f554e53554646494349454e545f42414c414e4345000000000000000000000000600082015250565b600061477860148361361e565b915061478382614742565b602082019050919050565b600060208201905081810360008301526147a78161476b565b9050919050565b60006060820190506147c3600083018661381c565b6147d0602083018561381c565b6147dd604083018461343b565b949350505050565b60006147f0826131f3565b91506147fb836131f3565b925082820390508181111561481357614812613d1c565b5b92915050565b7f4e4f5f54504c5f4e414d45000000000000000000000000000000000000000000600082015250565b600061484f600b8361361e565b915061485a82614819565b602082019050919050565b6000602082019050818103600083015261487e81614842565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026148e77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826148aa565b6148f186836148aa565b95508019841693508086168417925050509392505050565b6000819050919050565b600061492e614929614924846131f3565b614909565b6131f3565b9050919050565b6000819050919050565b61494883614913565b61495c61495482614935565b8484546148b7565b825550505050565b600090565b614971614964565b61497c81848461493f565b505050565b5b818110156149a057614995600082614969565b600181019050614982565b5050565b601f8211156149e5576149b681614885565b6149bf8461489a565b810160208510156149ce578190505b6149e26149da8561489a565b830182614981565b50505b505050565b600082821c905092915050565b6000614a08600019846008026149ea565b1980831691505092915050565b6000614a2183836149f7565b9150826002028217905092915050565b614a3a82613613565b67ffffffffffffffff811115614a5357614a52613147565b5b614a5d8254613e2e565b614a688282856149a4565b600060209050601f831160018114614a9b5760008415614a89578287015190505b614a938582614a15565b865550614afb565b601f198416614aa986614885565b60005b82811015614ad157848901518255600182019150602085019450602081019050614aac565b86831015614aee5784890151614aea601f8916826149f7565b8355505b6001600288020188555050505b505050505050565b7f4f5f4241445f544f4b454e000000000000000000000000000000000000000000600082015250565b6000614b39600b8361361e565b9150614b4482614b03565b602082019050919050565b60006020820190508181036000830152614b6881614b2c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614bd381614b9e565b82525050565b6000602082019050614bee6000830184614bca565b9291505056fea26469706673582212200ec00e6808af38ac1c8a0166558ac6cb7627e85aec9c07a62d59fbcee6a9c2c764736f6c6343000814003300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000e486f706576657273652053686f70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002053656c6c207072696d6974697665204e465420666f7220486f70657665727365
Deployed ByteCode
0x6080604052600436106101e35760003560e01c806376967cbf11610102578063d5cb87a111610095578063e30c397811610064578063e30c3978146106f5578063e55661bd14610720578063e65deceb1461075d578063f2fde38b1461079a576101e3565b8063d5cb87a114610611578063dd99b73d1461063a578063dda0da001461067b578063df8e759a146106b8576101e3565b8063a3066e43116100d1578063a3066e4314610545578063b8c7871a1461056e578063ba848608146105ab578063bb21ac54146105e8576101e3565b806376967cbf146104af57806379ba5097146104d8578063839d7f11146104ef5780638da5cb5b1461051a576101e3565b80633b9ebeec1161017a5780636f11432d116101495780636f11432d1461041457806370876c9814610453578063715018a61461046f57806371e09bd314610486576101e3565b80633b9ebeec1461036e5780633f84dc1b146103975780635458c28e146103c25780636586bb70146103eb576101e3565b80631a7db56e116101b65780631a7db56e146102b4578063284293cf146102dd57806330546c9b1461031a5780633a525c2914610343576101e3565b80630f6bec9a146101e85780630fe421591461021157806310010ae81461023a57806319df118214610277575b600080fd5b3480156101f457600080fd5b5061020f600480360381019061020a91906132c0565b6107c3565b005b34801561021d57600080fd5b50610238600480360381019061023391906133ce565b610871565b005b34801561024657600080fd5b50610261600480360381019061025c919061340e565b610943565b60405161026e919061344a565b60405180910390f35b34801561028357600080fd5b5061029e6004803603810190610299919061340e565b610960565b6040516102ab9190613474565b60405180910390f35b3480156102c057600080fd5b506102db60048036038101906102d69190613552565b61098a565b005b3480156102e957600080fd5b5061030460048036038101906102ff919061340e565b610a38565b6040516103119190613474565b60405180910390f35b34801561032657600080fd5b50610341600480360381019061033c91906135ca565b610a62565b005b34801561034f57600080fd5b50610358610ab0565b6040516103659190613692565b60405180910390f35b34801561037a57600080fd5b5061039560048036038101906103909190613777565b610b42565b005b3480156103a357600080fd5b506103ac610bf0565b6040516103b9919061344a565b60405180910390f35b3480156103ce57600080fd5b506103e960048036038101906103e49190613552565b610bfa565b005b3480156103f757600080fd5b50610412600480360381019061040d91906137ef565b610ca8565b005b34801561042057600080fd5b5061043b6004803603810190610436919061340e565b610dbe565b60405161044a9392919061382b565b60405180910390f35b61046d60048036038101906104689190613862565b610e7c565b005b34801561047b57600080fd5b5061048461119d565b005b34801561049257600080fd5b506104ad60048036038101906104a89190613862565b6111b1565b005b3480156104bb57600080fd5b506104d660048036038101906104d19190613a38565b611244565b005b3480156104e457600080fd5b506104ed6112f2565b005b3480156104fb57600080fd5b50610504611381565b6040516105119190613692565b60405180910390f35b34801561052657600080fd5b5061052f611413565b60405161053c9190613ab0565b60405180910390f35b34801561055157600080fd5b5061056c60048036038101906105679190613a38565b61143c565b005b34801561057a57600080fd5b506105956004803603810190610590919061340e565b6114ea565b6040516105a29190613474565b60405180910390f35b3480156105b757600080fd5b506105d260048036038101906105cd91906137ef565b611515565b6040516105df9190613474565b60405180910390f35b3480156105f457600080fd5b5061060f600480360381019061060a91906137ef565b61156b565b005b34801561061d57600080fd5b5061063860048036038101906106339190613acb565b611676565b005b34801561064657600080fd5b50610661600480360381019061065c919061340e565b6117de565b604051610672959493929190613b1e565b60405180910390f35b34801561068757600080fd5b506106a2600480360381019061069d919061340e565b611975565b6040516106af9190613474565b60405180910390f35b3480156106c457600080fd5b506106df60048036038101906106da919061340e565b611987565b6040516106ec9190613ab0565b60405180910390f35b34801561070157600080fd5b5061070a611a26565b6040516107179190613ab0565b60405180910390f35b34801561072c57600080fd5b506107476004803603810190610742919061340e565b611a50565b6040516107549190613ab0565b60405180910390f35b34801561076957600080fd5b50610784600480360381019061077f9190613b7f565b611aef565b604051610791919061344a565b60405180910390f35b3480156107a657600080fd5b506107c160048036038101906107bc91906137ef565b611ced565b005b6107cb611d9a565b805182511461080f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080690613ccd565b60405180910390fd5b60005b825181101561086c5761085983828151811061083157610830613ced565b5b602002602001015183838151811061084c5761084b613ced565b5b6020026020010151611e34565b808061086490613d4b565b915050610812565b505050565b610879611e98565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036108e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108df90613ddf565b60405180910390fd5b80600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000600e6000838152602001908152602001600020549050919050565b60006007600083815260200190815260200160002060009054906101000a900460ff169050919050565b610992611d9a565b80518251146109d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109cd90613ccd565b60405180910390fd5b60005b8251811015610a3357610a208382815181106109f8576109f7613ced565b5b6020026020010151838381518110610a1357610a12613ced565b5b6020026020010151611f1f565b8080610a2b90613d4b565b9150506109d9565b505050565b60006007600083815260200190815260200160002060009054906101000a900460ff169050919050565b610a6a611d9a565b60005b8151811015610aac57610a99828281518110610a8c57610a8b613ced565b5b602002602001015161202c565b8080610aa490613d4b565b915050610a6d565b5050565b606060028054610abf90613e2e565b80601f0160208091040260200160405190810160405280929190818152602001828054610aeb90613e2e565b8015610b385780601f10610b0d57610100808354040283529160200191610b38565b820191906000526020600020905b815481529060010190602001808311610b1b57829003601f168201915b5050505050905090565b610b4a611d9a565b8051825114610b8e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b8590613ccd565b60405180910390fd5b60005b8251811015610beb57610bd8838281518110610bb057610baf613ced565b5b6020026020010151838381518110610bcb57610bca613ced565b5b60200260200101516120c0565b8080610be390613d4b565b915050610b91565b505050565b6000600f54905090565b610c02611d9a565b8051825114610c46576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3d90613ccd565b60405180910390fd5b60005b8251811015610ca357610c90838281518110610c6857610c67613ced565b5b6020026020010151838381518110610c8357610c82613ced565b5b6020026020010151612137565b8080610c9b90613d4b565b915050610c49565b505050565b610cb0611d9a565b8073ffffffffffffffffffffffffffffffffffffffff16600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614158015610d3b5750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b610d7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7190613eab565b60405180910390fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080600080600d60008681526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481526020016002820160009054906101000a900460ff1615151515815250509050806000015181602001518260400151935093509350509193909250565b60008111610ebf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb690613f17565b60405180910390fd5b610ec882610960565b610f07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610efe90613f83565b60405180910390fd5b80600e6000848152602001908152602001600020541015610f5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f5490613fef565b60405180910390fd5b610f6682612244565b6000600d60008481526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481526020016002820160009054906101000a900460ff161515151581525050905080604001511561108f576000816000015190508073ffffffffffffffffffffffffffffffffffffffff166325f5e8ee338460200151866040518463ffffffff1660e01b81526004016110579392919061400f565b600060405180830381600087803b15801561107157600080fd5b505af1158015611085573d6000803e3d6000fd5b5050505050611107565b6000816000015190508073ffffffffffffffffffffffffffffffffffffffff1663f0a8587b33856040518363ffffffff1660e01b81526004016110d3929190614046565b600060405180830381600087803b1580156110ed57600080fd5b505af1158015611101573d6000803e3d6000fd5b50505050505b61111183836123b7565b60008061113a84600e6000888152602001908152602001600020546127bd90919063ffffffff16565b915091508161117e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611175906140bb565b60405180910390fd5b80600e6000878152602001908152602001600020819055505050505050565b6111a5611e98565b6111af60006127e5565b565b6111b9611d9a565b6000806111e283600e60008781526020019081526020016000205461281690919063ffffffff16565b9150915081611226576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161121d90614127565b60405180910390fd5b80600e60008681526020019081526020016000208190555050505050565b61124c611d9a565b8051825114611290576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128790613ccd565b60405180910390fd5b60005b82518110156112ed576112da8382815181106112b2576112b1613ced565b5b60200260200101518383815181106112cd576112cc613ced565b5b6020026020010151612845565b80806112e590613d4b565b915050611293565b505050565b60006112fc612910565b90508073ffffffffffffffffffffffffffffffffffffffff1661131d611a26565b73ffffffffffffffffffffffffffffffffffffffff161461137557806040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161136c9190613ab0565b60405180910390fd5b61137e816127e5565b50565b60606003805461139090613e2e565b80601f01602080910402602001604051908101604052809291908181526020018280546113bc90613e2e565b80156114095780601f106113de57610100808354040283529160200191611409565b820191906000526020600020905b8154815290600101906020018083116113ec57829003601f168201915b5050505050905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611444611d9a565b8051825114611488576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161147f90613ccd565b60405180910390fd5b60005b82518110156114e5576114d28382815181106114aa576114a9613ced565b5b60200260200101518383815181106114c5576114c4613ced565b5b6020026020010151612918565b80806114dd90613d4b565b91505061148b565b505050565b60008060046000848152602001908152602001600020805461150b90613e2e565b9050119050919050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b611573611d9a565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806115f357506115f27f36372b07000000000000000000000000000000000000000000000000000000008273ffffffffffffffffffffffffffffffffffffffff1661298590919063ffffffff16565b5b611632576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161162990614193565b60405180910390fd5b80600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61167e611e98565b611687836114ea565b6116c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116bd906141ff565b60405180910390fd5b60006116d283836129aa565b905060405180606001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001821515815250600d600086815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001015560408201518160020160006101000a81548160ff021916908315150217905550905050837ff8be7536636830fa5411abf57f748eee1c95eab766b4c467aaca8f030b213fb7600d60008781526020019081526020016000206040516117d09190614343565b60405180910390a250505050565b606080600080600060046000878152602001908152602001600020600560008881526020019081526020016000206006600089815260200190815260200160002054600760008a815260200190815260200160002060009054906101000a900460ff1661184a8a611987565b84805461185690613e2e565b80601f016020809104026020016040519081016040528092919081815260200182805461188290613e2e565b80156118cf5780601f106118a4576101008083540402835291602001916118cf565b820191906000526020600020905b8154815290600101906020018083116118b257829003601f168201915b505050505094508380546118e290613e2e565b80601f016020809104026020016040519081016040528092919081815260200182805461190e90613e2e565b801561195b5780601f106119305761010080835404028352916020019161195b565b820191906000526020600020905b81548152906001019060200180831161193e57829003601f168201915b505050505093509450945094509450945091939590929450565b6000611980826114ea565b9050919050565b6000806008600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a1c57600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611a1e565b805b915050919050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806009600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ae557600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611ae7565b805b915050919050565b6000611af9611e98565b60008a5111611b3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b34906143aa565b60405180910390fd5b600080611b566001600f5461281690919063ffffffff16565b9150915081611b9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b9190614416565b60405180910390fd5b80600f81905550611bb0818d8d8b8b8b8b612ade565b6000611bbc8b8b6129aa565b905060405180606001604052808c73ffffffffffffffffffffffffffffffffffffffff1681526020018b8152602001821515815250600d600084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001015560408201518160020160006101000a81548160ff02191690831515021790555090505084600e600084815260200190815260200160002081905550817ff3736c52e82baf0a7809d035d2cb086da7ecc38af53628ad048adff1af85da41600d6000858152602001908152602001600020604051611cd29190614343565b60405180910390a28193505050509998505050505050505050565b611cf5611e98565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16611d55611413565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000611da4612910565b90508073ffffffffffffffffffffffffffffffffffffffff16611dc5611413565b73ffffffffffffffffffffffffffffffffffffffff1614158015611def5750611ded81612c10565b155b15611e3157806040517f8a08cbf5000000000000000000000000000000000000000000000000000000008152600401611e289190613ab0565b60405180910390fd5b50565b611e3d826114ea565b611e7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7390614482565b60405180910390fd5b8060066000848152602001908152602001600020819055505050565b611ea0612910565b73ffffffffffffffffffffffffffffffffffffffff16611ebe611413565b73ffffffffffffffffffffffffffffffffffffffff1614611f1d57611ee1612910565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611f149190613ab0565b60405180910390fd5b565b611f28826114ea565b611f67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f5e90614482565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611fd6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fcd906144ee565b60405180910390fd5b806008600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b612035816114ea565b612074576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206b90614482565b60405180910390fd5b61207d81612c66565b61208681612d4d565b7f63990d06670189d4fb8d01ea4be2772448398bd273ca4e119185ef26ee5007b7816040516120b5919061344a565b60405180910390a150565b6120c9826114ea565b612108576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120ff90614482565b60405180910390fd5b806007600084815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b612140826114ea565b61217f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161217690614482565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036121ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e5906144ee565b60405180910390fd5b806009600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000600d60008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481526020016002820160009054906101000a900460ff16151515158152505090508060400151156123b3576000816000015190508073ffffffffffffffffffffffffffffffffffffffff1663b419c80783602001516040518263ffffffff1660e01b8152600401612331919061344a565b602060405180830381865afa15801561234e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123729190614523565b6123b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123a89061459c565b60405180910390fd5b505b5050565b600081116123fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123f190614608565b60405180910390fd5b6000600660008481526020019081526020016000205490506000810361242057506127b9565b600061242b84611987565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361249c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161249390614674565b60405180910390fd5b6000806124b28585612da990919063ffffffff16565b91509150816124f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124ed906146e0565b60405180910390fd5b600061250187611a50565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146126d05760008173ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b81526004016125729190613ab0565b602060405180830381865afa15801561258f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b39190614715565b9050828110156125f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125ef9061478e565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166323b872dd3387866040518463ffffffff1660e01b8152600401612635939291906147ae565b6020604051808303816000875af1158015612654573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126789190614523565b5060003411156126ca573373ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501580156126c8573d6000803e3d6000fd5b505b506127b3565b81341015612713576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161270a9061478e565b60405180910390fd5b6000823461272191906147e5565b90508473ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015612769573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156127b0573d6000803e3d6000fd5b50505b50505050505b5050565b600080838311156127d457600080915091506127de565b6001838503915091505b9250929050565b600160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905561281381612dfc565b50565b600080600083850190508481101561283557600080925092505061283e565b60018192509250505b9250929050565b600060046000848152602001908152602001600020805461286590613e2e565b9050116128a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289e90614482565b60405180910390fd5b60008151116128eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128e290614865565b60405180910390fd5b8060046000848152602001908152602001600020908161290b9190614a31565b505050565b600033905090565b612921826114ea565b612960576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161295790614482565b60405180910390fd5b806005600084815260200190815260200160002090816129809190614a31565b505050565b600061299083612ec0565b80156129a257506129a18383612f0d565b5b905092915050565b6000806129b684612fac565b905060006129c385613036565b905081806129ce5750805b612a0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a0490614b4f565b60405180910390fd5b8115612ad35760008590508073ffffffffffffffffffffffffffffffffffffffff1663b419c807866040518263ffffffff1660e01b8152600401612a51919061344a565b602060405180830381865afa158015612a6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a929190614523565b612ad1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac89061459c565b60405180910390fd5b505b819250505092915050565b85600460008981526020019081526020016000209081612afe9190614a31565b5084600560008981526020019081526020016000209081612b1f9190614a31565b50836006600089815260200190815260200160002081905550826007600089815260200190815260200160002060006101000a81548160ff021916908315150217905550816008600089815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806009600089815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050505050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600460008281526020019081526020016000206000612c8591906130c0565b600560008281526020019081526020016000206000612ca491906130c0565b60066000828152602001908152602001600020600090556007600082815260200190815260200160002060006101000a81549060ff02191690556008600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550565b600d6000828152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560018201600090556002820160006101000a81549060ff0219169055505050565b60008060008403612dc1576001600091509150612df5565b6000838502905083858281612dd957612dd8614b6f565b5b0414612dec576000809250925050612df5565b60018192509250505b9250929050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000612eec827f01ffc9a700000000000000000000000000000000000000000000000000000000612f0d565b8015612f065750612f048263ffffffff60e01b612f0d565b155b9050919050565b60008082604051602401612f219190614bd9565b6040516020818303038152906040526301ffc9a760e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000806000602060008551602087018a617530fa92503d91506000519050828015612f94575060208210155b8015612fa05750600081115b94505050505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415801561302f575061302e7ff4e25cdb000000000000000000000000000000000000000000000000000000008373ffffffffffffffffffffffffffffffffffffffff1661298590919063ffffffff16565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156130b957506130b87f87c91820000000000000000000000000000000000000000000000000000000008373ffffffffffffffffffffffffffffffffffffffff1661298590919063ffffffff16565b5b9050919050565b5080546130cc90613e2e565b6000825580601f106130de57506130fd565b601f0160209004906000526020600020908101906130fc9190613100565b5b50565b5b80821115613119576000816000905550600101613101565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61317f82613136565b810181811067ffffffffffffffff8211171561319e5761319d613147565b5b80604052505050565b60006131b161311d565b90506131bd8282613176565b919050565b600067ffffffffffffffff8211156131dd576131dc613147565b5b602082029050602081019050919050565b600080fd5b6000819050919050565b613206816131f3565b811461321157600080fd5b50565b600081359050613223816131fd565b92915050565b600061323c613237846131c2565b6131a7565b9050808382526020820190506020840283018581111561325f5761325e6131ee565b5b835b8181101561328857806132748882613214565b845260208401935050602081019050613261565b5050509392505050565b600082601f8301126132a7576132a6613131565b5b81356132b7848260208601613229565b91505092915050565b600080604083850312156132d7576132d6613127565b5b600083013567ffffffffffffffff8111156132f5576132f461312c565b5b61330185828601613292565b925050602083013567ffffffffffffffff8111156133225761332161312c565b5b61332e85828601613292565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061336382613338565b9050919050565b61337381613358565b811461337e57600080fd5b50565b6000813590506133908161336a565b92915050565b60008115159050919050565b6133ab81613396565b81146133b657600080fd5b50565b6000813590506133c8816133a2565b92915050565b600080604083850312156133e5576133e4613127565b5b60006133f385828601613381565b9250506020613404858286016133b9565b9150509250929050565b60006020828403121561342457613423613127565b5b600061343284828501613214565b91505092915050565b613444816131f3565b82525050565b600060208201905061345f600083018461343b565b92915050565b61346e81613396565b82525050565b60006020820190506134896000830184613465565b92915050565b600067ffffffffffffffff8211156134aa576134a9613147565b5b602082029050602081019050919050565b60006134ce6134c98461348f565b6131a7565b905080838252602082019050602084028301858111156134f1576134f06131ee565b5b835b8181101561351a57806135068882613381565b8452602084019350506020810190506134f3565b5050509392505050565b600082601f83011261353957613538613131565b5b81356135498482602086016134bb565b91505092915050565b6000806040838503121561356957613568613127565b5b600083013567ffffffffffffffff8111156135875761358661312c565b5b61359385828601613292565b925050602083013567ffffffffffffffff8111156135b4576135b361312c565b5b6135c085828601613524565b9150509250929050565b6000602082840312156135e0576135df613127565b5b600082013567ffffffffffffffff8111156135fe576135fd61312c565b5b61360a84828501613292565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561364d578082015181840152602081019050613632565b60008484015250505050565b600061366482613613565b61366e818561361e565b935061367e81856020860161362f565b61368781613136565b840191505092915050565b600060208201905081810360008301526136ac8184613659565b905092915050565b600067ffffffffffffffff8211156136cf576136ce613147565b5b602082029050602081019050919050565b60006136f36136ee846136b4565b6131a7565b90508083825260208201905060208402830185811115613716576137156131ee565b5b835b8181101561373f578061372b88826133b9565b845260208401935050602081019050613718565b5050509392505050565b600082601f83011261375e5761375d613131565b5b813561376e8482602086016136e0565b91505092915050565b6000806040838503121561378e5761378d613127565b5b600083013567ffffffffffffffff8111156137ac576137ab61312c565b5b6137b885828601613292565b925050602083013567ffffffffffffffff8111156137d9576137d861312c565b5b6137e585828601613749565b9150509250929050565b60006020828403121561380557613804613127565b5b600061381384828501613381565b91505092915050565b61382581613358565b82525050565b6000606082019050613840600083018661381c565b61384d602083018561343b565b61385a6040830184613465565b949350505050565b6000806040838503121561387957613878613127565b5b600061388785828601613214565b925050602061389885828601613214565b9150509250929050565b600067ffffffffffffffff8211156138bd576138bc613147565b5b602082029050602081019050919050565b600080fd5b600067ffffffffffffffff8211156138ee576138ed613147565b5b6138f782613136565b9050602081019050919050565b82818337600083830152505050565b6000613926613921846138d3565b6131a7565b905082815260208101848484011115613942576139416138ce565b5b61394d848285613904565b509392505050565b600082601f83011261396a57613969613131565b5b813561397a848260208601613913565b91505092915050565b6000613996613991846138a2565b6131a7565b905080838252602082019050602084028301858111156139b9576139b86131ee565b5b835b81811015613a0057803567ffffffffffffffff8111156139de576139dd613131565b5b8086016139eb8982613955565b855260208501945050506020810190506139bb565b5050509392505050565b600082601f830112613a1f57613a1e613131565b5b8135613a2f848260208601613983565b91505092915050565b60008060408385031215613a4f57613a4e613127565b5b600083013567ffffffffffffffff811115613a6d57613a6c61312c565b5b613a7985828601613292565b925050602083013567ffffffffffffffff811115613a9a57613a9961312c565b5b613aa685828601613a0a565b9150509250929050565b6000602082019050613ac5600083018461381c565b92915050565b600080600060608486031215613ae457613ae3613127565b5b6000613af286828701613214565b9350506020613b0386828701613381565b9250506040613b1486828701613214565b9150509250925092565b600060a0820190508181036000830152613b388188613659565b90508181036020830152613b4c8187613659565b9050613b5b604083018661343b565b613b686060830185613465565b613b75608083018461381c565b9695505050505050565b60008060008060008060008060006101208a8c031215613ba257613ba1613127565b5b60008a013567ffffffffffffffff811115613bc057613bbf61312c565b5b613bcc8c828d01613955565b99505060208a013567ffffffffffffffff811115613bed57613bec61312c565b5b613bf98c828d01613955565b9850506040613c0a8c828d01613381565b9750506060613c1b8c828d01613214565b9650506080613c2c8c828d01613214565b95505060a0613c3d8c828d016133b9565b94505060c0613c4e8c828d01613381565b93505060e0613c5f8c828d01613381565b925050610100613c718c828d01613214565b9150509295985092959850929598565b7f504152414d5f44494d5f4d49534d415443480000000000000000000000000000600082015250565b6000613cb760128361361e565b9150613cc282613c81565b602082019050919050565b60006020820190508181036000830152613ce681613caa565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613d56826131f3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d8857613d87613d1c565b5b600182019050919050565b7f4e756c6c204164647265737320616c6c6f776564000000000000000000000000600082015250565b6000613dc960148361361e565b9150613dd482613d93565b602082019050919050565b60006020820190508181036000830152613df881613dbc565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613e4657607f821691505b602082108103613e5957613e58613dff565b5b50919050565b7f494e56414c49445f4d45524348414e5400000000000000000000000000000000600082015250565b6000613e9560108361361e565b9150613ea082613e5f565b602082019050919050565b60006020820190508181036000830152613ec481613e88565b9050919050565b7f5a45524f5f4150504c595f434f554e5400000000000000000000000000000000600082015250565b6000613f0160108361361e565b9150613f0c82613ecb565b602082019050919050565b60006020820190508181036000830152613f3081613ef4565b9050919050565b7f5052445f4e4f545f4f4e53414c45000000000000000000000000000000000000600082015250565b6000613f6d600e8361361e565b9150613f7882613f37565b602082019050919050565b60006020820190508181036000830152613f9c81613f60565b9050919050565b7f4f55545f4f465f53544f434b0000000000000000000000000000000000000000600082015250565b6000613fd9600c8361361e565b9150613fe482613fa3565b602082019050919050565b6000602082019050818103600083015261400881613fcc565b9050919050565b6000606082019050614024600083018661381c565b614031602083018561343b565b61403e604083018461343b565b949350505050565b600060408201905061405b600083018561381c565b614068602083018461343b565b9392505050565b7f52454d494e5f554e444552464c4f570000000000000000000000000000000000600082015250565b60006140a5600f8361361e565b91506140b08261406f565b602082019050919050565b600060208201905081810360008301526140d481614098565b9050919050565b7f53544f434b5f4f564552464c4f57000000000000000000000000000000000000600082015250565b6000614111600e8361361e565b915061411c826140db565b602082019050919050565b6000602082019050818103600083015261414081614104565b9050919050565b7f554e535550504f52545f43555252454e43590000000000000000000000000000600082015250565b600061417d60128361361e565b915061418882614147565b602082019050919050565b600060208201905081810360008301526141ac81614170565b9050919050565b7f4e4f5f5052445f444546494e4544000000000000000000000000000000000000600082015250565b60006141e9600e8361361e565b91506141f4826141b3565b602082019050919050565b60006020820190508181036000830152614218816141dc565b9050919050565b60008160001c9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061425f61425a8361421f565b61422c565b9050919050565b61426f81613358565b82525050565b6000819050919050565b600061429261428d8361421f565b614275565b9050919050565b6142a2816131f3565b82525050565b600060ff82169050919050565b60006142c86142c38361421f565b6142a8565b9050919050565b6142d881613396565b82525050565b6060820160008083015490506142f38161424c565b6143006000860182614266565b50600183015490506143118161427f565b61431e6020860182614299565b506002830154905061432f816142b5565b61433c60408601826142cf565b5050505050565b600060608201905061435860008301846142de565b92915050565b7f4e4f5f5052445f4e414d45000000000000000000000000000000000000000000600082015250565b6000614394600b8361361e565b915061439f8261435e565b602082019050919050565b600060208201905081810360008301526143c381614387565b9050919050565b7f54504c5f49445f4f564552464c4f570000000000000000000000000000000000600082015250565b6000614400600f8361361e565b915061440b826143ca565b602082019050919050565b6000602082019050818103600083015261442f816143f3565b9050919050565b7f4e4f5f54504c5f444546494e4544000000000000000000000000000000000000600082015250565b600061446c600e8361361e565b915061447782614436565b602082019050919050565b6000602082019050818103600083015261449b8161445f565b9050919050565b7f4e554c4c5f414444524553530000000000000000000000000000000000000000600082015250565b60006144d8600c8361361e565b91506144e3826144a2565b602082019050919050565b60006020820190508181036000830152614507816144cb565b9050919050565b60008151905061451d816133a2565b92915050565b60006020828403121561453957614538613127565b5b60006145478482850161450e565b91505092915050565b7f4e4f5f544f4b454e5f4944000000000000000000000000000000000000000000600082015250565b6000614586600b8361361e565b915061459182614550565b602082019050919050565b600060208201905081810360008301526145b581614579565b9050919050565b7f5a45524f5f4150504c59434f554e540000000000000000000000000000000000600082015250565b60006145f2600f8361361e565b91506145fd826145bc565b602082019050919050565b60006020820190508181036000830152614621816145e5565b9050919050565b7f4e4f5f4d45524348414e545f4144445200000000000000000000000000000000600082015250565b600061465e60108361361e565b915061466982614628565b602082019050919050565b6000602082019050818103600083015261468d81614651565b9050919050565b7f4f505f434f53545f4f564552464c4f5700000000000000000000000000000000600082015250565b60006146ca60108361361e565b91506146d582614694565b602082019050919050565b600060208201905081810360008301526146f9816146bd565b9050919050565b60008151905061470f816131fd565b92915050565b60006020828403121561472b5761472a613127565b5b600061473984828501614700565b91505092915050565b7f554e53554646494349454e545f42414c414e4345000000000000000000000000600082015250565b600061477860148361361e565b915061478382614742565b602082019050919050565b600060208201905081810360008301526147a78161476b565b9050919050565b60006060820190506147c3600083018661381c565b6147d0602083018561381c565b6147dd604083018461343b565b949350505050565b60006147f0826131f3565b91506147fb836131f3565b925082820390508181111561481357614812613d1c565b5b92915050565b7f4e4f5f54504c5f4e414d45000000000000000000000000000000000000000000600082015250565b600061484f600b8361361e565b915061485a82614819565b602082019050919050565b6000602082019050818103600083015261487e81614842565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026148e77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826148aa565b6148f186836148aa565b95508019841693508086168417925050509392505050565b6000819050919050565b600061492e614929614924846131f3565b614909565b6131f3565b9050919050565b6000819050919050565b61494883614913565b61495c61495482614935565b8484546148b7565b825550505050565b600090565b614971614964565b61497c81848461493f565b505050565b5b818110156149a057614995600082614969565b600181019050614982565b5050565b601f8211156149e5576149b681614885565b6149bf8461489a565b810160208510156149ce578190505b6149e26149da8561489a565b830182614981565b50505b505050565b600082821c905092915050565b6000614a08600019846008026149ea565b1980831691505092915050565b6000614a2183836149f7565b9150826002028217905092915050565b614a3a82613613565b67ffffffffffffffff811115614a5357614a52613147565b5b614a5d8254613e2e565b614a688282856149a4565b600060209050601f831160018114614a9b5760008415614a89578287015190505b614a938582614a15565b865550614afb565b601f198416614aa986614885565b60005b82811015614ad157848901518255600182019150602085019450602081019050614aac565b86831015614aee5784890151614aea601f8916826149f7565b8355505b6001600288020188555050505b505050505050565b7f4f5f4241445f544f4b454e000000000000000000000000000000000000000000600082015250565b6000614b39600b8361361e565b9150614b4482614b03565b602082019050919050565b60006020820190508181036000830152614b6881614b2c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614bd381614b9e565b82525050565b6000602082019050614bee6000830184614bca565b9291505056fea26469706673582212200ec00e6808af38ac1c8a0166558ac6cb7627e85aec9c07a62d59fbcee6a9c2c764736f6c63430008140033