Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- NFTMarketplace
- Optimization enabled
- true
- Compiler version
- v0.8.10+commit.fc410830
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2025-05-31T18:21:20.241373Z
Constructor Arguments
0x000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca700000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019
Arg [0] (address) : 0xad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca7
Arg [1] (uint256) : 25
Arg [2] (uint256) : 25
Contract source code
// File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.10; /** * @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; } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.10; /** * @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); } } // File: @openzeppelin/contracts/security/ReentrancyGuard.sol // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.10; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ 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); } // File: @openzeppelin/contracts/utils/introspection/IERC165.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.10; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * 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[ERC 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); } // File: @openzeppelin/contracts/token/ERC1155/IERC1155.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.10; /** * @dev Required interface of an ERC-1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[ERC]. */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the value of tokens of token type `id` owned by `account`. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] calldata accounts, uint256[] calldata ids ) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the zero address. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155Received} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `value` amount. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments. * * Requirements: * * - `ids` and `values` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external; } // File: @openzeppelin/contracts/utils/introspection/ERC165.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.10; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // File: @openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.10; /** * @dev Interface that must be implemented by smart contracts in order to receive * ERC-1155 token transfers. */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC-1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC-1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); } // File: @openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol) pragma solidity ^0.8.10; /** * @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens. * * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be * stuck. */ abstract contract ERC1155Holder is ERC165, IERC1155Receiver { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); } function onERC1155Received( address, address, uint256, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] memory, uint256[] memory, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155BatchReceived.selector; } } // File: @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol // OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.10; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reinitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location. * * NOTE: Consider following the ERC-7201 formula to derive storage locations. */ function _initializableStorageSlot() internal pure virtual returns (bytes32) { return INITIALIZABLE_STORAGE; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { bytes32 slot = _initializableStorageSlot(); assembly { $.slot := slot } } } // File: @openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.10; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } 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; } } // File: @openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.10; /** * @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 OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @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. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { 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) { OwnableStorage storage $ = _getOwnableStorage(); 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 { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } interface ICollection { struct NFTDetails { string name; string description; string uri; uint256 maxSupply; address creator; } event NFTCreated(string name, string description,uint256 indexed tokenId, address indexed creator, uint256 maxSupply); function initialize( string memory name, string memory symbol, address owner, address marketplace, bool isDrop ) external; function createNFT( string memory name, string memory description, string memory _tokenURI, uint256 maxSupply ) external returns (uint256); function nftDetails(uint256 tokenId) external view returns (NFTDetails memory); function getRoyaltyPercentage() external view returns(uint16); } // File: contracts/marketplace/NFTMarketplace.sol contract NFTMarketplace is OwnableUpgradeable , ReentrancyGuard, ERC1155Holder { enum ListingType { FIXED_PRICE, AUCTION } enum AuctionStatus { ACTIVE, ENDED, CANCELLED } enum OfferStatus { PENDING, ACCEPTED, REJECTED, CANCELLED } struct Listing { address seller; uint256 price; uint256 quantity; ListingType listingType; uint256 auctionId; // 0 for fixed price listings } struct AuctionDetails { address seller; uint256 startPrice; uint256 currentPrice; uint256 minBidIncrement; uint256 startTime; uint256 endTime; uint256 tokenId; uint256 quantity; address highestBidder; AuctionStatus status; } struct Offer { address buyer; address seller; uint256 price; uint256 quantity; uint256 createTime; OfferStatus status; } struct FilterParams { address collection; uint256 tokenId; address user; uint8 filterType; } struct BatchPurchaseParams { address collection; uint256 tokenId; address seller; uint256 quantity; } uint256 public primaryFee; uint256 public secondaryFee; address public collectionFactory; uint256 public totalCollections; IERC20 public immutable designatedToken; uint256 private _auctionIds; uint256 private _offerIds; uint256 public minAuctionDuration; uint256 public maxAuctionDuration; uint256 public auctionExtensionInterval; mapping(address => mapping(uint256 => mapping(address => Listing))) public listings; mapping(address => bool) public registeredCollections; mapping(uint256 => address) private collectionIndex; mapping(uint256 => AuctionDetails) public auctions; mapping(uint256 => mapping(address => uint256)) public bids; mapping(uint256 => address) public auctionCollections; // Offer mappings mapping(address => mapping(uint256 => mapping(uint256 => Offer))) public offers; // collection => tokenId => offerId => Offer mapping(address => uint256[]) private userOfferIds; // buyer => offerIds mapping(uint256 => address) private offerCollections; // offerId => collection mapping(uint256 => uint256) private offerTokenIds; // offerId => tokenId mapping(address => uint256[]) private sellerReceivedOffers; // seller => offerIds mapping(address => mapping(uint256 => uint256[])) private tokenOffers; // collection => tokenId => offerIds event NFTListed( address indexed collection, uint256 indexed tokenId, address seller, uint256 price, uint256 quantity, ListingType listingType, uint256 auctionId ); event NFTSold(address indexed collection, uint256 indexed tokenId, address seller, address buyer, uint256 price, uint256 quantity); event ListingRemoved(address indexed collection, uint256 indexed tokenId, address seller, string reason); event ListingQuantityUpdated( address indexed collection, uint256 indexed tokenId, address seller, uint256 newQuantity ); event AuctionCreated( uint256 indexed auctionId, address indexed collection, uint256 indexed tokenId, address seller, uint256 startPrice, uint256 minBidIncrement, uint256 startTime, uint256 endTime, uint256 quantity ); event BidPlaced( uint256 indexed auctionId, address indexed bidder, uint256 amount ); event AuctionSettled( uint256 indexed auctionId, address indexed winner, uint256 amount ); event AuctionCancelled(uint256 indexed auctionId); event AuctionExtended(uint256 indexed auctionId, uint256 newEndTime); event FeeUpdated(bool isPrimary, uint256 newFee); event CollectionRegistered(address indexed collection); event AuctionExtensionIntervalUpdated(uint256 newInterval); event OfferCreated( uint256 indexed offerId, address indexed collection, uint256 indexed tokenId, address buyer, address seller, uint256 price, uint256 quantity ); event OfferAccepted(uint256 indexed offerId, address indexed seller); event OfferRejected(uint256 indexed offerId, address indexed seller); event OfferCancelled(uint256 indexed offerId, address indexed buyer); constructor( address _designatedToken, uint256 _primaryFee, uint256 _secondaryFee ) { require(_designatedToken != address(0), "Invalid token address"); require(_primaryFee <= 1000, "Primary fee too high"); require(_secondaryFee <= 1000, "Secondary fee too high"); designatedToken = IERC20(_designatedToken); primaryFee = _primaryFee; secondaryFee = _secondaryFee; minAuctionDuration = 1 hours; maxAuctionDuration = 30 days; auctionExtensionInterval = 10 minutes; } function setCollectionFactory(address _factory) external onlyOwner { require(_factory != address(0), "Invalid factory address"); collectionFactory = _factory; } function registerCollection(address collection) external { require(msg.sender == collectionFactory, "Only factory can register"); require(collection != address(0), "Invalid collection address"); require(!registeredCollections[collection], "Already registered"); registeredCollections[collection] = true; collectionIndex[totalCollections] = collection; totalCollections++; emit CollectionRegistered(collection); } function setPrimaryFee(uint256 _fee) external onlyOwner { require(_fee <= 1000, "Fee too high"); primaryFee = _fee; emit FeeUpdated(true, _fee); } function setSecondaryFee(uint256 _fee) external onlyOwner { require(_fee <= 1000, "Fee too high"); secondaryFee = _fee; emit FeeUpdated(false, _fee); } function listNFT( address collection, uint256 tokenId, uint256 price, uint256 quantity ) external nonReentrant { require(registeredCollections[collection], "Collection not registered"); require(price > 0, "Invalid price"); require(quantity > 0, "Invalid quantity"); require( IERC1155(collection).balanceOf(msg.sender, tokenId) >= quantity, "Insufficient balance" ); // Check if NFT is already listed by this seller Listing storage existingListing = listings[collection][tokenId][msg.sender]; require( existingListing.quantity == 0 || (existingListing.listingType == ListingType.AUCTION && auctions[existingListing.auctionId].status != AuctionStatus.ACTIVE), "Already listed" ); listings[collection][tokenId][msg.sender] = Listing({ seller: msg.sender, price: price, quantity: quantity, listingType: ListingType.FIXED_PRICE, auctionId: 0 }); emit NFTListed( collection, tokenId, msg.sender, price, quantity, ListingType.FIXED_PRICE, 0 ); } function removeListing( address collection, uint256 tokenId ) external nonReentrant { Listing storage listing = listings[collection][tokenId][msg.sender]; require(listing.seller == msg.sender && listing.quantity > 0, "No active listing"); if (listing.listingType == ListingType.AUCTION) { AuctionDetails storage auction = auctions[listing.auctionId]; require(auction.status == AuctionStatus.ACTIVE, "Auction not active"); require(auction.highestBidder == address(0), "Bids already placed"); auction.status = AuctionStatus.CANCELLED; IERC1155(collection).safeTransferFrom( address(this), msg.sender, tokenId, listing.quantity, "" ); emit AuctionCancelled(listing.auctionId); } delete listings[collection][tokenId][msg.sender]; emit ListingRemoved(collection, tokenId, msg.sender, "REMOVED_BY_SELLER"); } function buyListedNFT( address collection, uint256 tokenId, address seller, uint256 quantity ) external nonReentrant { require(registeredCollections[collection], "Collection not registered"); Listing storage listing = listings[collection][tokenId][seller]; require(listing.seller == seller && listing.quantity > 0, "Invalid listing"); require(listing.listingType == ListingType.FIXED_PRICE, "Not a fixed price listing"); require(listing.quantity >= quantity, "Insufficient quantity"); ICollection.NFTDetails memory nftDetails = ICollection(collection).nftDetails(tokenId); uint256 fee = secondaryFee; if(nftDetails.creator == seller) { fee = primaryFee; } uint16 royaltyPercentage = ICollection(collection).getRoyaltyPercentage(); uint256 totalPrice = listing.price * quantity; uint256 platformFee = (totalPrice * fee) / 1000; uint256 royaltyFee = (totalPrice * royaltyPercentage) / 1000; uint256 sellerAmount = totalPrice - platformFee - royaltyFee; designatedToken.transferFrom(msg.sender, address(this), platformFee); designatedToken.transferFrom(msg.sender, seller, sellerAmount); if(royaltyFee > 0) { designatedToken.transferFrom(msg.sender, nftDetails.creator, royaltyFee); } IERC1155(collection).safeTransferFrom(seller, msg.sender, tokenId, quantity, ""); listing.quantity -= quantity; if (listing.quantity == 0) { delete listings[collection][tokenId][seller]; emit ListingRemoved(collection, tokenId, seller, "SOLD_OUT"); } emit NFTSold(collection, tokenId, seller, msg.sender, listing.price, quantity); } function getRegisteredCollections(uint256 offset, uint256 limit) public view returns (address[] memory collections) { require(offset <= totalCollections, "Invalid offset"); uint256 size = totalCollections - offset; if (size > limit) { size = limit; } collections = new address[](size); for (uint256 i = 0; i < size; i++) { collections[i] = collectionIndex[offset + i]; } return collections; } function getCollectionsByOwner(address _owner, uint256 offset, uint256 limit) external view returns (address[] memory _collections, uint256 total) { uint256 count = 0; for (uint256 i = 0; i < totalCollections; i++) { address collection = collectionIndex[i]; if (OwnableUpgradeable(collection).owner() == _owner) { count++; } } require(offset <= count, "Invalid offset"); uint256 size = count - offset; if (size > limit) { size = limit; } _collections = new address[](size); uint256 currentIndex = 0; uint256 skipped = 0; for (uint256 i = 0; i < totalCollections && currentIndex < size; i++) { address collection = collectionIndex[i]; if (OwnableUpgradeable(collection).owner() == _owner) { if (skipped < offset) { skipped++; continue; } _collections[currentIndex] = collection; currentIndex++; } } return (_collections, count); } function withdrawFees() external onlyOwner { uint256 balance = designatedToken.balanceOf(address(this)); if (balance > 0) { designatedToken.transfer(owner(), balance); } } function getListing( address collection, uint256 tokenId, address seller ) external view returns (Listing memory) { return listings[collection][tokenId][seller]; } function createAuction( address collection, uint256 tokenId, uint256 quantity, uint256 startPrice, uint256 minBidIncrement, uint256 duration ) external nonReentrant returns (uint256) { _validateAuctionParams( collection, tokenId, quantity, startPrice, minBidIncrement, duration ); _auctionIds++; uint256 auctionId = _auctionIds; _createAuctionListing( collection, tokenId, quantity, startPrice, auctionId ); _setupAuction( auctionId, collection, tokenId, quantity, startPrice, minBidIncrement, duration ); return auctionId; } function _validateAuctionParams( address collection, uint256 tokenId, uint256 quantity, uint256 startPrice, uint256 minBidIncrement, uint256 duration ) internal view { require(registeredCollections[collection], "Collection not registered"); require(quantity > 0, "Invalid quantity"); require(startPrice > 0, "Invalid start price"); require(minBidIncrement > 0, "Invalid min bid increment"); require(duration >= minAuctionDuration && duration <= maxAuctionDuration, "Invalid duration"); require( IERC1155(collection).balanceOf(msg.sender, tokenId) >= quantity, "Insufficient balance" ); require( IERC1155(collection).isApprovedForAll(msg.sender, address(this)), "Not approved" ); Listing storage existingListing = listings[collection][tokenId][msg.sender]; require( existingListing.quantity == 0 || (existingListing.listingType == ListingType.AUCTION && auctions[existingListing.auctionId].status != AuctionStatus.ACTIVE), "Already listed" ); } function _createAuctionListing( address collection, uint256 tokenId, uint256 quantity, uint256 startPrice, uint256 auctionId ) internal { listings[collection][tokenId][msg.sender] = Listing({ seller: msg.sender, price: startPrice, quantity: quantity, listingType: ListingType.AUCTION, auctionId: auctionId }); emit NFTListed( collection, tokenId, msg.sender, startPrice, quantity, ListingType.AUCTION, auctionId ); } function _setupAuction( uint256 auctionId, address collection, uint256 tokenId, uint256 quantity, uint256 startPrice, uint256 minBidIncrement, uint256 duration ) internal { uint256 startTime = block.timestamp; uint256 endTime = startTime + duration; auctions[auctionId] = AuctionDetails({ seller: msg.sender, startPrice: startPrice, currentPrice: startPrice, minBidIncrement: minBidIncrement, startTime: startTime, endTime: endTime, tokenId: tokenId, quantity: quantity, highestBidder: address(0), status: AuctionStatus.ACTIVE }); auctionCollections[auctionId] = collection; IERC1155(collection).safeTransferFrom( msg.sender, address(this), tokenId, quantity, "" ); emit AuctionCreated( auctionId, collection, tokenId, msg.sender, startPrice, minBidIncrement, startTime, endTime, quantity ); } function placeBid(uint256 auctionId, uint256 bidAmount) external nonReentrant { AuctionDetails storage auction = auctions[auctionId]; require(auction.status == AuctionStatus.ACTIVE, "Auction not active"); require(block.timestamp <= auction.endTime, "Auction ended"); require(bidAmount >= auction.currentPrice + auction.minBidIncrement, "Bid too low"); // Check if bid is placed near the end if (auction.endTime - block.timestamp <= auctionExtensionInterval) { auction.endTime = block.timestamp + auctionExtensionInterval; emit AuctionExtended(auctionId, auction.endTime); } address previousBidder = auction.highestBidder; uint256 previousBid = bids[auctionId][previousBidder]; if (previousBidder != address(0)) { designatedToken.transfer(previousBidder, previousBid); } require( designatedToken.transferFrom(msg.sender, address(this), bidAmount), "Transfer failed" ); auction.highestBidder = msg.sender; auction.currentPrice = bidAmount; bids[auctionId][msg.sender] = bidAmount; emit BidPlaced(auctionId, msg.sender, bidAmount); } function settleAuction(uint256 auctionId) external nonReentrant { AuctionDetails storage auction = auctions[auctionId]; require(auction.status == AuctionStatus.ACTIVE, "Auction not active"); require(block.timestamp > auction.endTime, "Auction not ended"); require(auction.highestBidder != address(0), "No bids placed"); auction.status = AuctionStatus.ENDED; address collection = auctionCollections[auctionId]; uint256 finalPrice = auction.currentPrice; ICollection.NFTDetails memory nftDetails = ICollection(collection).nftDetails(auction.tokenId); uint256 fee = secondaryFee; if(nftDetails.creator == auction.seller) { fee = primaryFee; } uint16 royaltyPercentage = ICollection(collection).getRoyaltyPercentage(); // Calculate fees uint256 platformFee = (finalPrice * fee) / 1000; uint256 royaltyFee = (finalPrice * royaltyPercentage) / 1000; uint256 sellerAmount = finalPrice - platformFee - royaltyFee; // Distribute funds designatedToken.transfer(auction.seller, sellerAmount); if(royaltyFee>0) { designatedToken.transfer(nftDetails.creator, royaltyFee); } // Transfer NFT IERC1155(collection).safeTransferFrom( address(this), auction.highestBidder, auction.tokenId, auction.quantity, "" ); // Remove listing address seller = auction.seller; delete listings[collection][auction.tokenId][seller]; emit ListingRemoved(collection, auction.tokenId, seller, "AUCTION_SETTLED"); emit AuctionSettled(auctionId, auction.highestBidder, finalPrice); } function cancelAuction(uint256 auctionId) external nonReentrant { AuctionDetails storage auction = auctions[auctionId]; require(auction.status == AuctionStatus.ACTIVE, "Auction not active"); require(msg.sender == auction.seller, "Not seller"); require(auction.highestBidder == address(0), "Bids already placed"); auction.status = AuctionStatus.CANCELLED; address collection = auctionCollections[auctionId]; IERC1155(collection).safeTransferFrom( address(this), auction.seller, auction.tokenId, auction.quantity, "" ); // Remove listing delete listings[collection][auction.tokenId][auction.seller]; emit ListingRemoved(collection, auction.tokenId, auction.seller, "AUCTION_CANCELLED"); emit AuctionCancelled(auctionId); } function setAuctionExtensionInterval(uint256 _interval) external onlyOwner { require(_interval > 0, "Invalid interval"); auctionExtensionInterval = _interval; emit AuctionExtensionIntervalUpdated(_interval); } function makeOffer( address collection, uint256 tokenId, address seller, uint256 quantity, uint256 price ) external nonReentrant { require(registeredCollections[collection], "Collection not registered"); require(quantity > 0, "Invalid quantity"); require(price > 0, "Invalid price"); require(seller != address(0), "Invalid seller"); require(seller != msg.sender, "Cannot make offer to self"); uint256 sellerBalance = IERC1155(collection).balanceOf(seller, tokenId); require(sellerBalance >= quantity, "Insufficient seller balance"); _offerIds++; uint256 offerId = _offerIds; offers[collection][tokenId][offerId] = Offer({ buyer: msg.sender, seller: seller, price: price, quantity: quantity, createTime: block.timestamp, status: OfferStatus.PENDING }); userOfferIds[msg.sender].push(offerId); sellerReceivedOffers[seller].push(offerId); tokenOffers[collection][tokenId].push(offerId); offerCollections[offerId] = collection; offerTokenIds[offerId] = tokenId; // Pre-approve marketplace for token transfer designatedToken.transferFrom(msg.sender, address(this), price * quantity); emit OfferCreated(offerId, collection, tokenId, msg.sender, seller, price, quantity); } function acceptOffer(uint256 offerId) external nonReentrant { (address collection, uint256 tokenId, Offer storage offer) = _validateAndGetOffer(offerId); uint256 totalBalance = _validateSellerBalance(collection, tokenId, offer); _validateAndUpdateListing(collection, tokenId, offer.quantity, totalBalance); _processOfferAcceptance(collection, tokenId, offer, offerId); } function _validateAndGetOffer(uint256 offerId) private view returns ( address collection, uint256 tokenId, Offer storage offer ) { collection = offerCollections[offerId]; require(collection != address(0), "Offer does not exist"); tokenId = offerTokenIds[offerId]; offer = offers[collection][tokenId][offerId]; require(offer.status == OfferStatus.PENDING, "Invalid offer status"); require(msg.sender == offer.seller, "Not offer recipient"); return (collection, tokenId, offer); } function _validateSellerBalance( address collection, uint256 tokenId, Offer memory offer ) private view returns (uint256) { uint256 totalBalance = IERC1155(collection).balanceOf(msg.sender, tokenId); require(totalBalance >= offer.quantity, "Insufficient balance"); return totalBalance; } function _validateAndUpdateListing( address collection, uint256 tokenId, uint256 offerQuantity, uint256 totalBalance ) private { Listing storage listing = listings[collection][tokenId][msg.sender]; // Check if NFT is not in active auction if(listing.listingType == ListingType.AUCTION) { require( auctions[listing.auctionId].status != AuctionStatus.ACTIVE, "Active auction exists" ); } // Calculate available quantities uint256 listedQuantity = listing.quantity; uint256 unlistedQuantity = totalBalance - listedQuantity; // Calculate how many NFTs to take from unlisted and listed uint256 takeFromUnlisted = unlistedQuantity >= offerQuantity ? offerQuantity : unlistedQuantity; uint256 takeFromListed = offerQuantity - takeFromUnlisted; // Update listing if needed if(takeFromListed > 0) { if(takeFromListed == listedQuantity) { delete listings[collection][tokenId][msg.sender]; emit ListingRemoved(collection, tokenId, msg.sender, "ZERO_QUANTITY"); } else { listing.quantity = listedQuantity - takeFromListed; emit ListingQuantityUpdated( collection, tokenId, msg.sender, listing.quantity ); } } } function _processOfferAcceptance( address collection, uint256 tokenId, Offer storage offer, uint256 offerId ) private { require( IERC1155(collection).isApprovedForAll(msg.sender, address(this)), "Not approved" ); ICollection.NFTDetails memory nftDetails = ICollection(collection).nftDetails(tokenId); uint256 fee = secondaryFee; if(nftDetails.creator == msg.sender) { fee = primaryFee; } uint16 royaltyPercentage = ICollection(collection).getRoyaltyPercentage(); // Calculate fees uint256 totalPrice = offer.price * offer.quantity; uint256 platformFee = (totalPrice * fee) / 1000; uint256 royaltyFee = (totalPrice * royaltyPercentage) / 1000; uint256 sellerAmount = totalPrice - platformFee - royaltyFee; // Transfer NFT IERC1155(collection).safeTransferFrom( msg.sender, offer.buyer, tokenId, offer.quantity, "" ); // Distribute payments designatedToken.transfer(msg.sender, sellerAmount); if(royaltyFee>0) { designatedToken.transfer(nftDetails.creator, royaltyFee); } offer.status = OfferStatus.ACCEPTED; emit OfferAccepted(offerId, msg.sender); } function rejectOffer(uint256 offerId) external nonReentrant { address collection = offerCollections[offerId]; uint256 tokenId = offerTokenIds[offerId]; require(collection != address(0), "Offer does not exist"); Offer storage offer = offers[collection][tokenId][offerId]; require(offer.status == OfferStatus.PENDING, "Invalid offer status"); require( IERC1155(collection).balanceOf(msg.sender, tokenId) > 0, "Not token owner" ); offer.status = OfferStatus.REJECTED; // Refund buyer designatedToken.transfer(offer.buyer, offer.price * offer.quantity); emit OfferRejected(offerId, msg.sender); } function cancelOffer(uint256 offerId) external nonReentrant { address collection = offerCollections[offerId]; uint256 tokenId = offerTokenIds[offerId]; require(collection != address(0), "Offer does not exist"); Offer storage offer = offers[collection][tokenId][offerId]; require(offer.buyer == msg.sender, "Not offer creator"); require(offer.status == OfferStatus.PENDING, "Invalid offer status"); offer.status = OfferStatus.CANCELLED; // Refund buyer designatedToken.transfer(msg.sender, offer.price * offer.quantity); emit OfferCancelled(offerId, msg.sender); } function getOffersByToken( address collection, uint256 tokenId, uint256 offset, uint256 limit ) external view returns (uint256[] memory offerIdList, uint256 total) { return _getOffersWithFilter( collection, tokenId, address(0), // no user filter offset, limit, 0 // filter type: BY_TOKEN ); } function getOffersToSeller( address seller, uint256 offset, uint256 limit ) external view returns (uint256[] memory offerIdList, uint256 total) { return _getOffersWithFilter( address(0), // no collection filter 0, // no tokenId filter seller, offset, limit, 1 // filter type: BY_SELLER ); } function getOffersByBuyer( address buyer, uint256 offset, uint256 limit ) external view returns (uint256[] memory offerIdList, uint256 total) { return _getOffersWithFilter( address(0), // no collection filter 0, // no tokenId filter buyer, offset, limit, 2 // filter type: BY_BUYER ); } function _getOffersWithFilter( address collection, uint256 tokenId, address user, uint256 offset, uint256 limit, uint8 filterType ) private view returns (uint256[] memory offerIdList, uint256 total) { FilterParams memory params = FilterParams(collection, tokenId, user, filterType); uint256[] storage sourceOffers = _getSourceOffers(user, filterType, params); // Get total count first uint256 count = _countValidOffers(sourceOffers, params); if(count == 0 || offset >= count) { return (new uint256[](0), count); } return _getFilteredOffers(sourceOffers, params, offset, limit, count); } function _getSourceOffers(address user, uint8 filterType, FilterParams memory params) private view returns (uint256[] storage) { if (filterType == 0) { // BY_TOKEN return tokenOffers[params.collection][params.tokenId]; } else if (filterType == 1) { // BY_SELLER return sellerReceivedOffers[user]; } else { // BY_BUYER return userOfferIds[user]; } } function _countValidOffers( uint256[] storage sourceOffers, FilterParams memory params ) private view returns (uint256) { uint256 count; for(uint256 i = 0; i < sourceOffers.length; i++) { if(_isValidOffer(sourceOffers[i], params)) { count++; } } return count; } function _getFilteredOffers( uint256[] storage sourceOffers, FilterParams memory params, uint256 offset, uint256 limit, uint256 count ) private view returns (uint256[] memory offerIdList, uint256) { uint256 size = count - offset; if(size > limit) { size = limit; } offerIdList = new uint256[](size); uint256 currentIndex; uint256 skipped; for(uint256 i = 0; i < sourceOffers.length && currentIndex < size; i++) { uint256 offerId = sourceOffers[i]; if(_isValidOffer(offerId, params)) { if(skipped < offset) { skipped++; continue; } offerIdList[currentIndex++] = offerId; } } return (offerIdList, count); } function _isValidOffer( uint256 offerId, FilterParams memory params ) private view returns (bool) { address offerCollection = offerCollections[offerId]; uint256 offerTokenId = offerTokenIds[offerId]; Offer storage offer = offers[offerCollection][offerTokenId][offerId]; if (params.filterType == 0) { // BY_TOKEN return offerCollection == params.collection && offerTokenId == params.tokenId && offer.status == OfferStatus.PENDING; } else if (params.filterType == 1) { // BY_SELLER return offer.seller == params.user && offer.status == OfferStatus.PENDING; } else { // BY_BUYER return offer.buyer == params.user && offer.status == OfferStatus.PENDING; } } function getOffer(uint256 offerId) external view returns ( address collection, uint256 tokenId, Offer memory offer ) { collection = offerCollections[offerId]; require(collection != address(0), "Offer does not exist"); tokenId = offerTokenIds[offerId]; offer = offers[collection][tokenId][offerId]; return (collection, tokenId, offer); } function batchBuyListedNFTs(BatchPurchaseParams[] calldata params) external nonReentrant { require(params.length > 0, "Empty batch"); for(uint256 i = 0; i < params.length; i++) { BatchPurchaseParams calldata purchase = params[i]; require(registeredCollections[purchase.collection], "Collection not registered"); Listing storage listing = listings[purchase.collection][purchase.tokenId][purchase.seller]; require(listing.seller == purchase.seller && listing.quantity > 0, "Invalid listing"); require(listing.listingType == ListingType.FIXED_PRICE, "Not a fixed price listing"); require(listing.quantity >= purchase.quantity, "Insufficient quantity"); ICollection.NFTDetails memory nftDetails = ICollection(purchase.collection).nftDetails(purchase.tokenId); uint256 fee = secondaryFee; if(nftDetails.creator == purchase.seller) { fee = primaryFee; } uint16 royaltyPercentage = ICollection(purchase.collection).getRoyaltyPercentage(); uint256 totalPrice = listing.price * purchase.quantity; uint256 platformFee = (totalPrice * fee) / 1000; uint256 royaltyFee = (totalPrice * royaltyPercentage) / 1000; uint256 sellerAmount = totalPrice - platformFee - royaltyFee; designatedToken.transferFrom(msg.sender, address(this), platformFee); designatedToken.transferFrom(msg.sender, purchase.seller, sellerAmount); if(royaltyFee>0) { designatedToken.transferFrom(msg.sender, nftDetails.creator, royaltyFee); } IERC1155(purchase.collection).safeTransferFrom( purchase.seller, msg.sender, purchase.tokenId, purchase.quantity, "" ); listing.quantity -= purchase.quantity; if (listing.quantity == 0) { delete listings[purchase.collection][purchase.tokenId][purchase.seller]; emit ListingRemoved(purchase.collection, purchase.tokenId, purchase.seller, "SOLD_OUT"); } emit NFTSold( purchase.collection, purchase.tokenId, purchase.seller, msg.sender, listing.price, purchase.quantity ); } } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_designatedToken","internalType":"address"},{"type":"uint256","name":"_primaryFee","internalType":"uint256"},{"type":"uint256","name":"_secondaryFee","internalType":"uint256"}]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"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":"AuctionCancelled","inputs":[{"type":"uint256","name":"auctionId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"AuctionCreated","inputs":[{"type":"uint256","name":"auctionId","internalType":"uint256","indexed":true},{"type":"address","name":"collection","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"seller","internalType":"address","indexed":false},{"type":"uint256","name":"startPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"minBidIncrement","internalType":"uint256","indexed":false},{"type":"uint256","name":"startTime","internalType":"uint256","indexed":false},{"type":"uint256","name":"endTime","internalType":"uint256","indexed":false},{"type":"uint256","name":"quantity","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"AuctionExtended","inputs":[{"type":"uint256","name":"auctionId","internalType":"uint256","indexed":true},{"type":"uint256","name":"newEndTime","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"AuctionExtensionIntervalUpdated","inputs":[{"type":"uint256","name":"newInterval","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"AuctionSettled","inputs":[{"type":"uint256","name":"auctionId","internalType":"uint256","indexed":true},{"type":"address","name":"winner","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"BidPlaced","inputs":[{"type":"uint256","name":"auctionId","internalType":"uint256","indexed":true},{"type":"address","name":"bidder","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CollectionRegistered","inputs":[{"type":"address","name":"collection","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"FeeUpdated","inputs":[{"type":"bool","name":"isPrimary","internalType":"bool","indexed":false},{"type":"uint256","name":"newFee","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"type":"uint64","name":"version","internalType":"uint64","indexed":false}],"anonymous":false},{"type":"event","name":"ListingQuantityUpdated","inputs":[{"type":"address","name":"collection","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"seller","internalType":"address","indexed":false},{"type":"uint256","name":"newQuantity","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ListingRemoved","inputs":[{"type":"address","name":"collection","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"seller","internalType":"address","indexed":false},{"type":"string","name":"reason","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"NFTListed","inputs":[{"type":"address","name":"collection","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"seller","internalType":"address","indexed":false},{"type":"uint256","name":"price","internalType":"uint256","indexed":false},{"type":"uint256","name":"quantity","internalType":"uint256","indexed":false},{"type":"uint8","name":"listingType","internalType":"enum NFTMarketplace.ListingType","indexed":false},{"type":"uint256","name":"auctionId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NFTSold","inputs":[{"type":"address","name":"collection","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"seller","internalType":"address","indexed":false},{"type":"address","name":"buyer","internalType":"address","indexed":false},{"type":"uint256","name":"price","internalType":"uint256","indexed":false},{"type":"uint256","name":"quantity","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OfferAccepted","inputs":[{"type":"uint256","name":"offerId","internalType":"uint256","indexed":true},{"type":"address","name":"seller","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OfferCancelled","inputs":[{"type":"uint256","name":"offerId","internalType":"uint256","indexed":true},{"type":"address","name":"buyer","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OfferCreated","inputs":[{"type":"uint256","name":"offerId","internalType":"uint256","indexed":true},{"type":"address","name":"collection","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"buyer","internalType":"address","indexed":false},{"type":"address","name":"seller","internalType":"address","indexed":false},{"type":"uint256","name":"price","internalType":"uint256","indexed":false},{"type":"uint256","name":"quantity","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OfferRejected","inputs":[{"type":"uint256","name":"offerId","internalType":"uint256","indexed":true},{"type":"address","name":"seller","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":"acceptOffer","inputs":[{"type":"uint256","name":"offerId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"auctionCollections","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"auctionExtensionInterval","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"startPrice","internalType":"uint256"},{"type":"uint256","name":"currentPrice","internalType":"uint256"},{"type":"uint256","name":"minBidIncrement","internalType":"uint256"},{"type":"uint256","name":"startTime","internalType":"uint256"},{"type":"uint256","name":"endTime","internalType":"uint256"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"quantity","internalType":"uint256"},{"type":"address","name":"highestBidder","internalType":"address"},{"type":"uint8","name":"status","internalType":"enum NFTMarketplace.AuctionStatus"}],"name":"auctions","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"batchBuyListedNFTs","inputs":[{"type":"tuple[]","name":"params","internalType":"struct NFTMarketplace.BatchPurchaseParams[]","components":[{"type":"address","name":"collection","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"quantity","internalType":"uint256"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"bids","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"buyListedNFT","inputs":[{"type":"address","name":"collection","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"quantity","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelAuction","inputs":[{"type":"uint256","name":"auctionId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelOffer","inputs":[{"type":"uint256","name":"offerId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"collectionFactory","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"createAuction","inputs":[{"type":"address","name":"collection","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"quantity","internalType":"uint256"},{"type":"uint256","name":"startPrice","internalType":"uint256"},{"type":"uint256","name":"minBidIncrement","internalType":"uint256"},{"type":"uint256","name":"duration","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"designatedToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"_collections","internalType":"address[]"},{"type":"uint256","name":"total","internalType":"uint256"}],"name":"getCollectionsByOwner","inputs":[{"type":"address","name":"_owner","internalType":"address"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"limit","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct NFTMarketplace.Listing","components":[{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"quantity","internalType":"uint256"},{"type":"uint8","name":"listingType","internalType":"enum NFTMarketplace.ListingType"},{"type":"uint256","name":"auctionId","internalType":"uint256"}]}],"name":"getListing","inputs":[{"type":"address","name":"collection","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"seller","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"collection","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"tuple","name":"offer","internalType":"struct NFTMarketplace.Offer","components":[{"type":"address","name":"buyer","internalType":"address"},{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"quantity","internalType":"uint256"},{"type":"uint256","name":"createTime","internalType":"uint256"},{"type":"uint8","name":"status","internalType":"enum NFTMarketplace.OfferStatus"}]}],"name":"getOffer","inputs":[{"type":"uint256","name":"offerId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"offerIdList","internalType":"uint256[]"},{"type":"uint256","name":"total","internalType":"uint256"}],"name":"getOffersByBuyer","inputs":[{"type":"address","name":"buyer","internalType":"address"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"limit","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"offerIdList","internalType":"uint256[]"},{"type":"uint256","name":"total","internalType":"uint256"}],"name":"getOffersByToken","inputs":[{"type":"address","name":"collection","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"limit","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"offerIdList","internalType":"uint256[]"},{"type":"uint256","name":"total","internalType":"uint256"}],"name":"getOffersToSeller","inputs":[{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"limit","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"collections","internalType":"address[]"}],"name":"getRegisteredCollections","inputs":[{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"limit","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"listNFT","inputs":[{"type":"address","name":"collection","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"quantity","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"quantity","internalType":"uint256"},{"type":"uint8","name":"listingType","internalType":"enum NFTMarketplace.ListingType"},{"type":"uint256","name":"auctionId","internalType":"uint256"}],"name":"listings","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"makeOffer","inputs":[{"type":"address","name":"collection","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"quantity","internalType":"uint256"},{"type":"uint256","name":"price","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxAuctionDuration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minAuctionDuration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"buyer","internalType":"address"},{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"quantity","internalType":"uint256"},{"type":"uint256","name":"createTime","internalType":"uint256"},{"type":"uint8","name":"status","internalType":"enum NFTMarketplace.OfferStatus"}],"name":"offers","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"onERC1155BatchReceived","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"},{"type":"uint256[]","name":"","internalType":"uint256[]"},{"type":"uint256[]","name":"","internalType":"uint256[]"},{"type":"bytes","name":"","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"onERC1155Received","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"bytes","name":"","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"placeBid","inputs":[{"type":"uint256","name":"auctionId","internalType":"uint256"},{"type":"uint256","name":"bidAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"primaryFee","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"registerCollection","inputs":[{"type":"address","name":"collection","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"registeredCollections","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rejectOffer","inputs":[{"type":"uint256","name":"offerId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeListing","inputs":[{"type":"address","name":"collection","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"secondaryFee","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAuctionExtensionInterval","inputs":[{"type":"uint256","name":"_interval","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setCollectionFactory","inputs":[{"type":"address","name":"_factory","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPrimaryFee","inputs":[{"type":"uint256","name":"_fee","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setSecondaryFee","inputs":[{"type":"uint256","name":"_fee","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"settleAuction","inputs":[{"type":"uint256","name":"auctionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalCollections","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawFees","inputs":[]}]
Contract Creation Code
0x60a06040523480156200001157600080fd5b5060405162005e6b38038062005e6b83398101604081905262000034916200016a565b60016000556001600160a01b038316620000955760405162461bcd60e51b815260206004820152601560248201527f496e76616c696420746f6b656e2061646472657373000000000000000000000060448201526064015b60405180910390fd5b6103e8821115620000e95760405162461bcd60e51b815260206004820152601460248201527f5072696d6172792066656520746f6f206869676800000000000000000000000060448201526064016200008c565b6103e88111156200013d5760405162461bcd60e51b815260206004820152601660248201527f5365636f6e646172792066656520746f6f20686967680000000000000000000060448201526064016200008c565b6001600160a01b03909216608052600155600255610e1060075562278d00600855610258600955620001af565b6000806000606084860312156200018057600080fd5b83516001600160a01b03811681146200019857600080fd5b602085015160409095015190969495509392505050565b608051615c2962000242600039600081816105d901528181610c2e015281816112a20152818161134001528181611bda01528181611c6e01528181611d0d0152818161240f0152818161248c015281816126b90152818161274c01528181612fbb01528181613042015281816130fd015281816135b401528181613b9001528181614b040152614ba30152615c296000f3fe608060405234801561001057600080fd5b506004361061027f5760003560e01c806359edbe711161015c5780638da5cb5b116100ce578063cf25a2fd11610087578063cf25a2fd146106bb578063d371f24f146106ce578063e3b43677146106f7578063ef706adf1461076d578063f23a6e6114610780578063f2fde38b1461079f57600080fd5b80638da5cb5b1461063957806396b5a75514610641578063a914607c14610654578063bc197c811461065d578063bc72157a14610695578063c815729d146106a857600080fd5b80637561a71d116101205780637561a71d146105a5578063791bb4ef146105ae5780637b1e7675146105c15780637c89d2f0146105d4578063822232021461061357806388b10c751461062657600080fd5b806359edbe711461050257806361d9db2d146105155780636bd3a64b1461051e578063715018a61461058a57806371626bd91461059257600080fd5b8063402d698f116101f5578063476343ee116101b9578063476343ee1461044657806348c9581e1461044e5780635413487614610457578063570ff4de14610460578063571a26a01461046957806357c90de5146104ef57600080fd5b8063402d698f146103be57806341c40576146103d157806342eb81d5146103e45780634579268a1461040457806347518c161461042657600080fd5b80631ba186ce116102475780631ba186ce146103185780631cd8d512146103395780632e9936111461034c57806334277f071461035f5780633c44a5f0146103725780633f1ffcec1461038557600080fd5b806301ffc9a7146102845780630d8264c1146102ac5780630ebf3675146102cf5780630f54a822146102f05780631387c2b514610305575b600080fd5b610297610292366004614f51565b6107b2565b60405190151581526020015b60405180910390f35b6102976102ba366004614f90565b600b6020526000908152604090205460ff1681565b6102e26102dd366004614fad565b6107e9565b6040516102a3929190614fe8565b6103036102fe366004615030565b61080a565b005b610303610313366004615049565b61089b565b61032b61032636600461509b565b610d1f565b6040516102a3929190615114565b610303610347366004615030565b610f9b565b61030361035a366004615030565b61101f565b6102e261036d36600461509b565b6115b9565b610303610380366004614fad565b6115d9565b6103b0610393366004615136565b600e60209081526000928352604080842090915290825290205481565b6040519081526020016102a3565b6103036103cc366004615166565b6118e6565b6103036103df366004614f90565b611f40565b6103f76103f23660046151ae565b6120dc565b6040516102a391906151d0565b610417610412366004615030565b612202565b6040516102a39392919061520d565b610439610434366004615277565b612325565b6040516102a391906152c9565b6103036123ef565b6103b060085481565b6103b060075481565b6103b060025481565b6104d9610477366004615030565b600d602052600090815260409020805460018201546002830154600384015460048501546005860154600687015460078801546008909801546001600160a01b039788169896979596949593949293919291811690600160a01b900460ff168a565b6040516102a39a99989796959493929190615310565b6103036104fd3660046151ae565b612526565b610303610510366004615381565b612880565b6103b060045481565b61057961052c366004615277565b600a602090815260009384526040808520825292845282842090528252902080546001820154600283015460038401546004909401546001600160a01b03909316939192909160ff169085565b6040516102a39594939291906153ad565b610303612b2a565b6102e26105a036600461509b565b612b3e565b6103b060015481565b6103b06105bc3660046153e8565b612b52565b6103036105cf366004615434565b612bb4565b6105fb7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b610303610621366004615030565b6133ab565b610303610634366004615030565b61342b565b6105fb613684565b61030361064f366004615030565b6136b2565b6103b060095481565b61067c61066b366004615617565b63bc197c8160e01b95945050505050565b6040516001600160e01b031990911681526020016102a3565b6103036106a3366004614f90565b61391e565b6103036106b6366004615030565b61399e565b6003546105fb906001600160a01b031681565b6105fb6106dc366004615030565b600f602052600090815260409020546001600160a01b031681565b61075b61070536600461509b565b60106020908152600093845260408085208252928452828420905282529020805460018201546002830154600384015460048501546005909501546001600160a01b039485169593909416939192909160ff1686565b6040516102a3969594939291906156c5565b61030361077b366004615030565b613a75565b61067c61078e3660046156ff565b63f23a6e6160e01b95945050505050565b6103036107ad366004614f90565b613c5d565b60006001600160e01b03198216630271189760e51b14806107e357506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060006107fd8686600087876000613c98565b9150915094509492505050565b610812613d3f565b6103e88111156108585760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b60448201526064015b60405180910390fd5b60028190556040805160008152602081018390527fdcabe98a3516480dd980e2164ecede5a6829fda8ff4471d83d8bf3391367815491015b60405180910390a150565b6108a3613d71565b6001600160a01b0385166000908152600b602052604090205460ff166108db5760405162461bcd60e51b815260040161084f90615768565b600082116108fb5760405162461bcd60e51b815260040161084f9061579f565b6000811161093b5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420707269636560981b604482015260640161084f565b6001600160a01b0383166109825760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b63632b960911b604482015260640161084f565b6001600160a01b0383163314156109db5760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f74206d616b65206f6666657220746f2073656c6600000000000000604482015260640161084f565b604051627eeac760e11b81526000906001600160a01b0387169062fdd58e90610a0a90879089906004016157c9565b602060405180830381865afa158015610a27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4b91906157e2565b905082811015610a9d5760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e742073656c6c65722062616c616e63650000000000604482015260640161084f565b60068054906000610aad83615811565b90915550506006546040805160c0810182523381526001600160a01b03871660208201529081018490526060810185905242608082015260a08101600090526001600160a01b0380891660009081526010602090815260408083208b84528252808320868452825291829020845181549085166001600160a01b0319918216178255918501516001808301805492909616919093161790935590830151600283015560608301516003808401919091556080840151600484015560a08401516005840180549193909260ff19909216918490811115610b8e57610b8e6151e3565b021790555050336000818152601160209081526040808320805460018181018355918552838520018790556001600160a01b038b811685526014845282852080548084018255908652848620018890558d8116808652601585528386208e875285528386208054938401815586528486209092018890558785526012845282852080546001600160a01b03191690921790915560139092529091208990557f00000000000000000000000000000000000000000000000000000000000000001691506323b872dd9030610c61888861582c565b6040518463ffffffff1660e01b8152600401610c7f9392919061584b565b6020604051808303816000875af1158015610c9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc2919061586f565b5085876001600160a01b0316827f7bfcb39fd55d72b78fc79c395e43811f2690be921ebd660649c546603cbab1673389888a604051610d049493929190615891565b60405180910390a45050610d186001600055565b5050505050565b6060600080805b600454811015610ddd576000818152600c6020908152604091829020548251638da5cb5b60e01b815292516001600160a01b0391821693918b16928492638da5cb5b92600480830193928290030181865afa158015610d89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dad91906158ca565b6001600160a01b03161415610dca5782610dc681615811565b9350505b5080610dd581615811565b915050610d26565b5080851115610e1f5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a59081bd9999cd95d60921b604482015260640161084f565b6000610e2b86836158e7565b905084811115610e385750835b8067ffffffffffffffff811115610e5157610e516154a9565b604051908082528060200260200182016040528015610e7a578160200160208202803683370190505b50935060008060005b60045481108015610e9357508383105b15610f8c576000818152600c6020908152604091829020548251638da5cb5b60e01b815292516001600160a01b0391821693918e16928492638da5cb5b92600480830193928290030181865afa158015610ef1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1591906158ca565b6001600160a01b03161415610f785789831015610f3f5782610f3681615811565b93505050610f7a565b80888581518110610f5257610f526158fe565b6001600160a01b039092166020928302919091019091015283610f7481615811565b9450505b505b80610f8481615811565b915050610e83565b50929350505050935093915050565b610fa3613d3f565b6103e8811115610fe45760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b604482015260640161084f565b600181815560408051918252602082018390527fdcabe98a3516480dd980e2164ecede5a6829fda8ff4471d83d8bf339136781549101610890565b611027613d71565b6000818152600d60205260408120906008820154600160a01b900460ff166002811115611056576110566151e3565b146110735760405162461bcd60e51b815260040161084f90615914565b806005015442116110ba5760405162461bcd60e51b8152602060048201526011602482015270105d58dd1a5bdb881b9bdd08195b991959607a1b604482015260640161084f565b60088101546001600160a01b03166111055760405162461bcd60e51b815260206004820152600e60248201526d139bc8189a591cc81c1b1858d95960921b604482015260640161084f565b600881018054600160a01b60ff60a01b199091161790556000828152600f602052604080822054600284015460068501549251637d4cd84760e01b815260048101939093526001600160a01b039091169290918390637d4cd84790602401600060405180830381865afa158015611180573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111a891908101906159af565b6002548554608083015192935090916001600160a01b03908116911614156111cf57506001545b6000846001600160a01b03166359c8b7dd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561120f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112339190615a7f565b905060006103e8611244848761582c565b61124e9190615aa3565b905060006103e861126361ffff85168861582c565b61126d9190615aa3565b905060008161127c84896158e7565b61128691906158e7565b895460405163a9059cbb60e01b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263a9059cbb926112da92169085906004016157c9565b6020604051808303816000875af11580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d919061586f565b5081156113bb57608086015160405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb91611376919086906004016157c9565b6020604051808303816000875af1158015611395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b9919061586f565b505b600889015460068a015460078b0154604051637921219560e11b81526001600160a01b03808d169463f242432a946113fe94309492909316929091600401615ac5565b600060405180830381600087803b15801561141857600080fd5b505af115801561142c573d6000803e3d6000fd5b5050505060008960000160009054906101000a90046001600160a01b03169050600a60008a6001600160a01b03166001600160a01b0316815260200190815260200160002060008b6006015481526020019081526020016000206000826001600160a01b03166001600160a01b03168152602001908152602001600020600080820160006101000a8154906001600160a01b030219169055600182016000905560028201600090556003820160006101000a81549060ff0219169055600482016000905550508960060154896001600160a01b0316600080516020615bd48339815191528360405161155491906001600160a01b03919091168152604060208201819052600f908201526e105550d51253d397d4d15515131151608a1b606082015260800190565b60405180910390a360088a01546040518981526001600160a01b03909116908c907fc9f72b276a388619c6d185d146697036241880c36654b1a3ffdad07c24038d999060200160405180910390a3505050505050505050506115b66001600055565b50565b606060006115cd6000808787876002613c98565b91509150935093915050565b6115e1613d71565b6001600160a01b0384166000908152600b602052604090205460ff166116195760405162461bcd60e51b815260040161084f90615768565b600082116116595760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420707269636560981b604482015260640161084f565b600081116116795760405162461bcd60e51b815260040161084f9061579f565b604051627eeac760e11b815281906001600160a01b0386169062fdd58e906116a790339088906004016157c9565b602060405180830381865afa1580156116c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e891906157e2565b10156117065760405162461bcd60e51b815260040161084f90615afd565b6001600160a01b0384166000908152600a60209081526040808320868452825280832033845290915290206002810154158061179757506001600382015460ff166001811115611758576117586151e3565b1480156117975750600060048201546000908152600d6020526040902060080154600160a01b900460ff166002811115611794576117946151e3565b14155b6117d45760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e481b1a5cdd195960921b604482015260640161084f565b6040805160a081018252338152602081018590529081018390526060810160008152600060209182018190526001600160a01b038881168252600a835260408083208984528452808320338452845291829020845181546001600160a01b03191692169190911781559183015160018084019190915590830151600283015560608301516003830180549192909160ff1916908381811115611878576118786151e3565b02179055506080820151816004015590505083856001600160a01b03167f97e6d0949163c71f57f0ac35f319e1895a30454cba82cfe6b940b9862cc0dbdd3386866000806040516118cd9594939291906153ad565b60405180910390a3506118e06001600055565b50505050565b6118ee613d71565b6001600160a01b0384166000908152600b602052604090205460ff166119265760405162461bcd60e51b815260040161084f90615768565b6001600160a01b038085166000908152600a6020908152604080832087845282528083208685168085529252909120805490921614801561196b575060008160020154115b6119a95760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206c697374696e6760881b604482015260640161084f565b6000600382015460ff1660018111156119c4576119c46151e3565b14611a0d5760405162461bcd60e51b81526020600482015260196024820152784e6f742061206669786564207072696365206c697374696e6760381b604482015260640161084f565b8181600201541015611a595760405162461bcd60e51b8152602060048201526015602482015274496e73756666696369656e74207175616e7469747960581b604482015260640161084f565b604051637d4cd84760e01b8152600481018590526000906001600160a01b03871690637d4cd84790602401600060405180830381865afa158015611aa1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ac991908101906159af565b905060006002549050846001600160a01b031682608001516001600160a01b03161415611af557506001545b6000876001600160a01b03166359c8b7dd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b599190615a7f565b90506000858560010154611b6d919061582c565b905060006103e8611b7e858461582c565b611b889190615aa3565b905060006103e8611b9d61ffff86168561582c565b611ba79190615aa3565b9050600081611bb684866158e7565b611bc091906158e7565b6040516323b872dd60e01b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90611c139033903090889060040161584b565b6020604051808303816000875af1158015611c32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c56919061586f565b506040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90611ca79033908e90869060040161584b565b6020604051808303816000875af1158015611cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cea919061586f565b508115611d895760808701516040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916323b872dd91611d44913391879060040161584b565b6020604051808303816000875af1158015611d63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d87919061586f565b505b8b6001600160a01b031663f242432a8b338e8d6040518563ffffffff1660e01b8152600401611dbb9493929190615ac5565b600060405180830381600087803b158015611dd557600080fd5b505af1158015611de9573d6000803e3d6000fd5b5050505088886002016000828254611e0191906158e7565b90915550506002880154611ee257600a60008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008c815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020600080820160006101000a8154906001600160a01b030219169055600182016000905560028201600090556003820160006101000a81549060ff0219169055600482016000905550508a8c6001600160a01b0316600080516020615bd48339815191528c604051611ed99190615b2b565b60405180910390a35b8a8c6001600160a01b03167f85d6aff492354cbf7fdd7efb2bd8bce059037aef73b968f95d32a417598cbff98c338c600101548e604051611f269493929190615891565b60405180910390a350505050505050506118e06001600055565b6003546001600160a01b03163314611f9a5760405162461bcd60e51b815260206004820152601960248201527f4f6e6c7920666163746f72792063616e20726567697374657200000000000000604482015260640161084f565b6001600160a01b038116611ff05760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6c6c656374696f6e2061646472657373000000000000604482015260640161084f565b6001600160a01b0381166000908152600b602052604090205460ff161561204e5760405162461bcd60e51b8152602060048201526012602482015271105b1c9958591e481c9959da5cdd195c995960721b604482015260640161084f565b6001600160a01b0381166000818152600b60209081526040808320805460ff19166001179055600480548452600c909252822080546001600160a01b031916909317909255815491906120a083615811565b90915550506040516001600160a01b038216907ffb99393fd31547f4a765604f2c2d122ce8ccb313edeef8b951130d8bcca866e990600090a250565b60606004548311156121215760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a59081bd9999cd95d60921b604482015260640161084f565b60008360045461213191906158e7565b90508281111561213e5750815b8067ffffffffffffffff811115612157576121576154a9565b604051908082528060200260200182016040528015612180578160200160208202803683370190505b50915060005b818110156121fa57600c600061219c8388615b5f565b815260200190815260200160002060009054906101000a90046001600160a01b03168382815181106121d0576121d06158fe565b6001600160a01b0390921660209283029190910190910152806121f281615811565b915050612186565b505092915050565b60008061223b6040805160c08101825260008082526020820181905291810182905260608101829052608081018290529060a082015290565b6000848152601260205260409020546001600160a01b03169250826122725760405162461bcd60e51b815260040161084f90615b77565b6000848152601360209081526040808320546001600160a01b038088168552601084528285208286528452828520898652845293829020825160c081018452815486168152600182015490951693850193909352600283015491840191909152600380830154606085015260048301546080850152600583015491955060a084019160ff1690811115612307576123076151e3565b6003811115612318576123186151e3565b90525090505b9193909250565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526001600160a01b038085166000908152600a6020908152604080832087845282528083208685168452825291829020825160a08101845281549094168452600180820154928501929092526002810154928401929092526003820154606084019160ff909116908111156123c6576123c66151e3565b60018111156123d7576123d76151e3565b815260200160048201548152505090505b9392505050565b6123f7613d3f565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561245e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061248291906157e2565b905080156115b6577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6124c1613684565b836040518363ffffffff1660e01b81526004016124df9291906157c9565b6020604051808303816000875af11580156124fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612522919061586f565b5050565b61252e613d71565b6000828152600d60205260408120906008820154600160a01b900460ff16600281111561255d5761255d6151e3565b1461257a5760405162461bcd60e51b815260040161084f90615914565b80600501544211156125be5760405162461bcd60e51b815260206004820152600d60248201526c105d58dd1a5bdb88195b991959609a1b604482015260640161084f565b806003015481600201546125d29190615b5f565b82101561260f5760405162461bcd60e51b815260206004820152600b60248201526a42696420746f6f206c6f7760a81b604482015260640161084f565b60095442826005015461262291906158e7565b11612671576009546126349042615b5f565b6005820181905560405190815283907f6e912a3a9105bdd2af817ba5adc14e6c127c1035b5b648faa29ca0d58ab8ff4e9060200160405180910390a25b60088101546000848152600e602090815260408083206001600160a01b039094168084529390915290205481156127355760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906126f090859085906004016157c9565b6020604051808303816000875af115801561270f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612733919061586f565b505b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906127859033903090899060040161584b565b6020604051808303816000875af11580156127a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127c8919061586f565b6128065760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161084f565b6008830180546001600160a01b03191633908117909155600284018590556000868152600e60209081526040808320848452825291829020879055905186815287917f0e54eff26401bf69b81b26f60bd85ef47f5d85275c1d268d84f68d6897431c47910160405180910390a35050506125226001600055565b612888613d71565b6001600160a01b038083166000908152600a60209081526040808320858452825280832033808552925290912080549092161480156128cb575060008160020154115b61290b5760405162461bcd60e51b81526020600482015260116024820152704e6f20616374697665206c697374696e6760781b604482015260640161084f565b6001600382015460ff166001811115612926576129266151e3565b1415612a7a5760048101546000908152600d60205260408120906008820154600160a01b900460ff166002811115612960576129606151e3565b1461297d5760405162461bcd60e51b815260040161084f90615914565b60088101546001600160a01b0316156129ce5760405162461bcd60e51b8152602060048201526013602482015272109a591cc8185b1c9958591e481c1b1858d959606a1b604482015260640161084f565b60088101805460ff60a01b1916600160a11b1790556002820154604051637921219560e11b81526001600160a01b0386169163f242432a91612a1891309133918991600401615ac5565b600060405180830381600087803b158015612a3257600080fd5b505af1158015612a46573d6000803e3d6000fd5b5050505060048201546040517f2809c7e17bf978fbc7194c0a694b638c4215e9140cacc6c38ca36010b45697df90600090a2505b6001600160a01b0383166000818152600a6020908152604080832086845282528083203380855290835281842080546001600160a01b0319168155600181018590556002810185905560038101805460ff19169055600401939093558051928352908201819052601190820152702922a6a7ab22a22fa12cafa9a2a62622a960791b6060820152839190600080516020615bd48339815191529060800160405180910390a3506125226001600055565b612b32613d3f565b612b3c6000613dcb565b565b606060006115cd6000808787876001613c98565b6000612b5c613d71565b612b6a878787878787613e3c565b60058054906000612b7a83615811565b9091555050600554612b8f888888888561418a565b612b9e8189898989898961428b565b9050612baa6001600055565b9695505050505050565b612bbc613d71565b80612bf75760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b604482015260640161084f565b60005b818110156133a05736838383818110612c1557612c156158fe565b608002919091019150600b90506000612c316020840184614f90565b6001600160a01b0316815260208101919091526040016000205460ff16612c6a5760405162461bcd60e51b815260040161084f90615768565b6000600a81612c7c6020850185614f90565b6001600160a01b03166001600160a01b031681526020019081526020016000206000836020013581526020019081526020016000206000836040016020810190612cc69190614f90565b6001600160a01b03166001600160a01b031681526020019081526020016000209050816040016020810190612cfb9190614f90565b81546001600160a01b039081169116148015612d1b575060008160020154115b612d595760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206c697374696e6760881b604482015260640161084f565b6000600382015460ff166001811115612d7457612d746151e3565b14612dbd5760405162461bcd60e51b81526020600482015260196024820152784e6f742061206669786564207072696365206c697374696e6760381b604482015260640161084f565b816060013581600201541015612e0d5760405162461bcd60e51b8152602060048201526015602482015274496e73756666696369656e74207175616e7469747960581b604482015260640161084f565b6000612e1c6020840184614f90565b604051637d4cd84760e01b8152602085013560048201526001600160a01b039190911690637d4cd84790602401600060405180830381865afa158015612e66573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e8e91908101906159af565b600254909150612ea46060850160408601614f90565b6001600160a01b031682608001516001600160a01b03161415612ec657506001545b6000612ed56020860186614f90565b6001600160a01b03166359c8b7dd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f369190615a7f565b9050600085606001358560010154612f4e919061582c565b905060006103e8612f5f858461582c565b612f699190615aa3565b905060006103e8612f7e61ffff86168561582c565b612f889190615aa3565b9050600081612f9784866158e7565b612fa191906158e7565b6040516323b872dd60e01b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90612ff49033903090889060040161584b565b6020604051808303816000875af1158015613013573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613037919061586f565b506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd3361307860608d0160408e01614f90565b846040518463ffffffff1660e01b81526004016130979392919061584b565b6020604051808303816000875af11580156130b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130da919061586f565b5081156131795760808701516040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916323b872dd91613134913391879060040161584b565b6020604051808303816000875af1158015613153573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613177919061586f565b505b61318660208a018a614f90565b6001600160a01b031663f242432a6131a460608c0160408d01614f90565b338c602001358d606001356040518563ffffffff1660e01b81526004016131ce9493929190615ac5565b600060405180830381600087803b1580156131e857600080fd5b505af11580156131fc573d6000803e3d6000fd5b50505050886060013588600201600082825461321891906158e7565b9091555050600288015461331657600a600061323760208c018c614f90565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008a60200135815260200190815260200160002060008a60400160208101906132819190614f90565b6001600160a01b03168152602080820192909252604001600090812080546001600160a01b0319168155600181018290556002810182905560038101805460ff191690556004015589018035906132d8908b614f90565b6001600160a01b0316600080516020615bd483398151915261330060608d0160408e01614f90565b60405161330d9190615b2b565b60405180910390a35b60208901803590613327908b614f90565b6001600160a01b03167f85d6aff492354cbf7fdd7efb2bd8bce059037aef73b968f95d32a417598cbff961336160608d0160408e01614f90565b338c600101548e6060013560405161337c9493929190615891565b60405180910390a3505050505050505050808061339890615811565b915050612bfa565b506125226001600055565b6133b3613d3f565b600081116133f65760405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081a5b9d195c9d985b60821b604482015260640161084f565b60098190556040518181527f70d2c25f438b055a840aa5b6a9c16e5555b10f0b947ac750dbd16ecefd55e78f90602001610890565b613433613d71565b6000818152601260209081526040808320546013909252909120546001600160a01b0390911690816134775760405162461bcd60e51b815260040161084f90615b77565b6001600160a01b03821660009081526010602090815260408083208484528252808320868452909152812090600582015460ff1660038111156134bc576134bc6151e3565b146134d95760405162461bcd60e51b815260040161084f90615ba5565b604051627eeac760e11b81526000906001600160a01b0385169062fdd58e9061350890339087906004016157c9565b602060405180830381865afa158015613525573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061354991906157e2565b116135885760405162461bcd60e51b815260206004820152600f60248201526e2737ba103a37b5b2b71037bbb732b960891b604482015260640161084f565b6005810180546002919060ff191660018302179055508054600382015460028301546001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169363a9059cbb939116916135e9919061582c565b6040518363ffffffff1660e01b81526004016136069291906157c9565b6020604051808303816000875af1158015613625573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613649919061586f565b50604051339085907f1b15bc319d6f29dd5bcf76cd2b89490ed2fe49f1a31fb6b8624b0029fd85c26590600090a35050506115b66001600055565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6136ba613d71565b6000818152600d60205260408120906008820154600160a01b900460ff1660028111156136e9576136e96151e3565b146137065760405162461bcd60e51b815260040161084f90615914565b80546001600160a01b0316331461374c5760405162461bcd60e51b815260206004820152600a6024820152692737ba1039b2b63632b960b11b604482015260640161084f565b60088101546001600160a01b03161561379d5760405162461bcd60e51b8152602060048201526013602482015272109a591cc8185b1c9958591e481c1b1858d959606a1b604482015260640161084f565b60088101805460ff60a01b1916600160a11b1790556000828152600f602052604090819020548254600684015460078501549351637921219560e11b81526001600160a01b0393841694859463f242432a9461380494309492909116929091600401615ac5565b600060405180830381600087803b15801561381e57600080fd5b505af1158015613832573d6000803e3d6000fd5b505050506001600160a01b038181166000818152600a602090815260408083206006880180548552908352818420885487168552835281842080546001600160a01b0319168155600181018590556002810185905560038101805460ff19169055600401939093559154865483519516855290840182905260118483015270105550d51253d397d0d05390d153131151607a1b606085015290519092600080516020615bd4833981519152919081900360800190a360405183907f2809c7e17bf978fbc7194c0a694b638c4215e9140cacc6c38ca36010b45697df90600090a250506115b66001600055565b613926613d3f565b6001600160a01b03811661397c5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420666163746f72792061646472657373000000000000000000604482015260640161084f565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6139a6613d71565b60008060006139b4846144bc565b6040805160c08101825282546001600160a01b03908116825260018401541660208201526002830154918101919091526003808301546060830152600483015460808301526005830154949750929550909350600092613a4992879287929091879160a084019160ff90911690811115613a3057613a306151e3565b6003811115613a4157613a416151e3565b9052506145b4565b9050613a5b8484846003015484614653565b613a6784848488614865565b505050506115b66001600055565b613a7d613d71565b6000818152601260209081526040808320546013909252909120546001600160a01b039091169081613ac15760405162461bcd60e51b815260040161084f90615b77565b6001600160a01b0380831660009081526010602090815260408083208584528252808320878452909152902080549091163314613b345760405162461bcd60e51b81526020600482015260116024820152702737ba1037b33332b91031b932b0ba37b960791b604482015260640161084f565b6000600582015460ff166003811115613b4f57613b4f6151e3565b14613b6c5760405162461bcd60e51b815260040161084f90615ba5565b60058101805460ff1916600390811790915581015460028201546001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb913391613bc29161582c565b6040518363ffffffff1660e01b8152600401613bdf9291906157c9565b6020604051808303816000875af1158015613bfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c22919061586f565b50604051339085907f1f51377b3e685a0e2419f9bb4ba7c07ec54936353ba3d0fb3c6538dab676622290600090a35050506115b66001600055565b613c65613d3f565b6001600160a01b038116613c8f57604051631e4fbdf760e01b81526000600482015260240161084f565b6115b681613dcb565b606060008060405180608001604052808a6001600160a01b03168152602001898152602001886001600160a01b031681526020018560ff1681525090506000613ce2888684614c67565b90506000613cf08284614ce6565b9050801580613cff5750808810155b15613d1f5760408051600081526020810190915294509250613d34915050565b613d2c82848a8a85614d48565b945094505050505b965096945050505050565b33613d48613684565b6001600160a01b031614612b3c5760405163118cdaa760e01b815233600482015260240161084f565b60026000541415613dc45760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161084f565b6002600055565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6001600160a01b0386166000908152600b602052604090205460ff16613e745760405162461bcd60e51b815260040161084f90615768565b60008411613e945760405162461bcd60e51b815260040161084f9061579f565b60008311613eda5760405162461bcd60e51b8152602060048201526013602482015272496e76616c696420737461727420707269636560681b604482015260640161084f565b60008211613f2a5760405162461bcd60e51b815260206004820152601960248201527f496e76616c6964206d696e2062696420696e6372656d656e7400000000000000604482015260640161084f565b6007548110158015613f3e57506008548111155b613f7d5760405162461bcd60e51b815260206004820152601060248201526f24b73b30b634b210323ab930ba34b7b760811b604482015260640161084f565b604051627eeac760e11b815284906001600160a01b0388169062fdd58e90613fab9033908a906004016157c9565b602060405180830381865afa158015613fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fec91906157e2565b101561400a5760405162461bcd60e51b815260040161084f90615afd565b60405163e985e9c560e01b81523360048201523060248201526001600160a01b0387169063e985e9c590604401602060405180830381865afa158015614054573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614078919061586f565b6140b35760405162461bcd60e51b815260206004820152600c60248201526b139bdd08185c1c1c9bdd995960a21b604482015260640161084f565b6001600160a01b0386166000908152600a60209081526040808320888452825280832033845290915290206002810154158061414457506001600382015460ff166001811115614105576141056151e3565b1480156141445750600060048201546000908152600d6020526040902060080154600160a01b900460ff166002811115614141576141416151e3565b14155b6141815760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e481b1a5cdd195960921b604482015260640161084f565b50505050505050565b6040805160a081018252338082526020808301868152838501888152600160608601818152608087018990526001600160a01b038d81166000908152600a87528981208e825287528981209781529690955296909420855181546001600160a01b031916941693909317835590518284015551600282015592516003840180549394939192909160ff1916908381811115614227576142276151e3565b02179055506080820151816004015590505083856001600160a01b03167f97e6d0949163c71f57f0ac35f319e1895a30454cba82cfe6b940b9862cc0dbdd33858760018760405161427c9594939291906153ad565b60405180910390a35050505050565b4260006142988383615b5f565b9050604051806101400160405280336001600160a01b0316815260200186815260200186815260200185815260200183815260200182815260200188815260200187815260200160006001600160a01b0316815260200160006002811115614302576143026151e3565b905260008a8152600d6020908152604091829020835181546001600160a01b03199081166001600160a01b0392831617835592850151600183015592840151600280830191909155606085015160038301556080850151600483015560a0850151600583015560c0850151600683015560e08501516007830155610100850151600883018054948516919095169081178555610120860151929492936001600160a81b0319161790600160a01b9084908111156143c1576143c16151e3565b021790555050506000898152600f60205260409081902080546001600160a01b0319166001600160a01b038b169081179091559051637921219560e11b815263f242432a9061441a90339030908c908c90600401615ac5565b600060405180830381600087803b15801561443457600080fd5b505af1158015614448573d6000803e3d6000fd5b50506040805133815260208101899052908101879052606081018590526080810184905260a081018990528992506001600160a01b038b1691508b907f2a7e6a41d497de122134820d2f68c4e648c60cf6f4a1ecb9cd1c3cf37384589f9060c00160405180910390a4505050505050505050565b6000818152601260205260408120546001600160a01b03169080826144f35760405162461bcd60e51b815260040161084f90615b77565b50506000828152601360209081526040808320546001600160a01b038516845260108352818420818552835281842086855290925282209091600582015460ff166003811115614545576145456151e3565b146145625760405162461bcd60e51b815260040161084f90615ba5565b60018101546001600160a01b0316331461231e5760405162461bcd60e51b8152602060048201526013602482015272139bdd081bd999995c881c9958da5c1a595b9d606a1b604482015260640161084f565b600080846001600160a01b031662fdd58e33866040518363ffffffff1660e01b81526004016145e49291906157c9565b602060405180830381865afa158015614601573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061462591906157e2565b9050826060015181101561464b5760405162461bcd60e51b815260040161084f90615afd565b949350505050565b6001600160a01b0384166000908152600a60209081526040808320868452825280832033845290915290206001600382015460ff166001811115614699576146996151e3565b141561471957600060048201546000908152600d6020526040902060080154600160a01b900460ff1660028111156146d3576146d36151e3565b14156147195760405162461bcd60e51b81526020600482015260156024820152744163746976652061756374696f6e2065786973747360581b604482015260640161084f565b6002810154600061472a82856158e7565b905060008582101561473c578161473e565b855b9050600061474c82886158e7565b9050801561485a5783811415614802576001600160a01b0389166000818152600a602090815260408083208c845282528083203380855290835281842080546001600160a01b0319168155600181018590556002810185905560038101805460ff19169055600401939093558051928352908201819052600d908201526c5a45524f5f5155414e5449545960981b6060820152899190600080516020615bd48339815191529060800160405180910390a361485a565b61480c81856158e7565b6002860181905560405189916001600160a01b038c16917f36dba6da50cf7eb05d1a346c00f785d8a335ca42221245492e6e243624ce71fb91614851913391906157c9565b60405180910390a35b505050505050505050565b60405163e985e9c560e01b81523360048201523060248201526001600160a01b0385169063e985e9c590604401602060405180830381865afa1580156148af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148d3919061586f565b61490e5760405162461bcd60e51b815260206004820152600c60248201526b139bdd08185c1c1c9bdd995960a21b604482015260640161084f565b604051637d4cd84760e01b8152600481018490526000906001600160a01b03861690637d4cd84790602401600060405180830381865afa158015614956573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261497e91908101906159af565b6002546080820151919250906001600160a01b031633141561499f57506001545b6000866001600160a01b03166359c8b7dd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156149df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a039190615a7f565b9050600085600301548660020154614a1b919061582c565b905060006103e8614a2c858461582c565b614a369190615aa3565b905060006103e8614a4b61ffff86168561582c565b614a559190615aa3565b9050600081614a6484866158e7565b614a6e91906158e7565b90508a6001600160a01b031663f242432a338b60000160009054906101000a90046001600160a01b03168d8d600301546040518563ffffffff1660e01b8152600401614abd9493929190615ac5565b600060405180830381600087803b158015614ad757600080fd5b505af1158015614aeb573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063a9059cbb9150614b3d90339085906004016157c9565b6020604051808303816000875af1158015614b5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b80919061586f565b508115614c1e57608087015160405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb91614bd9919086906004016157c9565b6020604051808303816000875af1158015614bf8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c1c919061586f565b505b60058901805460ff19166001179055604051339089907fa7a40af5a1d0c10a3eb94af90cb008170915e8a71a6aaff052794cd762c72fc090600090a35050505050505050505050565b600060ff8316614c9e575080516001600160a01b0316600090815260156020908152604080832082850151845290915290206123e8565b8260ff1660011415614cc857506001600160a01b03831660009081526014602052604090206123e8565b506001600160a01b03831660009081526011602052604090206123e8565b60008060005b8454811015614d4057614d1b858281548110614d0a57614d0a6158fe565b906000526020600020015485614e5e565b15614d2e5781614d2a81615811565b9250505b80614d3881615811565b915050614cec565b509392505050565b6060600080614d5786856158e7565b905084811115614d645750835b8067ffffffffffffffff811115614d7d57614d7d6154a9565b604051908082528060200260200182016040528015614da6578160200160208202803683370190505b50925060008060005b8a5481108015614dbe57508383105b15614e4d5760008b8281548110614dd757614dd76158fe565b90600052602060002001549050614dee818c614e5e565b15614e395789831015614e0e5782614e0581615811565b93505050614e3b565b808785614e1a81615811565b965081518110614e2c57614e2c6158fe565b6020026020010181815250505b505b80614e4581615811565b915050614daf565b508593505050509550959350505050565b60008281526012602090815260408083205460138352818420546001600160a01b03909116808552601084528285208286528452828520878652909352908320606085015160ff16614ef85784516001600160a01b038481169116148015614ec95750846020015182145b8015614eee575060005b600582015460ff166003811115614eec57614eec6151e3565b145b93505050506107e3565b846060015160ff1660011415614f2e57604085015160018201546001600160a01b039081169116148015614eee57506000614ed3565b604085015181546001600160a01b039081169116148015614eee57506000614ed3565b600060208284031215614f6357600080fd5b81356001600160e01b0319811681146123e857600080fd5b6001600160a01b03811681146115b657600080fd5b600060208284031215614fa257600080fd5b81356123e881614f7b565b60008060008060808587031215614fc357600080fd5b8435614fce81614f7b565b966020860135965060408601359560600135945092505050565b604080825283519082018190526000906020906060840190828701845b8281101561502157815184529284019290840190600101615005565b50505092019290925292915050565b60006020828403121561504257600080fd5b5035919050565b600080600080600060a0868803121561506157600080fd5b853561506c81614f7b565b945060208601359350604086013561508381614f7b565b94979396509394606081013594506080013592915050565b6000806000606084860312156150b057600080fd5b83356150bb81614f7b565b95602085013595506040909401359392505050565b600081518084526020808501945080840160005b838110156151095781516001600160a01b0316875295820195908201906001016150e4565b509495945050505050565b60408152600061512760408301856150d0565b90508260208301529392505050565b6000806040838503121561514957600080fd5b82359150602083013561515b81614f7b565b809150509250929050565b6000806000806080858703121561517c57600080fd5b843561518781614f7b565b935060208501359250604085013561519e81614f7b565b9396929550929360600135925050565b600080604083850312156151c157600080fd5b50508035926020909101359150565b6020815260006123e860208301846150d0565b634e487b7160e01b600052602160045260246000fd5b60048110615209576152096151e3565b9052565b60006101008201905060018060a01b0380861683528460208401528084511660408401528060208501511660608401525060408301516080830152606083015160a0830152608083015160c083015260a083015161526e60e08401826151f9565b50949350505050565b60008060006060848603121561528c57600080fd5b833561529781614f7b565b92506020840135915060408401356152ae81614f7b565b809150509250925092565b60028110615209576152096151e3565b81516001600160a01b03168152602080830151908201526040808301519082015260608083015160a0830191615301908401826152b9565b50608092830151919092015290565b6001600160a01b038b81168252602082018b9052604082018a9052606082018990526080820188905260a0820187905260c0820186905260e08201859052831661010082015261014081016003831061536b5761536b6151e3565b826101208301529b9a5050505050505050505050565b6000806040838503121561539457600080fd5b823561539f81614f7b565b946020939093013593505050565b6001600160a01b0386168152602081018590526040810184905260a081016153d860608301856152b9565b8260808301529695505050505050565b60008060008060008060c0878903121561540157600080fd5b863561540c81614f7b565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b6000806020838503121561544757600080fd5b823567ffffffffffffffff8082111561545f57600080fd5b818501915085601f83011261547357600080fd5b81358181111561548257600080fd5b8660208260071b850101111561549757600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156154e2576154e26154a9565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715615511576155116154a9565b604052919050565b600082601f83011261552a57600080fd5b8135602067ffffffffffffffff821115615546576155466154a9565b8160051b6155558282016154e8565b928352848101820192828101908785111561556f57600080fd5b83870192505b8483101561558e57823582529183019190830190615575565b979650505050505050565b600067ffffffffffffffff8211156155b3576155b36154a9565b50601f01601f191660200190565b600082601f8301126155d257600080fd5b81356155e56155e082615599565b6154e8565b8181528460208386010111156155fa57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561562f57600080fd5b853561563a81614f7b565b9450602086013561564a81614f7b565b9350604086013567ffffffffffffffff8082111561566757600080fd5b61567389838a01615519565b9450606088013591508082111561568957600080fd5b61569589838a01615519565b935060808801359150808211156156ab57600080fd5b506156b8888289016155c1565b9150509295509295909350565b6001600160a01b0387811682528616602082015260408101859052606081018490526080810183905260c0810161558e60a08301846151f9565b600080600080600060a0868803121561571757600080fd5b853561572281614f7b565b9450602086013561573281614f7b565b93506040860135925060608601359150608086013567ffffffffffffffff81111561575c57600080fd5b6156b8888289016155c1565b60208082526019908201527f436f6c6c656374696f6e206e6f74207265676973746572656400000000000000604082015260600190565b60208082526010908201526f496e76616c6964207175616e7469747960801b604082015260600190565b6001600160a01b03929092168252602082015260400190565b6000602082840312156157f457600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000600019821415615825576158256157fb565b5060010190565b6000816000190483118215151615615846576158466157fb565b500290565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006020828403121561588157600080fd5b815180151581146123e857600080fd5b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b80516158c581614f7b565b919050565b6000602082840312156158dc57600080fd5b81516123e881614f7b565b6000828210156158f9576158f96157fb565b500390565b634e487b7160e01b600052603260045260246000fd5b60208082526012908201527141756374696f6e206e6f742061637469766560701b604082015260600190565b600082601f83011261595157600080fd5b815161595f6155e082615599565b8181526020858184870101111561597557600080fd5b60005b83811015615993578581018201518382018301528101615978565b838111156159a45760008285850101525b509095945050505050565b6000602082840312156159c157600080fd5b815167ffffffffffffffff808211156159d957600080fd5b9083019060a082860312156159ed57600080fd5b6159f56154bf565b825182811115615a0457600080fd5b615a1087828601615940565b825250602083015182811115615a2557600080fd5b615a3187828601615940565b602083015250604083015182811115615a4957600080fd5b615a5587828601615940565b60408301525060608301516060820152615a71608084016158ba565b608082015295945050505050565b600060208284031215615a9157600080fd5b815161ffff811681146123e857600080fd5b600082615ac057634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b602080825260149082015273496e73756666696369656e742062616c616e636560601b604082015260600190565b6001600160a01b039190911681526040602082018190526008908201526714d3d31117d3d55560c21b606082015260800190565b60008219821115615b7257615b726157fb565b500190565b60208082526014908201527313d999995c88191bd95cc81b9bdd08195e1a5cdd60621b604082015260600190565b602080825260149082015273496e76616c6964206f666665722073746174757360601b60408201526060019056fe17d654f862f895d7741bf4e3234b08875e872e59e08d21c44d35187a60cfa2a2a264697066735822122038e8d0eafbd8c404f68a0900168be87a0d969945c4a52f2d44e3d8b08582443964736f6c634300080a0033000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca700000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019
Deployed ByteCode
0x608060405234801561001057600080fd5b506004361061027f5760003560e01c806359edbe711161015c5780638da5cb5b116100ce578063cf25a2fd11610087578063cf25a2fd146106bb578063d371f24f146106ce578063e3b43677146106f7578063ef706adf1461076d578063f23a6e6114610780578063f2fde38b1461079f57600080fd5b80638da5cb5b1461063957806396b5a75514610641578063a914607c14610654578063bc197c811461065d578063bc72157a14610695578063c815729d146106a857600080fd5b80637561a71d116101205780637561a71d146105a5578063791bb4ef146105ae5780637b1e7675146105c15780637c89d2f0146105d4578063822232021461061357806388b10c751461062657600080fd5b806359edbe711461050257806361d9db2d146105155780636bd3a64b1461051e578063715018a61461058a57806371626bd91461059257600080fd5b8063402d698f116101f5578063476343ee116101b9578063476343ee1461044657806348c9581e1461044e5780635413487614610457578063570ff4de14610460578063571a26a01461046957806357c90de5146104ef57600080fd5b8063402d698f146103be57806341c40576146103d157806342eb81d5146103e45780634579268a1461040457806347518c161461042657600080fd5b80631ba186ce116102475780631ba186ce146103185780631cd8d512146103395780632e9936111461034c57806334277f071461035f5780633c44a5f0146103725780633f1ffcec1461038557600080fd5b806301ffc9a7146102845780630d8264c1146102ac5780630ebf3675146102cf5780630f54a822146102f05780631387c2b514610305575b600080fd5b610297610292366004614f51565b6107b2565b60405190151581526020015b60405180910390f35b6102976102ba366004614f90565b600b6020526000908152604090205460ff1681565b6102e26102dd366004614fad565b6107e9565b6040516102a3929190614fe8565b6103036102fe366004615030565b61080a565b005b610303610313366004615049565b61089b565b61032b61032636600461509b565b610d1f565b6040516102a3929190615114565b610303610347366004615030565b610f9b565b61030361035a366004615030565b61101f565b6102e261036d36600461509b565b6115b9565b610303610380366004614fad565b6115d9565b6103b0610393366004615136565b600e60209081526000928352604080842090915290825290205481565b6040519081526020016102a3565b6103036103cc366004615166565b6118e6565b6103036103df366004614f90565b611f40565b6103f76103f23660046151ae565b6120dc565b6040516102a391906151d0565b610417610412366004615030565b612202565b6040516102a39392919061520d565b610439610434366004615277565b612325565b6040516102a391906152c9565b6103036123ef565b6103b060085481565b6103b060075481565b6103b060025481565b6104d9610477366004615030565b600d602052600090815260409020805460018201546002830154600384015460048501546005860154600687015460078801546008909801546001600160a01b039788169896979596949593949293919291811690600160a01b900460ff168a565b6040516102a39a99989796959493929190615310565b6103036104fd3660046151ae565b612526565b610303610510366004615381565b612880565b6103b060045481565b61057961052c366004615277565b600a602090815260009384526040808520825292845282842090528252902080546001820154600283015460038401546004909401546001600160a01b03909316939192909160ff169085565b6040516102a39594939291906153ad565b610303612b2a565b6102e26105a036600461509b565b612b3e565b6103b060015481565b6103b06105bc3660046153e8565b612b52565b6103036105cf366004615434565b612bb4565b6105fb7f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca781565b6040516001600160a01b0390911681526020016102a3565b610303610621366004615030565b6133ab565b610303610634366004615030565b61342b565b6105fb613684565b61030361064f366004615030565b6136b2565b6103b060095481565b61067c61066b366004615617565b63bc197c8160e01b95945050505050565b6040516001600160e01b031990911681526020016102a3565b6103036106a3366004614f90565b61391e565b6103036106b6366004615030565b61399e565b6003546105fb906001600160a01b031681565b6105fb6106dc366004615030565b600f602052600090815260409020546001600160a01b031681565b61075b61070536600461509b565b60106020908152600093845260408085208252928452828420905282529020805460018201546002830154600384015460048501546005909501546001600160a01b039485169593909416939192909160ff1686565b6040516102a3969594939291906156c5565b61030361077b366004615030565b613a75565b61067c61078e3660046156ff565b63f23a6e6160e01b95945050505050565b6103036107ad366004614f90565b613c5d565b60006001600160e01b03198216630271189760e51b14806107e357506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060006107fd8686600087876000613c98565b9150915094509492505050565b610812613d3f565b6103e88111156108585760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b60448201526064015b60405180910390fd5b60028190556040805160008152602081018390527fdcabe98a3516480dd980e2164ecede5a6829fda8ff4471d83d8bf3391367815491015b60405180910390a150565b6108a3613d71565b6001600160a01b0385166000908152600b602052604090205460ff166108db5760405162461bcd60e51b815260040161084f90615768565b600082116108fb5760405162461bcd60e51b815260040161084f9061579f565b6000811161093b5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420707269636560981b604482015260640161084f565b6001600160a01b0383166109825760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b63632b960911b604482015260640161084f565b6001600160a01b0383163314156109db5760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f74206d616b65206f6666657220746f2073656c6600000000000000604482015260640161084f565b604051627eeac760e11b81526000906001600160a01b0387169062fdd58e90610a0a90879089906004016157c9565b602060405180830381865afa158015610a27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4b91906157e2565b905082811015610a9d5760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e742073656c6c65722062616c616e63650000000000604482015260640161084f565b60068054906000610aad83615811565b90915550506006546040805160c0810182523381526001600160a01b03871660208201529081018490526060810185905242608082015260a08101600090526001600160a01b0380891660009081526010602090815260408083208b84528252808320868452825291829020845181549085166001600160a01b0319918216178255918501516001808301805492909616919093161790935590830151600283015560608301516003808401919091556080840151600484015560a08401516005840180549193909260ff19909216918490811115610b8e57610b8e6151e3565b021790555050336000818152601160209081526040808320805460018181018355918552838520018790556001600160a01b038b811685526014845282852080548084018255908652848620018890558d8116808652601585528386208e875285528386208054938401815586528486209092018890558785526012845282852080546001600160a01b03191690921790915560139092529091208990557f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca71691506323b872dd9030610c61888861582c565b6040518463ffffffff1660e01b8152600401610c7f9392919061584b565b6020604051808303816000875af1158015610c9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc2919061586f565b5085876001600160a01b0316827f7bfcb39fd55d72b78fc79c395e43811f2690be921ebd660649c546603cbab1673389888a604051610d049493929190615891565b60405180910390a45050610d186001600055565b5050505050565b6060600080805b600454811015610ddd576000818152600c6020908152604091829020548251638da5cb5b60e01b815292516001600160a01b0391821693918b16928492638da5cb5b92600480830193928290030181865afa158015610d89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dad91906158ca565b6001600160a01b03161415610dca5782610dc681615811565b9350505b5080610dd581615811565b915050610d26565b5080851115610e1f5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a59081bd9999cd95d60921b604482015260640161084f565b6000610e2b86836158e7565b905084811115610e385750835b8067ffffffffffffffff811115610e5157610e516154a9565b604051908082528060200260200182016040528015610e7a578160200160208202803683370190505b50935060008060005b60045481108015610e9357508383105b15610f8c576000818152600c6020908152604091829020548251638da5cb5b60e01b815292516001600160a01b0391821693918e16928492638da5cb5b92600480830193928290030181865afa158015610ef1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1591906158ca565b6001600160a01b03161415610f785789831015610f3f5782610f3681615811565b93505050610f7a565b80888581518110610f5257610f526158fe565b6001600160a01b039092166020928302919091019091015283610f7481615811565b9450505b505b80610f8481615811565b915050610e83565b50929350505050935093915050565b610fa3613d3f565b6103e8811115610fe45760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b604482015260640161084f565b600181815560408051918252602082018390527fdcabe98a3516480dd980e2164ecede5a6829fda8ff4471d83d8bf339136781549101610890565b611027613d71565b6000818152600d60205260408120906008820154600160a01b900460ff166002811115611056576110566151e3565b146110735760405162461bcd60e51b815260040161084f90615914565b806005015442116110ba5760405162461bcd60e51b8152602060048201526011602482015270105d58dd1a5bdb881b9bdd08195b991959607a1b604482015260640161084f565b60088101546001600160a01b03166111055760405162461bcd60e51b815260206004820152600e60248201526d139bc8189a591cc81c1b1858d95960921b604482015260640161084f565b600881018054600160a01b60ff60a01b199091161790556000828152600f602052604080822054600284015460068501549251637d4cd84760e01b815260048101939093526001600160a01b039091169290918390637d4cd84790602401600060405180830381865afa158015611180573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111a891908101906159af565b6002548554608083015192935090916001600160a01b03908116911614156111cf57506001545b6000846001600160a01b03166359c8b7dd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561120f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112339190615a7f565b905060006103e8611244848761582c565b61124e9190615aa3565b905060006103e861126361ffff85168861582c565b61126d9190615aa3565b905060008161127c84896158e7565b61128691906158e7565b895460405163a9059cbb60e01b81529192506001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca781169263a9059cbb926112da92169085906004016157c9565b6020604051808303816000875af11580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d919061586f565b5081156113bb57608086015160405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca7169163a9059cbb91611376919086906004016157c9565b6020604051808303816000875af1158015611395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b9919061586f565b505b600889015460068a015460078b0154604051637921219560e11b81526001600160a01b03808d169463f242432a946113fe94309492909316929091600401615ac5565b600060405180830381600087803b15801561141857600080fd5b505af115801561142c573d6000803e3d6000fd5b5050505060008960000160009054906101000a90046001600160a01b03169050600a60008a6001600160a01b03166001600160a01b0316815260200190815260200160002060008b6006015481526020019081526020016000206000826001600160a01b03166001600160a01b03168152602001908152602001600020600080820160006101000a8154906001600160a01b030219169055600182016000905560028201600090556003820160006101000a81549060ff0219169055600482016000905550508960060154896001600160a01b0316600080516020615bd48339815191528360405161155491906001600160a01b03919091168152604060208201819052600f908201526e105550d51253d397d4d15515131151608a1b606082015260800190565b60405180910390a360088a01546040518981526001600160a01b03909116908c907fc9f72b276a388619c6d185d146697036241880c36654b1a3ffdad07c24038d999060200160405180910390a3505050505050505050506115b66001600055565b50565b606060006115cd6000808787876002613c98565b91509150935093915050565b6115e1613d71565b6001600160a01b0384166000908152600b602052604090205460ff166116195760405162461bcd60e51b815260040161084f90615768565b600082116116595760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420707269636560981b604482015260640161084f565b600081116116795760405162461bcd60e51b815260040161084f9061579f565b604051627eeac760e11b815281906001600160a01b0386169062fdd58e906116a790339088906004016157c9565b602060405180830381865afa1580156116c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e891906157e2565b10156117065760405162461bcd60e51b815260040161084f90615afd565b6001600160a01b0384166000908152600a60209081526040808320868452825280832033845290915290206002810154158061179757506001600382015460ff166001811115611758576117586151e3565b1480156117975750600060048201546000908152600d6020526040902060080154600160a01b900460ff166002811115611794576117946151e3565b14155b6117d45760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e481b1a5cdd195960921b604482015260640161084f565b6040805160a081018252338152602081018590529081018390526060810160008152600060209182018190526001600160a01b038881168252600a835260408083208984528452808320338452845291829020845181546001600160a01b03191692169190911781559183015160018084019190915590830151600283015560608301516003830180549192909160ff1916908381811115611878576118786151e3565b02179055506080820151816004015590505083856001600160a01b03167f97e6d0949163c71f57f0ac35f319e1895a30454cba82cfe6b940b9862cc0dbdd3386866000806040516118cd9594939291906153ad565b60405180910390a3506118e06001600055565b50505050565b6118ee613d71565b6001600160a01b0384166000908152600b602052604090205460ff166119265760405162461bcd60e51b815260040161084f90615768565b6001600160a01b038085166000908152600a6020908152604080832087845282528083208685168085529252909120805490921614801561196b575060008160020154115b6119a95760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206c697374696e6760881b604482015260640161084f565b6000600382015460ff1660018111156119c4576119c46151e3565b14611a0d5760405162461bcd60e51b81526020600482015260196024820152784e6f742061206669786564207072696365206c697374696e6760381b604482015260640161084f565b8181600201541015611a595760405162461bcd60e51b8152602060048201526015602482015274496e73756666696369656e74207175616e7469747960581b604482015260640161084f565b604051637d4cd84760e01b8152600481018590526000906001600160a01b03871690637d4cd84790602401600060405180830381865afa158015611aa1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ac991908101906159af565b905060006002549050846001600160a01b031682608001516001600160a01b03161415611af557506001545b6000876001600160a01b03166359c8b7dd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b599190615a7f565b90506000858560010154611b6d919061582c565b905060006103e8611b7e858461582c565b611b889190615aa3565b905060006103e8611b9d61ffff86168561582c565b611ba79190615aa3565b9050600081611bb684866158e7565b611bc091906158e7565b6040516323b872dd60e01b81529091506001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca716906323b872dd90611c139033903090889060040161584b565b6020604051808303816000875af1158015611c32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c56919061586f565b506040516323b872dd60e01b81526001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca716906323b872dd90611ca79033908e90869060040161584b565b6020604051808303816000875af1158015611cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cea919061586f565b508115611d895760808701516040516323b872dd60e01b81526001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca716916323b872dd91611d44913391879060040161584b565b6020604051808303816000875af1158015611d63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d87919061586f565b505b8b6001600160a01b031663f242432a8b338e8d6040518563ffffffff1660e01b8152600401611dbb9493929190615ac5565b600060405180830381600087803b158015611dd557600080fd5b505af1158015611de9573d6000803e3d6000fd5b5050505088886002016000828254611e0191906158e7565b90915550506002880154611ee257600a60008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008c815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020600080820160006101000a8154906001600160a01b030219169055600182016000905560028201600090556003820160006101000a81549060ff0219169055600482016000905550508a8c6001600160a01b0316600080516020615bd48339815191528c604051611ed99190615b2b565b60405180910390a35b8a8c6001600160a01b03167f85d6aff492354cbf7fdd7efb2bd8bce059037aef73b968f95d32a417598cbff98c338c600101548e604051611f269493929190615891565b60405180910390a350505050505050506118e06001600055565b6003546001600160a01b03163314611f9a5760405162461bcd60e51b815260206004820152601960248201527f4f6e6c7920666163746f72792063616e20726567697374657200000000000000604482015260640161084f565b6001600160a01b038116611ff05760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6c6c656374696f6e2061646472657373000000000000604482015260640161084f565b6001600160a01b0381166000908152600b602052604090205460ff161561204e5760405162461bcd60e51b8152602060048201526012602482015271105b1c9958591e481c9959da5cdd195c995960721b604482015260640161084f565b6001600160a01b0381166000818152600b60209081526040808320805460ff19166001179055600480548452600c909252822080546001600160a01b031916909317909255815491906120a083615811565b90915550506040516001600160a01b038216907ffb99393fd31547f4a765604f2c2d122ce8ccb313edeef8b951130d8bcca866e990600090a250565b60606004548311156121215760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a59081bd9999cd95d60921b604482015260640161084f565b60008360045461213191906158e7565b90508281111561213e5750815b8067ffffffffffffffff811115612157576121576154a9565b604051908082528060200260200182016040528015612180578160200160208202803683370190505b50915060005b818110156121fa57600c600061219c8388615b5f565b815260200190815260200160002060009054906101000a90046001600160a01b03168382815181106121d0576121d06158fe565b6001600160a01b0390921660209283029190910190910152806121f281615811565b915050612186565b505092915050565b60008061223b6040805160c08101825260008082526020820181905291810182905260608101829052608081018290529060a082015290565b6000848152601260205260409020546001600160a01b03169250826122725760405162461bcd60e51b815260040161084f90615b77565b6000848152601360209081526040808320546001600160a01b038088168552601084528285208286528452828520898652845293829020825160c081018452815486168152600182015490951693850193909352600283015491840191909152600380830154606085015260048301546080850152600583015491955060a084019160ff1690811115612307576123076151e3565b6003811115612318576123186151e3565b90525090505b9193909250565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526001600160a01b038085166000908152600a6020908152604080832087845282528083208685168452825291829020825160a08101845281549094168452600180820154928501929092526002810154928401929092526003820154606084019160ff909116908111156123c6576123c66151e3565b60018111156123d7576123d76151e3565b815260200160048201548152505090505b9392505050565b6123f7613d3f565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca76001600160a01b0316906370a0823190602401602060405180830381865afa15801561245e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061248291906157e2565b905080156115b6577f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca76001600160a01b031663a9059cbb6124c1613684565b836040518363ffffffff1660e01b81526004016124df9291906157c9565b6020604051808303816000875af11580156124fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612522919061586f565b5050565b61252e613d71565b6000828152600d60205260408120906008820154600160a01b900460ff16600281111561255d5761255d6151e3565b1461257a5760405162461bcd60e51b815260040161084f90615914565b80600501544211156125be5760405162461bcd60e51b815260206004820152600d60248201526c105d58dd1a5bdb88195b991959609a1b604482015260640161084f565b806003015481600201546125d29190615b5f565b82101561260f5760405162461bcd60e51b815260206004820152600b60248201526a42696420746f6f206c6f7760a81b604482015260640161084f565b60095442826005015461262291906158e7565b11612671576009546126349042615b5f565b6005820181905560405190815283907f6e912a3a9105bdd2af817ba5adc14e6c127c1035b5b648faa29ca0d58ab8ff4e9060200160405180910390a25b60088101546000848152600e602090815260408083206001600160a01b039094168084529390915290205481156127355760405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca7169063a9059cbb906126f090859085906004016157c9565b6020604051808303816000875af115801561270f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612733919061586f565b505b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca716906323b872dd906127859033903090899060040161584b565b6020604051808303816000875af11580156127a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127c8919061586f565b6128065760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161084f565b6008830180546001600160a01b03191633908117909155600284018590556000868152600e60209081526040808320848452825291829020879055905186815287917f0e54eff26401bf69b81b26f60bd85ef47f5d85275c1d268d84f68d6897431c47910160405180910390a35050506125226001600055565b612888613d71565b6001600160a01b038083166000908152600a60209081526040808320858452825280832033808552925290912080549092161480156128cb575060008160020154115b61290b5760405162461bcd60e51b81526020600482015260116024820152704e6f20616374697665206c697374696e6760781b604482015260640161084f565b6001600382015460ff166001811115612926576129266151e3565b1415612a7a5760048101546000908152600d60205260408120906008820154600160a01b900460ff166002811115612960576129606151e3565b1461297d5760405162461bcd60e51b815260040161084f90615914565b60088101546001600160a01b0316156129ce5760405162461bcd60e51b8152602060048201526013602482015272109a591cc8185b1c9958591e481c1b1858d959606a1b604482015260640161084f565b60088101805460ff60a01b1916600160a11b1790556002820154604051637921219560e11b81526001600160a01b0386169163f242432a91612a1891309133918991600401615ac5565b600060405180830381600087803b158015612a3257600080fd5b505af1158015612a46573d6000803e3d6000fd5b5050505060048201546040517f2809c7e17bf978fbc7194c0a694b638c4215e9140cacc6c38ca36010b45697df90600090a2505b6001600160a01b0383166000818152600a6020908152604080832086845282528083203380855290835281842080546001600160a01b0319168155600181018590556002810185905560038101805460ff19169055600401939093558051928352908201819052601190820152702922a6a7ab22a22fa12cafa9a2a62622a960791b6060820152839190600080516020615bd48339815191529060800160405180910390a3506125226001600055565b612b32613d3f565b612b3c6000613dcb565b565b606060006115cd6000808787876001613c98565b6000612b5c613d71565b612b6a878787878787613e3c565b60058054906000612b7a83615811565b9091555050600554612b8f888888888561418a565b612b9e8189898989898961428b565b9050612baa6001600055565b9695505050505050565b612bbc613d71565b80612bf75760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b604482015260640161084f565b60005b818110156133a05736838383818110612c1557612c156158fe565b608002919091019150600b90506000612c316020840184614f90565b6001600160a01b0316815260208101919091526040016000205460ff16612c6a5760405162461bcd60e51b815260040161084f90615768565b6000600a81612c7c6020850185614f90565b6001600160a01b03166001600160a01b031681526020019081526020016000206000836020013581526020019081526020016000206000836040016020810190612cc69190614f90565b6001600160a01b03166001600160a01b031681526020019081526020016000209050816040016020810190612cfb9190614f90565b81546001600160a01b039081169116148015612d1b575060008160020154115b612d595760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206c697374696e6760881b604482015260640161084f565b6000600382015460ff166001811115612d7457612d746151e3565b14612dbd5760405162461bcd60e51b81526020600482015260196024820152784e6f742061206669786564207072696365206c697374696e6760381b604482015260640161084f565b816060013581600201541015612e0d5760405162461bcd60e51b8152602060048201526015602482015274496e73756666696369656e74207175616e7469747960581b604482015260640161084f565b6000612e1c6020840184614f90565b604051637d4cd84760e01b8152602085013560048201526001600160a01b039190911690637d4cd84790602401600060405180830381865afa158015612e66573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e8e91908101906159af565b600254909150612ea46060850160408601614f90565b6001600160a01b031682608001516001600160a01b03161415612ec657506001545b6000612ed56020860186614f90565b6001600160a01b03166359c8b7dd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f369190615a7f565b9050600085606001358560010154612f4e919061582c565b905060006103e8612f5f858461582c565b612f699190615aa3565b905060006103e8612f7e61ffff86168561582c565b612f889190615aa3565b9050600081612f9784866158e7565b612fa191906158e7565b6040516323b872dd60e01b81529091506001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca716906323b872dd90612ff49033903090889060040161584b565b6020604051808303816000875af1158015613013573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613037919061586f565b506001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca7166323b872dd3361307860608d0160408e01614f90565b846040518463ffffffff1660e01b81526004016130979392919061584b565b6020604051808303816000875af11580156130b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130da919061586f565b5081156131795760808701516040516323b872dd60e01b81526001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca716916323b872dd91613134913391879060040161584b565b6020604051808303816000875af1158015613153573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613177919061586f565b505b61318660208a018a614f90565b6001600160a01b031663f242432a6131a460608c0160408d01614f90565b338c602001358d606001356040518563ffffffff1660e01b81526004016131ce9493929190615ac5565b600060405180830381600087803b1580156131e857600080fd5b505af11580156131fc573d6000803e3d6000fd5b50505050886060013588600201600082825461321891906158e7565b9091555050600288015461331657600a600061323760208c018c614f90565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008a60200135815260200190815260200160002060008a60400160208101906132819190614f90565b6001600160a01b03168152602080820192909252604001600090812080546001600160a01b0319168155600181018290556002810182905560038101805460ff191690556004015589018035906132d8908b614f90565b6001600160a01b0316600080516020615bd483398151915261330060608d0160408e01614f90565b60405161330d9190615b2b565b60405180910390a35b60208901803590613327908b614f90565b6001600160a01b03167f85d6aff492354cbf7fdd7efb2bd8bce059037aef73b968f95d32a417598cbff961336160608d0160408e01614f90565b338c600101548e6060013560405161337c9493929190615891565b60405180910390a3505050505050505050808061339890615811565b915050612bfa565b506125226001600055565b6133b3613d3f565b600081116133f65760405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081a5b9d195c9d985b60821b604482015260640161084f565b60098190556040518181527f70d2c25f438b055a840aa5b6a9c16e5555b10f0b947ac750dbd16ecefd55e78f90602001610890565b613433613d71565b6000818152601260209081526040808320546013909252909120546001600160a01b0390911690816134775760405162461bcd60e51b815260040161084f90615b77565b6001600160a01b03821660009081526010602090815260408083208484528252808320868452909152812090600582015460ff1660038111156134bc576134bc6151e3565b146134d95760405162461bcd60e51b815260040161084f90615ba5565b604051627eeac760e11b81526000906001600160a01b0385169062fdd58e9061350890339087906004016157c9565b602060405180830381865afa158015613525573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061354991906157e2565b116135885760405162461bcd60e51b815260206004820152600f60248201526e2737ba103a37b5b2b71037bbb732b960891b604482015260640161084f565b6005810180546002919060ff191660018302179055508054600382015460028301546001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca781169363a9059cbb939116916135e9919061582c565b6040518363ffffffff1660e01b81526004016136069291906157c9565b6020604051808303816000875af1158015613625573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613649919061586f565b50604051339085907f1b15bc319d6f29dd5bcf76cd2b89490ed2fe49f1a31fb6b8624b0029fd85c26590600090a35050506115b66001600055565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6136ba613d71565b6000818152600d60205260408120906008820154600160a01b900460ff1660028111156136e9576136e96151e3565b146137065760405162461bcd60e51b815260040161084f90615914565b80546001600160a01b0316331461374c5760405162461bcd60e51b815260206004820152600a6024820152692737ba1039b2b63632b960b11b604482015260640161084f565b60088101546001600160a01b03161561379d5760405162461bcd60e51b8152602060048201526013602482015272109a591cc8185b1c9958591e481c1b1858d959606a1b604482015260640161084f565b60088101805460ff60a01b1916600160a11b1790556000828152600f602052604090819020548254600684015460078501549351637921219560e11b81526001600160a01b0393841694859463f242432a9461380494309492909116929091600401615ac5565b600060405180830381600087803b15801561381e57600080fd5b505af1158015613832573d6000803e3d6000fd5b505050506001600160a01b038181166000818152600a602090815260408083206006880180548552908352818420885487168552835281842080546001600160a01b0319168155600181018590556002810185905560038101805460ff19169055600401939093559154865483519516855290840182905260118483015270105550d51253d397d0d05390d153131151607a1b606085015290519092600080516020615bd4833981519152919081900360800190a360405183907f2809c7e17bf978fbc7194c0a694b638c4215e9140cacc6c38ca36010b45697df90600090a250506115b66001600055565b613926613d3f565b6001600160a01b03811661397c5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420666163746f72792061646472657373000000000000000000604482015260640161084f565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6139a6613d71565b60008060006139b4846144bc565b6040805160c08101825282546001600160a01b03908116825260018401541660208201526002830154918101919091526003808301546060830152600483015460808301526005830154949750929550909350600092613a4992879287929091879160a084019160ff90911690811115613a3057613a306151e3565b6003811115613a4157613a416151e3565b9052506145b4565b9050613a5b8484846003015484614653565b613a6784848488614865565b505050506115b66001600055565b613a7d613d71565b6000818152601260209081526040808320546013909252909120546001600160a01b039091169081613ac15760405162461bcd60e51b815260040161084f90615b77565b6001600160a01b0380831660009081526010602090815260408083208584528252808320878452909152902080549091163314613b345760405162461bcd60e51b81526020600482015260116024820152702737ba1037b33332b91031b932b0ba37b960791b604482015260640161084f565b6000600582015460ff166003811115613b4f57613b4f6151e3565b14613b6c5760405162461bcd60e51b815260040161084f90615ba5565b60058101805460ff1916600390811790915581015460028201546001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca7169163a9059cbb913391613bc29161582c565b6040518363ffffffff1660e01b8152600401613bdf9291906157c9565b6020604051808303816000875af1158015613bfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c22919061586f565b50604051339085907f1f51377b3e685a0e2419f9bb4ba7c07ec54936353ba3d0fb3c6538dab676622290600090a35050506115b66001600055565b613c65613d3f565b6001600160a01b038116613c8f57604051631e4fbdf760e01b81526000600482015260240161084f565b6115b681613dcb565b606060008060405180608001604052808a6001600160a01b03168152602001898152602001886001600160a01b031681526020018560ff1681525090506000613ce2888684614c67565b90506000613cf08284614ce6565b9050801580613cff5750808810155b15613d1f5760408051600081526020810190915294509250613d34915050565b613d2c82848a8a85614d48565b945094505050505b965096945050505050565b33613d48613684565b6001600160a01b031614612b3c5760405163118cdaa760e01b815233600482015260240161084f565b60026000541415613dc45760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161084f565b6002600055565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6001600160a01b0386166000908152600b602052604090205460ff16613e745760405162461bcd60e51b815260040161084f90615768565b60008411613e945760405162461bcd60e51b815260040161084f9061579f565b60008311613eda5760405162461bcd60e51b8152602060048201526013602482015272496e76616c696420737461727420707269636560681b604482015260640161084f565b60008211613f2a5760405162461bcd60e51b815260206004820152601960248201527f496e76616c6964206d696e2062696420696e6372656d656e7400000000000000604482015260640161084f565b6007548110158015613f3e57506008548111155b613f7d5760405162461bcd60e51b815260206004820152601060248201526f24b73b30b634b210323ab930ba34b7b760811b604482015260640161084f565b604051627eeac760e11b815284906001600160a01b0388169062fdd58e90613fab9033908a906004016157c9565b602060405180830381865afa158015613fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fec91906157e2565b101561400a5760405162461bcd60e51b815260040161084f90615afd565b60405163e985e9c560e01b81523360048201523060248201526001600160a01b0387169063e985e9c590604401602060405180830381865afa158015614054573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614078919061586f565b6140b35760405162461bcd60e51b815260206004820152600c60248201526b139bdd08185c1c1c9bdd995960a21b604482015260640161084f565b6001600160a01b0386166000908152600a60209081526040808320888452825280832033845290915290206002810154158061414457506001600382015460ff166001811115614105576141056151e3565b1480156141445750600060048201546000908152600d6020526040902060080154600160a01b900460ff166002811115614141576141416151e3565b14155b6141815760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e481b1a5cdd195960921b604482015260640161084f565b50505050505050565b6040805160a081018252338082526020808301868152838501888152600160608601818152608087018990526001600160a01b038d81166000908152600a87528981208e825287528981209781529690955296909420855181546001600160a01b031916941693909317835590518284015551600282015592516003840180549394939192909160ff1916908381811115614227576142276151e3565b02179055506080820151816004015590505083856001600160a01b03167f97e6d0949163c71f57f0ac35f319e1895a30454cba82cfe6b940b9862cc0dbdd33858760018760405161427c9594939291906153ad565b60405180910390a35050505050565b4260006142988383615b5f565b9050604051806101400160405280336001600160a01b0316815260200186815260200186815260200185815260200183815260200182815260200188815260200187815260200160006001600160a01b0316815260200160006002811115614302576143026151e3565b905260008a8152600d6020908152604091829020835181546001600160a01b03199081166001600160a01b0392831617835592850151600183015592840151600280830191909155606085015160038301556080850151600483015560a0850151600583015560c0850151600683015560e08501516007830155610100850151600883018054948516919095169081178555610120860151929492936001600160a81b0319161790600160a01b9084908111156143c1576143c16151e3565b021790555050506000898152600f60205260409081902080546001600160a01b0319166001600160a01b038b169081179091559051637921219560e11b815263f242432a9061441a90339030908c908c90600401615ac5565b600060405180830381600087803b15801561443457600080fd5b505af1158015614448573d6000803e3d6000fd5b50506040805133815260208101899052908101879052606081018590526080810184905260a081018990528992506001600160a01b038b1691508b907f2a7e6a41d497de122134820d2f68c4e648c60cf6f4a1ecb9cd1c3cf37384589f9060c00160405180910390a4505050505050505050565b6000818152601260205260408120546001600160a01b03169080826144f35760405162461bcd60e51b815260040161084f90615b77565b50506000828152601360209081526040808320546001600160a01b038516845260108352818420818552835281842086855290925282209091600582015460ff166003811115614545576145456151e3565b146145625760405162461bcd60e51b815260040161084f90615ba5565b60018101546001600160a01b0316331461231e5760405162461bcd60e51b8152602060048201526013602482015272139bdd081bd999995c881c9958da5c1a595b9d606a1b604482015260640161084f565b600080846001600160a01b031662fdd58e33866040518363ffffffff1660e01b81526004016145e49291906157c9565b602060405180830381865afa158015614601573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061462591906157e2565b9050826060015181101561464b5760405162461bcd60e51b815260040161084f90615afd565b949350505050565b6001600160a01b0384166000908152600a60209081526040808320868452825280832033845290915290206001600382015460ff166001811115614699576146996151e3565b141561471957600060048201546000908152600d6020526040902060080154600160a01b900460ff1660028111156146d3576146d36151e3565b14156147195760405162461bcd60e51b81526020600482015260156024820152744163746976652061756374696f6e2065786973747360581b604482015260640161084f565b6002810154600061472a82856158e7565b905060008582101561473c578161473e565b855b9050600061474c82886158e7565b9050801561485a5783811415614802576001600160a01b0389166000818152600a602090815260408083208c845282528083203380855290835281842080546001600160a01b0319168155600181018590556002810185905560038101805460ff19169055600401939093558051928352908201819052600d908201526c5a45524f5f5155414e5449545960981b6060820152899190600080516020615bd48339815191529060800160405180910390a361485a565b61480c81856158e7565b6002860181905560405189916001600160a01b038c16917f36dba6da50cf7eb05d1a346c00f785d8a335ca42221245492e6e243624ce71fb91614851913391906157c9565b60405180910390a35b505050505050505050565b60405163e985e9c560e01b81523360048201523060248201526001600160a01b0385169063e985e9c590604401602060405180830381865afa1580156148af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148d3919061586f565b61490e5760405162461bcd60e51b815260206004820152600c60248201526b139bdd08185c1c1c9bdd995960a21b604482015260640161084f565b604051637d4cd84760e01b8152600481018490526000906001600160a01b03861690637d4cd84790602401600060405180830381865afa158015614956573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261497e91908101906159af565b6002546080820151919250906001600160a01b031633141561499f57506001545b6000866001600160a01b03166359c8b7dd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156149df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a039190615a7f565b9050600085600301548660020154614a1b919061582c565b905060006103e8614a2c858461582c565b614a369190615aa3565b905060006103e8614a4b61ffff86168561582c565b614a559190615aa3565b9050600081614a6484866158e7565b614a6e91906158e7565b90508a6001600160a01b031663f242432a338b60000160009054906101000a90046001600160a01b03168d8d600301546040518563ffffffff1660e01b8152600401614abd9493929190615ac5565b600060405180830381600087803b158015614ad757600080fd5b505af1158015614aeb573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca716925063a9059cbb9150614b3d90339085906004016157c9565b6020604051808303816000875af1158015614b5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b80919061586f565b508115614c1e57608087015160405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000ad3e1f40ffe9318cd7b83b42d01a8c72fcbb8ca7169163a9059cbb91614bd9919086906004016157c9565b6020604051808303816000875af1158015614bf8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c1c919061586f565b505b60058901805460ff19166001179055604051339089907fa7a40af5a1d0c10a3eb94af90cb008170915e8a71a6aaff052794cd762c72fc090600090a35050505050505050505050565b600060ff8316614c9e575080516001600160a01b0316600090815260156020908152604080832082850151845290915290206123e8565b8260ff1660011415614cc857506001600160a01b03831660009081526014602052604090206123e8565b506001600160a01b03831660009081526011602052604090206123e8565b60008060005b8454811015614d4057614d1b858281548110614d0a57614d0a6158fe565b906000526020600020015485614e5e565b15614d2e5781614d2a81615811565b9250505b80614d3881615811565b915050614cec565b509392505050565b6060600080614d5786856158e7565b905084811115614d645750835b8067ffffffffffffffff811115614d7d57614d7d6154a9565b604051908082528060200260200182016040528015614da6578160200160208202803683370190505b50925060008060005b8a5481108015614dbe57508383105b15614e4d5760008b8281548110614dd757614dd76158fe565b90600052602060002001549050614dee818c614e5e565b15614e395789831015614e0e5782614e0581615811565b93505050614e3b565b808785614e1a81615811565b965081518110614e2c57614e2c6158fe565b6020026020010181815250505b505b80614e4581615811565b915050614daf565b508593505050509550959350505050565b60008281526012602090815260408083205460138352818420546001600160a01b03909116808552601084528285208286528452828520878652909352908320606085015160ff16614ef85784516001600160a01b038481169116148015614ec95750846020015182145b8015614eee575060005b600582015460ff166003811115614eec57614eec6151e3565b145b93505050506107e3565b846060015160ff1660011415614f2e57604085015160018201546001600160a01b039081169116148015614eee57506000614ed3565b604085015181546001600160a01b039081169116148015614eee57506000614ed3565b600060208284031215614f6357600080fd5b81356001600160e01b0319811681146123e857600080fd5b6001600160a01b03811681146115b657600080fd5b600060208284031215614fa257600080fd5b81356123e881614f7b565b60008060008060808587031215614fc357600080fd5b8435614fce81614f7b565b966020860135965060408601359560600135945092505050565b604080825283519082018190526000906020906060840190828701845b8281101561502157815184529284019290840190600101615005565b50505092019290925292915050565b60006020828403121561504257600080fd5b5035919050565b600080600080600060a0868803121561506157600080fd5b853561506c81614f7b565b945060208601359350604086013561508381614f7b565b94979396509394606081013594506080013592915050565b6000806000606084860312156150b057600080fd5b83356150bb81614f7b565b95602085013595506040909401359392505050565b600081518084526020808501945080840160005b838110156151095781516001600160a01b0316875295820195908201906001016150e4565b509495945050505050565b60408152600061512760408301856150d0565b90508260208301529392505050565b6000806040838503121561514957600080fd5b82359150602083013561515b81614f7b565b809150509250929050565b6000806000806080858703121561517c57600080fd5b843561518781614f7b565b935060208501359250604085013561519e81614f7b565b9396929550929360600135925050565b600080604083850312156151c157600080fd5b50508035926020909101359150565b6020815260006123e860208301846150d0565b634e487b7160e01b600052602160045260246000fd5b60048110615209576152096151e3565b9052565b60006101008201905060018060a01b0380861683528460208401528084511660408401528060208501511660608401525060408301516080830152606083015160a0830152608083015160c083015260a083015161526e60e08401826151f9565b50949350505050565b60008060006060848603121561528c57600080fd5b833561529781614f7b565b92506020840135915060408401356152ae81614f7b565b809150509250925092565b60028110615209576152096151e3565b81516001600160a01b03168152602080830151908201526040808301519082015260608083015160a0830191615301908401826152b9565b50608092830151919092015290565b6001600160a01b038b81168252602082018b9052604082018a9052606082018990526080820188905260a0820187905260c0820186905260e08201859052831661010082015261014081016003831061536b5761536b6151e3565b826101208301529b9a5050505050505050505050565b6000806040838503121561539457600080fd5b823561539f81614f7b565b946020939093013593505050565b6001600160a01b0386168152602081018590526040810184905260a081016153d860608301856152b9565b8260808301529695505050505050565b60008060008060008060c0878903121561540157600080fd5b863561540c81614f7b565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b6000806020838503121561544757600080fd5b823567ffffffffffffffff8082111561545f57600080fd5b818501915085601f83011261547357600080fd5b81358181111561548257600080fd5b8660208260071b850101111561549757600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156154e2576154e26154a9565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715615511576155116154a9565b604052919050565b600082601f83011261552a57600080fd5b8135602067ffffffffffffffff821115615546576155466154a9565b8160051b6155558282016154e8565b928352848101820192828101908785111561556f57600080fd5b83870192505b8483101561558e57823582529183019190830190615575565b979650505050505050565b600067ffffffffffffffff8211156155b3576155b36154a9565b50601f01601f191660200190565b600082601f8301126155d257600080fd5b81356155e56155e082615599565b6154e8565b8181528460208386010111156155fa57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561562f57600080fd5b853561563a81614f7b565b9450602086013561564a81614f7b565b9350604086013567ffffffffffffffff8082111561566757600080fd5b61567389838a01615519565b9450606088013591508082111561568957600080fd5b61569589838a01615519565b935060808801359150808211156156ab57600080fd5b506156b8888289016155c1565b9150509295509295909350565b6001600160a01b0387811682528616602082015260408101859052606081018490526080810183905260c0810161558e60a08301846151f9565b600080600080600060a0868803121561571757600080fd5b853561572281614f7b565b9450602086013561573281614f7b565b93506040860135925060608601359150608086013567ffffffffffffffff81111561575c57600080fd5b6156b8888289016155c1565b60208082526019908201527f436f6c6c656374696f6e206e6f74207265676973746572656400000000000000604082015260600190565b60208082526010908201526f496e76616c6964207175616e7469747960801b604082015260600190565b6001600160a01b03929092168252602082015260400190565b6000602082840312156157f457600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000600019821415615825576158256157fb565b5060010190565b6000816000190483118215151615615846576158466157fb565b500290565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006020828403121561588157600080fd5b815180151581146123e857600080fd5b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b80516158c581614f7b565b919050565b6000602082840312156158dc57600080fd5b81516123e881614f7b565b6000828210156158f9576158f96157fb565b500390565b634e487b7160e01b600052603260045260246000fd5b60208082526012908201527141756374696f6e206e6f742061637469766560701b604082015260600190565b600082601f83011261595157600080fd5b815161595f6155e082615599565b8181526020858184870101111561597557600080fd5b60005b83811015615993578581018201518382018301528101615978565b838111156159a45760008285850101525b509095945050505050565b6000602082840312156159c157600080fd5b815167ffffffffffffffff808211156159d957600080fd5b9083019060a082860312156159ed57600080fd5b6159f56154bf565b825182811115615a0457600080fd5b615a1087828601615940565b825250602083015182811115615a2557600080fd5b615a3187828601615940565b602083015250604083015182811115615a4957600080fd5b615a5587828601615940565b60408301525060608301516060820152615a71608084016158ba565b608082015295945050505050565b600060208284031215615a9157600080fd5b815161ffff811681146123e857600080fd5b600082615ac057634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b602080825260149082015273496e73756666696369656e742062616c616e636560601b604082015260600190565b6001600160a01b039190911681526040602082018190526008908201526714d3d31117d3d55560c21b606082015260800190565b60008219821115615b7257615b726157fb565b500190565b60208082526014908201527313d999995c88191bd95cc81b9bdd08195e1a5cdd60621b604082015260600190565b602080825260149082015273496e76616c6964206f666665722073746174757360601b60408201526060019056fe17d654f862f895d7741bf4e3234b08875e872e59e08d21c44d35187a60cfa2a2a264697066735822122038e8d0eafbd8c404f68a0900168be87a0d969945c4a52f2d44e3d8b08582443964736f6c634300080a0033