Contract Overview
Balance:
0 ETH
ETH Value:
$0.00
My Name Tag:
Not Available
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0x474763d787dd4390f4e4efd449d6a0caf2ba9f69fc6f43fc641156c46837c9fd | 0x60806040 | 17080111 | 209 days 38 mins ago | 0xb013abd83f0bd173e9f14ce7d6e420ad711483b4 | IN | Create: AdvancedQuesting | 0 ETH | 0.026309811011 ETH |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
AdvancedQuesting
Compiler Version
v0.8.9+commit.e5eed63a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @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. * * 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 initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155ReceiverUpgradeable is IERC165Upgradeable { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155Upgradeable is IERC165Upgradeable { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol) pragma solidity ^0.8.0; import "./ERC1155ReceiverUpgradeable.sol"; import "../../../proxy/utils/Initializable.sol"; /** * Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens. * * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be * stuck. * * @dev _Available since v3.1._ */ contract ERC1155HolderUpgradeable is Initializable, ERC1155ReceiverUpgradeable { function __ERC1155Holder_init() internal onlyInitializing { } function __ERC1155Holder_init_unchained() internal onlyInitializing { } 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; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol) pragma solidity ^0.8.0; import "../IERC1155ReceiverUpgradeable.sol"; import "../../../utils/introspection/ERC165Upgradeable.sol"; import "../../../proxy/utils/Initializable.sol"; /** * @dev _Available since v3.1._ */ abstract contract ERC1155ReceiverUpgradeable is Initializable, ERC165Upgradeable, IERC1155ReceiverUpgradeable { function __ERC1155Receiver_init() internal onlyInitializing { } function __ERC1155Receiver_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) { return interfaceId == type(IERC1155ReceiverUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721ReceiverUpgradeable { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721Upgradeable is IERC165Upgradeable { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721Upgradeable.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721MetadataUpgradeable is IERC721Upgradeable { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/utils/ERC721Holder.sol) pragma solidity ^0.8.0; import "../IERC721ReceiverUpgradeable.sol"; import "../../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC721Receiver} interface. * * Accepts all token transfers. * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}. */ contract ERC721HolderUpgradeable is Initializable, IERC721ReceiverUpgradeable { function __ERC721Holder_init() internal onlyInitializing { } function __ERC721Holder_init_unchained() internal onlyInitializing { } /** * @dev See {IERC721Receiver-onERC721Received}. * * Always returns `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address, address, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC721Received.selector; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSetUpgradeable { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "./AdvancedQuestingSettings.sol"; contract AdvancedQuesting is Initializable, AdvancedQuestingSettings { using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet; function initialize() external initializer { AdvancedQuestingSettings.__AdvancedQuestingSettings_init(); } function startAdvancedQuesting(StartQuestParams[] calldata _params) external whenNotPaused contractsAreSet onlyEOA { require(_params.length > 0, "No start quest params given"); for(uint256 i = 0; i < _params.length; i++) { _startAdvancedQuesting(_params[i], false); } } function _startAdvancedQuesting(StartQuestParams memory _startQuestParams, bool _isRestarting) private { uint256 _legionId = _startQuestParams.legionId; require(!isLegionQuesting(_legionId), "Legion is already questing"); require(isValidZone(_startQuestParams.zoneName), "Invalid zone"); uint256 _numberOfParts = zoneNameToInfo[_startQuestParams.zoneName].parts.length; require(_startQuestParams.advanceToPart > 0 && _startQuestParams.advanceToPart <= _numberOfParts, "Invalid advance to part"); LegionMetadata memory _legionMetadata = legionMetadataStore.metadataForLegion(_legionId); require(_legionMetadata.legionGeneration != LegionGeneration.RECRUIT, "Recruit cannot advanced quest"); bool _willPlayTreasureTriad = false; // Need to check that they have the correct level to advance through the given parts of the quest. for(uint256 i = 0; i < _startQuestParams.advanceToPart; i++) { uint8 _levelRequirement = zoneNameToInfo[_startQuestParams.zoneName].parts[i].questingLevelRequirement; require(_legionMetadata.questLevel >= _levelRequirement, "Legion not high enough questing level"); bool _treasureTriadOnThisPart = zoneNameToInfo[_startQuestParams.zoneName].parts[i].playTreasureTriad; _willPlayTreasureTriad = _willPlayTreasureTriad || _treasureTriadOnThisPart; // Also, if a part has a treasure triad game and it is not the last part, they cannot auto advance past it. if(i < _startQuestParams.advanceToPart - 1 && _treasureTriadOnThisPart) { revert("Cannot advanced past a part that requires treasure triad"); } } require(_startQuestParams.treasureIds.length == _startQuestParams.treasureAmounts.length, "Bad treasure lengths"); require(!_willPlayTreasureTriad || _startQuestParams.treasureIds.length > 0, "Need treasure to play treasure triad"); uint256 _totalTreasureAmounts = 0; uint8 _maxConstellationRank = _maxConstellationRankForLegionAndZone(_startQuestParams.zoneName, _legionMetadata); for(uint256 i = 0; i < _startQuestParams.treasureIds.length; i++) { require(_startQuestParams.treasureIds[i] > 0 && _startQuestParams.treasureAmounts[i] > 0, "Bad treasure id or amount"); _totalTreasureAmounts += _startQuestParams.treasureAmounts[i]; require(_totalTreasureAmounts <= _maxConstellationRank, "Too many treasures for constellation rank"); } uint256 _requestId = randomizer.requestRandomNumber(); legionIdToLegionQuestingInfoV2[_legionId].startTime = uint120(block.timestamp); legionIdToLegionQuestingInfoV2[_legionId].requestId = uint80(_requestId); legionIdToLegionQuestingInfoV2[_legionId].zoneName = _startQuestParams.zoneName; legionIdToLegionQuestingInfoV2[_legionId].owner = msg.sender; legionIdToLegionQuestingInfoV2[_legionId].advanceToPart = _startQuestParams.advanceToPart; legionIdToLegionQuestingInfoV2[_legionId].currentPart = 0; delete legionIdToLegionQuestingInfoV2[_legionId].timeTriadWasPlayed; delete legionIdToLegionQuestingInfoV2[_legionId].corruptedCellsRemainingForCurrentPart; delete legionIdToLegionQuestingInfoV2[_legionId].cardsFlipped; _saveStakedTreasures(_startQuestParams); if(!_isRestarting) { // Transfer legion and treasure to this contract. legion.adminSafeTransferFrom(msg.sender, address(this), _legionId); } if(!_isRestarting && _startQuestParams.treasureIds.length > 0) { treasure.safeBatchTransferFrom( msg.sender, address(this), _startQuestParams.treasureIds, _startQuestParams.treasureAmounts, ""); } emit AdvancedQuestStarted( msg.sender, _requestId, _startQuestParams); } function _saveStakedTreasures( StartQuestParams memory _startQuestParams) private { Treasures memory _treasures; uint256 _numberOfTreasures = _startQuestParams.treasureIds.length; _treasures.numberOfTypesOfTreasures = uint8(_numberOfTreasures); if(_numberOfTreasures > 0) { _treasures.treasure1Id = uint16(_startQuestParams.treasureIds[0]); _treasures.treasure1Amount = uint8(_startQuestParams.treasureAmounts[0]); } if(_numberOfTreasures > 1) { _treasures.treasure2Id = uint16(_startQuestParams.treasureIds[1]); _treasures.treasure2Amount = uint8(_startQuestParams.treasureAmounts[1]); } if(_numberOfTreasures > 2) { _treasures.treasure3Id = uint16(_startQuestParams.treasureIds[2]); _treasures.treasure3Amount = uint8(_startQuestParams.treasureAmounts[2]); } if(_numberOfTreasures > 3) { _treasures.treasure4Id = uint16(_startQuestParams.treasureIds[3]); _treasures.treasure4Amount = uint8(_startQuestParams.treasureAmounts[3]); } if(_numberOfTreasures > 4) { _treasures.treasure5Id = uint16(_startQuestParams.treasureIds[4]); _treasures.treasure5Amount = uint8(_startQuestParams.treasureAmounts[4]); } if(_numberOfTreasures > 5) { _treasures.treasure6Id = uint16(_startQuestParams.treasureIds[5]); _treasures.treasure6Amount = uint8(_startQuestParams.treasureAmounts[5]); } if(_numberOfTreasures > 6) { _treasures.treasure7Id = uint16(_startQuestParams.treasureIds[6]); _treasures.treasure7Amount = uint8(_startQuestParams.treasureAmounts[6]); } for(uint256 i = 0; i < _numberOfTreasures; i++) { for(uint256 j = i + 1; j < _numberOfTreasures; j++) { require(_startQuestParams.treasureIds[i] != _startQuestParams.treasureIds[j], "Duplicate treasure id in array"); } } legionIdToLegionQuestingInfoV2[_startQuestParams.legionId].treasures = _treasures; } function continueAdvancedQuesting(uint256[] calldata _legionIds) external whenNotPaused contractsAreSet onlyEOA nonZeroLength(_legionIds) { for(uint256 i = 0; i < _legionIds.length; i++) { _continueAdvancedQuesting(_legionIds[i]); } } function _continueAdvancedQuesting(uint256 _legionId) private { bool _usingOldSchema = _isUsingOldSchema(_legionId); string memory _zoneName = _activeZoneForLegion(_usingOldSchema, _legionId); LegionMetadata memory _legionMetadata = legionMetadataStore.metadataForLegion(_legionId); ZoneInfo storage _zoneInfo = zoneNameToInfo[_zoneName]; require(_ownerForLegion(_usingOldSchema, _legionId) == msg.sender, "Legion is not yours"); uint256 _randomNumber = randomizer.revealRandomNumber(_requestIdForLegion(_usingOldSchema, _legionId)); _ensureDoneWithCurrentPart(_legionId, _zoneName, _usingOldSchema, _legionMetadata, _zoneInfo, _randomNumber, true); uint8 _advanceToPart = _advanceToPartForLegion(_usingOldSchema, _legionId); // Ensure we are not continuing too far. require(_advanceToPart + 1 <= _zoneInfo.parts.length, "Already at last part"); // Check if player can even advance to part. // Using advancedToPart as index because it is the index of the next part. require(_legionMetadata.questLevel >= _zoneInfo.parts[_advanceToPart].questingLevelRequirement, "Legion not high enough questing level"); // If the next part has a triad requirement, must have treasure staked still. require(!_zoneInfo.parts[_advanceToPart].playTreasureTriad || _hasTreasuresStakedForLegion(_usingOldSchema, _legionId), "No treasure staked for legion"); // Need new number for stasis role + potentially treasure triad. uint256 _requestId = randomizer.requestRandomNumber(); if(_usingOldSchema) { legionIdToLegionQuestingInfoV1[_legionId].startTime = block.timestamp; legionIdToLegionQuestingInfoV1[_legionId].currentPart = _advanceToPart; legionIdToLegionQuestingInfoV1[_legionId].advanceToPart++; delete legionIdToLegionQuestingInfoV1[_legionId].triadOutcome; legionIdToLegionQuestingInfoV1[_legionId].requestId = _requestId; } else { legionIdToLegionQuestingInfoV2[_legionId].startTime = uint120(block.timestamp); legionIdToLegionQuestingInfoV2[_legionId].currentPart = _advanceToPart; legionIdToLegionQuestingInfoV2[_legionId].advanceToPart++; delete legionIdToLegionQuestingInfoV2[_legionId].timeTriadWasPlayed; delete legionIdToLegionQuestingInfoV2[_legionId].corruptedCellsRemainingForCurrentPart; delete legionIdToLegionQuestingInfoV2[_legionId].cardsFlipped; legionIdToLegionQuestingInfoV2[_legionId].requestId = uint80(_requestId); } emit AdvancedQuestContinued(msg.sender, _legionId, _requestId, _advanceToPart + 1); } function emergencyEndQuesting( EmergencyEndQuestingParams[] calldata _endParams) external override whenNotPaused contractsAreSet onlyAdminOrOwner { for(uint256 i = 0; i < _endParams.length; i++) { EmergencyEndQuestingParams calldata _params = _endParams[i]; uint256 _randomNumber; if(legionIdToLegionQuestingInfoV1[_params.legionId].requestId == 0) { _randomNumber = uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp, block.number))); } else { _randomNumber = randomizer.revealRandomNumber(legionIdToLegionQuestingInfoV1[_params.legionId].requestId); } LegionMetadata memory _legionMetadata = legionMetadataStore.metadataForLegion(_params.legionId); questing.processQPGainAndLevelUp(_params.legionId, _legionMetadata.questLevel, 40); ZoneInfo storage _zoneInfo = zoneNameToInfo[_params.zone]; AdvancedQuestReward[] memory _earnedRewards = _distributeRewards( _params.zone, 2, _zoneInfo.parts[2], // Give them the rewards for the last part _legionMetadata, _params.owner, _randomNumber, 3 ); // Send back legion and treasure. Ensure to send it to the owner, not the msg.sender. legion.adminSafeTransferFrom(address(this), _params.owner, _params.legionId); if(_params.treasureIds.length > 0) { treasure.safeBatchTransferFrom( address(this), _params.owner, _params.treasureIds, _params.treasureAmounts, ""); } delete legionIdToLegionQuestingInfoV1[_params.legionId].startTime; delete legionIdToLegionQuestingInfoV2[_params.legionId].startTime; // This will fix Subgraphs state, instead of being stuck forever. emit AdvancedQuestEnded(_params.owner, _params.legionId, _earnedRewards); } } // Ends questing at the current part. Must have played triad if triad is required on current part. function endQuesting( uint256[] calldata _legionIds, bool[] calldata _restartQuesting) external whenNotPaused contractsAreSet onlyEOA nonZeroLength(_legionIds) { require(_legionIds.length == _restartQuesting.length, "Bad array lengths"); for(uint256 i = 0; i < _legionIds.length; i++) { _endQuesting(_legionIds[i], _restartQuesting[i]); } } function _endQuesting(uint256 _legionId, bool _restartQuesting) private { bool _usingOldSchema = _isUsingOldSchema(_legionId); string memory _zoneName = _activeZoneForLegion(_usingOldSchema, _legionId); LegionMetadata memory _legionMetadata = legionMetadataStore.metadataForLegion(_legionId); ZoneInfo storage _zoneInfo = zoneNameToInfo[_zoneName]; require(_ownerForLegion(_usingOldSchema, _legionId) == msg.sender, "Legion is not yours"); uint256 _randomNumber = randomizer.revealRandomNumber(_requestIdForLegion(_usingOldSchema, _legionId)); _ensureDoneWithCurrentPart(_legionId, _zoneName, _usingOldSchema, _legionMetadata, _zoneInfo, _randomNumber, true); _endQuestingPostValidation(_legionId, _usingOldSchema, _legionMetadata, _zoneInfo, _randomNumber, _restartQuesting); } function _endQuestingPostValidation( uint256 _legionId, bool _usingOldSchema, LegionMetadata memory _legionMetadata, ZoneInfo storage _zoneInfo, uint256 _randomNumber, bool _isRestarting) private { uint8 _endingPart = _advanceToPartForLegion(_usingOldSchema, _legionId); questing.processQPGainAndLevelUp(_legionId, _legionMetadata.questLevel, endingPartToQPGained[_endingPart]); AdvancedQuestReward[] memory _earnedRewards = _getEarnedRewards( _legionId, _usingOldSchema, _endingPart, _zoneInfo, _legionMetadata, _randomNumber); // Only need to delete the start time to save on gas. Acts as a flag if the legion is questing. // When startQuesting is called all LegionQuestingInfo fields will be overridden. if(_usingOldSchema) { delete legionIdToLegionQuestingInfoV1[_legionId].startTime; } else { delete legionIdToLegionQuestingInfoV2[_legionId].startTime; } if(!_isRestarting) { // Send back legion and treasure legion.adminSafeTransferFrom(address(this), msg.sender, _legionId); } (uint256[] memory _treasureIds, uint256[] memory _treasureAmounts) = _unstakeTreasures(_legionId, _usingOldSchema, _isRestarting); emit AdvancedQuestEnded(msg.sender, _legionId, _earnedRewards); if(_isRestarting) { _startAdvancedQuesting(StartQuestParams(_legionId, _activeZoneForLegion(_usingOldSchema, _legionId), _endingPart, _treasureIds, _treasureAmounts), _isRestarting); } } // A helper method. Was running into stack too deep errors. // Helps remove some of the local variables. Just enough to compile. function _getEarnedRewards( uint256 _legionId, bool _usingOldSchema, uint8 _endingPart, ZoneInfo storage _zoneInfo, LegionMetadata memory _legionMetadata, uint256 _randomNumber) private returns(AdvancedQuestReward[] memory) { return _distributeRewards( _activeZoneForLegion(_usingOldSchema, _legionId), _endingPart - 1, _zoneInfo.parts[_endingPart - 1], _legionMetadata, msg.sender, _randomNumber, _cardsFlippedForLegion(_usingOldSchema, _legionId) ); } function _unstakeTreasures( uint256 _legionId, bool _usingOldSchema, bool _isRestarting) private returns(uint256[] memory, uint256[] memory) { uint256[] memory _treasureIds; uint256[] memory _treasureAmounts; if(_usingOldSchema) { _treasureIds = legionIdToLegionQuestingInfoV1[_legionId].treasureIds.values(); _treasureAmounts = new uint256[](_treasureIds.length); for(uint256 i = 0; i < _treasureIds.length; i++) { // No longer need to remove these from the mapping, as it is the old schema. // _legionQuestingInfo.treasureIds.remove(_treasureIds[i]); _treasureAmounts[i] = legionIdToLegionQuestingInfoV1[_legionId].treasureIdToAmount[_treasureIds[i]]; } } else { Treasures memory _treasures = legionIdToLegionQuestingInfoV2[_legionId].treasures; uint8 _numberOfTreasureTypes = _treasures.numberOfTypesOfTreasures; _treasureIds = new uint256[](_numberOfTreasureTypes); _treasureAmounts = new uint256[](_numberOfTreasureTypes); if(_numberOfTreasureTypes > 0) { _treasureIds[0] = _treasures.treasure1Id; _treasureAmounts[0] = _treasures.treasure1Amount; } if(_numberOfTreasureTypes > 1) { _treasureIds[1] = _treasures.treasure2Id; _treasureAmounts[1] = _treasures.treasure2Amount; } if(_numberOfTreasureTypes > 2) { _treasureIds[2] = _treasures.treasure3Id; _treasureAmounts[2] = _treasures.treasure3Amount; } if(_numberOfTreasureTypes > 3) { _treasureIds[3] = _treasures.treasure4Id; _treasureAmounts[3] = _treasures.treasure4Amount; } if(_numberOfTreasureTypes > 4) { _treasureIds[4] = _treasures.treasure5Id; _treasureAmounts[4] = _treasures.treasure5Amount; } if(_numberOfTreasureTypes > 5) { _treasureIds[5] = _treasures.treasure6Id; _treasureAmounts[5] = _treasures.treasure6Amount; } if(_numberOfTreasureTypes > 6) { _treasureIds[6] = _treasures.treasure7Id; _treasureAmounts[6] = _treasures.treasure7Amount; } } if(!_isRestarting && _treasureIds.length > 0) { treasure.safeBatchTransferFrom( address(this), msg.sender, _treasureIds, _treasureAmounts, ""); } return (_treasureIds, _treasureAmounts); } function _distributeRewards( string memory _zoneName, uint256 _partIndex, ZonePart storage _endingPart, LegionMetadata memory _legionMetadata, address _owner, uint256 _randomNumber, uint8 _cardsFlipped) private returns(AdvancedQuestReward[] memory) { // The returned random number was used for stasis calculations. Scramble the number with a constant. _randomNumber = uint256(keccak256(abi.encode(_randomNumber, 17647295972771752179227871979083739911846583376458796885201641052640283607576))); uint256 _legionGeneration = uint256(_legionMetadata.legionGeneration); uint256 _legionRarity = uint256(_legionMetadata.legionRarity); // Add one to the array length for the universal lock check. // AdvancedQuestReward[] memory _earnedRewards = new AdvancedQuestReward[](_endingPart.rewards.length + 1); for(uint256 i = 0; i < _endingPart.rewards.length; i++) { ZoneReward storage _reward = _endingPart.rewards[i]; uint256 _odds = uint256(_reward.baseRateRewardOdds) + uint256(_reward.generationToRarityToBoost[_legionGeneration][_legionRarity]) + (uint256(_reward.boostPerFlippedCard) * uint256(_cardsFlipped)) + zoneNameToPartIndexToRewardIndexToQuestBoosts[_zoneName][_partIndex][i][_legionMetadata.questLevel]; bool _hitReward; if(_odds >= 255) { _hitReward = true; } else if(_odds > 0) { if(_randomNumber % 256 < _odds) { _hitReward = true; } _randomNumber >>= 8; } if(_hitReward) { ZoneRewardOption storage _zoneRewardOption = _pickRewardFromOptions(_randomNumber, _reward); _earnedRewards[i] = _mintHitReward(_zoneRewardOption, _randomNumber, _owner); _randomNumber >>= 8; } } // Check for universal lock win if(chanceUniversalLock > 0) { _randomNumber = uint256(keccak256(abi.encodePacked(_randomNumber, _randomNumber))); uint256 _result = _randomNumber % 100000; if(_result < chanceUniversalLock) { consumable.mint(_owner, 10, 1); _earnedRewards[_earnedRewards.length - 1] = AdvancedQuestReward(10, 1, 0, 0); } } return _earnedRewards; } function _mintHitReward( ZoneRewardOption storage _zoneRewardOption, uint256 _randomNumber, address _owner) private returns(AdvancedQuestReward memory _earnedReward) { if(_zoneRewardOption.consumableId > 0 && _zoneRewardOption.consumableAmount > 0) { _earnedReward.consumableId = _zoneRewardOption.consumableId; _earnedReward.consumableAmount = _zoneRewardOption.consumableAmount; consumable.mint( _owner, _zoneRewardOption.consumableId, _zoneRewardOption.consumableAmount); } if(_zoneRewardOption.treasureFragmentId > 0) { _earnedReward.treasureFragmentId = _zoneRewardOption.treasureFragmentId; treasureFragment.mint( _owner, _zoneRewardOption.treasureFragmentId, 1); } if(_zoneRewardOption.treasureTier > 0) { uint256 _treasureId = treasureMetadataStore.getRandomTreasureForTierAndCategory( _zoneRewardOption.treasureTier, _zoneRewardOption.treasureCategory, _randomNumber); _earnedReward.treasureId = _treasureId; treasure.mint( _owner, _treasureId, 1); } } function _pickRewardFromOptions( uint256 _randomNumber, ZoneReward storage _zoneReward) private view returns(ZoneRewardOption storage) { // Gas optimization. Only run random calculations for rewards with more than 1 option. if(_zoneReward.rewardOptions.length == 1) { return _zoneReward.rewardOptions[0]; } uint256 _result = _randomNumber % 256; uint256 _topRange = 0; _randomNumber >>= 8; for(uint256 j = 0; j < _zoneReward.rewardOptions.length; j++) { ZoneRewardOption storage _zoneRewardOption = _zoneReward.rewardOptions[j]; _topRange += _zoneRewardOption.rewardOdds; if(_result < _topRange) { // Got this reward! return _zoneRewardOption; } } revert("Bad odds for zone reward"); } function playTreasureTriad( PlayTreasureTriadParams[] calldata _params) external whenNotPaused contractsAreSet onlyEOA { require(_params.length > 0, "Bad array length"); for(uint256 i = 0; i < _params.length; i++) { _playTreasureTriad(_params[i].legionId, _params[i].playerMoves, _params[i].restartQuestIfPossible); } } function _playTreasureTriad(uint256 _legionId, UserMove[] calldata _playerMoves, bool _restartQuestingIfPossible) private { bool _usingOldSchema = _isUsingOldSchema(_legionId); string memory _zoneName = _activeZoneForLegion(_usingOldSchema, _legionId); LegionMetadata memory _legionMetadata = legionMetadataStore.metadataForLegion(_legionId); ZoneInfo storage _zoneInfo = zoneNameToInfo[_zoneName]; require(_ownerForLegion(_usingOldSchema, _legionId) == msg.sender, "Legion is not yours"); uint256 _randomNumber = randomizer.revealRandomNumber(_requestIdForLegion(_usingOldSchema, _legionId)); // Don't check for triad as they will be playing it right now. _ensureDoneWithCurrentPart(_legionId, _zoneName, _usingOldSchema, _legionMetadata, _zoneInfo, _randomNumber, false); _validatePlayerHasTreasuresForMoves(_playerMoves, _usingOldSchema, _legionId); GameOutcome memory _outcome = treasureTriad.generateBoardAndPlayGame( _randomNumber, _legionMetadata.legionClass, _playerMoves); // Timestamp used to verify they have played and to calculate the length of stasis post game. if(_usingOldSchema) { legionIdToLegionQuestingInfoV1[_legionId].triadOutcome.timeTriadWasPlayed = block.timestamp; legionIdToLegionQuestingInfoV1[_legionId].triadOutcome.corruptedCellsRemainingForCurrentPart = _outcome.numberOfCorruptedCardsLeft; legionIdToLegionQuestingInfoV1[_legionId].triadOutcome.cardsFlipped = _outcome.numberOfFlippedCards; } else { legionIdToLegionQuestingInfoV2[_legionId].timeTriadWasPlayed = uint120(block.timestamp); legionIdToLegionQuestingInfoV2[_legionId].corruptedCellsRemainingForCurrentPart = _outcome.numberOfCorruptedCardsLeft; legionIdToLegionQuestingInfoV2[_legionId].cardsFlipped = _outcome.numberOfFlippedCards; } emit TreasureTriadPlayed(msg.sender, _legionId, _outcome.playerWon, _outcome.numberOfFlippedCards, _outcome.numberOfCorruptedCardsLeft); // If there are any corrupted cards left, they will be stuck in stasis and cannot end now. if(_outcome.numberOfCorruptedCardsLeft == 0 || !generationToCanHaveStasis[_legionMetadata.legionGeneration]) { _endQuestingPostValidation(_legionId, _usingOldSchema, _legionMetadata, _zoneInfo, _randomNumber, _restartQuestingIfPossible); } } function _validatePlayerHasTreasuresForMoves( UserMove[] calldata _playerMoves, bool _usingOldSchema, uint256 _legionId) private view { // Before sending to the treasure triad contract, ensure they have staked the treasures and can play them. // The treasure triad contract will handle the game logic, and validating that the player moves are valid. require(_playerMoves.length > 0 && _playerMoves.length < 4, "Bad number of treasure triad moves"); // Worst case, they have 3 different treasures. Treasure[] memory _treasures = new Treasure[](_playerMoves.length); uint256 _treasureIndex = 0; for(uint256 i = 0; i < _playerMoves.length; i++) { uint256 _treasureIdForMove = _playerMoves[i].treasureId; uint256 _treasureAmountStaked = _getTreasureAmountStaked(_treasureIdForMove, _usingOldSchema, _legionId); bool _foundLocalTreasure = false; for(uint256 k = 0; k < _treasures.length; k++) { if(_treasures[k].id == _treasureIdForMove) { _foundLocalTreasure = true; if(_treasures[k].amount == 0) { revert("Used more treasure than what was staked"); } else { _treasures[k].amount--; } break; } } if(!_foundLocalTreasure) { _treasures[_treasureIndex] = Treasure(_treasureIdForMove, _treasureAmountStaked - 1); _treasureIndex++; } } } function _getTreasureAmountStaked( uint256 _treasureIdForMove, bool _usingOldSchema, uint256 _legionId) private view returns(uint256) { if(_usingOldSchema) { require(legionIdToLegionQuestingInfoV1[_legionId].treasureIds.contains(_treasureIdForMove), "Cannot play treasure that was not staked"); return legionIdToLegionQuestingInfoV1[_legionId].treasureIdToAmount[_treasureIdForMove]; } else { Treasures memory _treasures = legionIdToLegionQuestingInfoV2[_legionId].treasures; require(_treasureIdForMove > 0); if(_treasures.treasure1Id == _treasureIdForMove) { return _treasures.treasure1Amount; } else if(_treasures.treasure2Id == _treasureIdForMove) { return _treasures.treasure2Amount; } else if(_treasures.treasure3Id == _treasureIdForMove) { return _treasures.treasure3Amount; } else if(_treasures.treasure4Id == _treasureIdForMove) { return _treasures.treasure4Amount; } else if(_treasures.treasure5Id == _treasureIdForMove) { return _treasures.treasure5Amount; } else if(_treasures.treasure6Id == _treasureIdForMove) { return _treasures.treasure6Amount; } else if(_treasures.treasure7Id == _treasureIdForMove) { return _treasures.treasure7Amount; } else { revert("Cannot play treasure that was not staked"); } } } // Ensures the legion is done with the current part they are on. // This includes checking the end time and making sure they played treasure triad. function _ensureDoneWithCurrentPart( uint256 _legionId, string memory _zoneName, bool _usingOldSchema, LegionMetadata memory _legionMetadata, ZoneInfo storage _zoneInfo, uint256 _randomNumber, bool _checkPlayedTriad) private view { uint8 _maxConstellationRank = _maxConstellationRankForLegionAndZone( _zoneName, _legionMetadata); // Handles checking if the legion is questing or not. Will revert if not. // Handles checking if stasis random is ready. Will revert if not. (uint256 _endTime,) = _endTimeForLegion(_legionId, _usingOldSchema, _zoneName, _legionMetadata, _maxConstellationRank, _randomNumber); require(block.timestamp >= _endTime, "Legion has not finished this part of the zone yet"); // Triad played check. Only need to check the last part as _startAdvancedQuesting would have reverted // if they tried to skip past a triad played check. if(_checkPlayedTriad && _zoneInfo.parts[_advanceToPartForLegion(_usingOldSchema, _legionId) - 1].playTreasureTriad && _triadPlayTimeForLegion(_usingOldSchema, _legionId) == 0) { revert("Has not played treasure triad for current part"); } } function isLegionQuesting(uint256 _legionId) public view returns(bool) { return legionIdToLegionQuestingInfoV1[_legionId].startTime > 0 || legionIdToLegionQuestingInfoV2[_legionId].startTime > 0; } function _activeZoneForLegion(bool _useOldSchema, uint256 _legionId) private view returns(string storage) { return _useOldSchema ? legionIdToLegionQuestingInfoV1[_legionId].zoneName : legionIdToLegionQuestingInfoV2[_legionId].zoneName; } function _ownerForLegion(bool _useOldSchema, uint256 _legionId) private view returns(address) { return _useOldSchema ? legionIdToLegionQuestingInfoV1[_legionId].owner : legionIdToLegionQuestingInfoV2[_legionId].owner; } function _requestIdForLegion(bool _useOldSchema, uint256 _legionId) private view returns(uint256) { return _useOldSchema ? legionIdToLegionQuestingInfoV1[_legionId].requestId : legionIdToLegionQuestingInfoV2[_legionId].requestId; } function _advanceToPartForLegion(bool _useOldSchema, uint256 _legionId) private view returns(uint8) { return _useOldSchema ? legionIdToLegionQuestingInfoV1[_legionId].advanceToPart : legionIdToLegionQuestingInfoV2[_legionId].advanceToPart; } function _currentPartForLegion(bool _useOldSchema, uint256 _legionId) private view returns(uint8) { return _useOldSchema ? legionIdToLegionQuestingInfoV1[_legionId].currentPart : legionIdToLegionQuestingInfoV2[_legionId].currentPart; } function _hasTreasuresStakedForLegion(bool _useOldSchema, uint256 _legionId) private view returns(bool) { return _useOldSchema ? legionIdToLegionQuestingInfoV1[_legionId].treasureIds.length() > 0 : legionIdToLegionQuestingInfoV2[_legionId].treasures.treasure1Id > 0; } function _triadPlayTimeForLegion(bool _useOldSchema, uint256 _legionId) private view returns(uint256) { return _useOldSchema ? legionIdToLegionQuestingInfoV1[_legionId].triadOutcome.timeTriadWasPlayed : legionIdToLegionQuestingInfoV2[_legionId].timeTriadWasPlayed; } function _cardsFlippedForLegion(bool _useOldSchema, uint256 _legionId) private view returns(uint8) { return _useOldSchema ? legionIdToLegionQuestingInfoV1[_legionId].triadOutcome.cardsFlipped : legionIdToLegionQuestingInfoV2[_legionId].cardsFlipped; } function _corruptedCellsRemainingForLegion(bool _useOldSchema, uint256 _legionId) private view returns(uint8) { return _useOldSchema ? legionIdToLegionQuestingInfoV1[_legionId].triadOutcome.corruptedCellsRemainingForCurrentPart : legionIdToLegionQuestingInfoV2[_legionId].corruptedCellsRemainingForCurrentPart; } function _startTimeForLegion(bool _useOldSchema, uint256 _legionId) private view returns(uint256) { return _useOldSchema ? legionIdToLegionQuestingInfoV1[_legionId].startTime : legionIdToLegionQuestingInfoV2[_legionId].startTime; } function _isUsingOldSchema(uint256 _legionId) private view returns(bool) { return legionIdToLegionQuestingInfoV1[_legionId].startTime > 0; } // Returns the end time for the legion and the number of stasis hit in all the parts of the zone. // If the legion is waiting through stasis caused by corrupt cards in treasure triad, the second number will be the number of cards remaining. function endTimeForLegion(uint256 _legionId) external view returns(uint256, uint8) { LegionMetadata memory _legionMetadata = legionMetadataStore.metadataForLegion(_legionId); bool _usingOldSchema = _isUsingOldSchema(_legionId); uint8 _maxConstellationRank = _maxConstellationRankForLegionAndZone( _activeZoneForLegion(_usingOldSchema, _legionId), _legionMetadata); uint256 _randomNumber = randomizer.revealRandomNumber(_requestIdForLegion(_usingOldSchema, _legionId)); return _endTimeForLegion(_legionId, _usingOldSchema, _activeZoneForLegion(_usingOldSchema, _legionId), _legionMetadata, _maxConstellationRank, _randomNumber); } function _endTimeForLegion( uint256 _legionId, bool _usingOldSchema, string memory _zoneName, LegionMetadata memory _legionMetadata, uint8 _maxConstellationRank, uint256 _randomNumber) private view returns(uint256 _endTime, uint8 _stasisHitCount) { require(isLegionQuesting(_legionId), "Legion is not questing"); uint256 _triadPlayTime = _triadPlayTimeForLegion(_usingOldSchema, _legionId); uint8 _corruptCellsRemaining = _corruptedCellsRemainingForLegion(_usingOldSchema, _legionId); uint8 _advanceToPart = _advanceToPartForLegion(_usingOldSchema, _legionId); uint8 _currentPart = _currentPartForLegion(_usingOldSchema, _legionId); // If this part requires treasure triad, and the user has already played it for this part, // AND the use had a corrupted card... the end time will be based on that stasis. if(zoneNameToInfo[_zoneName].parts[_advanceToPart - 1].playTreasureTriad && _triadPlayTime > 0 && _corruptCellsRemaining > 0 && generationToCanHaveStasis[_legionMetadata.legionGeneration]) { return (_triadPlayTime + (_corruptCellsRemaining * stasisLengthForCorruptedCard), _corruptCellsRemaining); } uint256 _totalLength; (_totalLength, _stasisHitCount) = _calculateStasis( zoneNameToInfo[_zoneName], _legionMetadata, _randomNumber, _maxConstellationRank, _currentPart, _advanceToPart ); _endTime = _startTimeForLegion(_usingOldSchema, _legionId) + _totalLength; } function _calculateStasis( ZoneInfo storage _zoneInfo, LegionMetadata memory _legionMetadata, uint256 _randomNumber, uint8 _maxConstellationRank, uint8 _currentPart, uint8 _advanceToPart) private view returns(uint256 _totalLength, uint8 _stasisHitCount) { uint8 _baseRateReduction = maxConstellationRankToReductionInStasis[_maxConstellationRank]; // For example, assume currentPart is 0 and they are advancing to part 1. // We will go through this for loop once. The first time, i = 0, which is also // the index of the parts array in the ZoneInfo object. for(uint256 i = _currentPart; i < _advanceToPart; i++) { _totalLength += _zoneInfo.parts[i].zonePartLength; if(generationToCanHaveStasis[_legionMetadata.legionGeneration]) { uint8 _baseRate = _zoneInfo.parts[i].stasisBaseRate; // If not greater than, no chance of stasis! if(_baseRate > _baseRateReduction) { if(_randomNumber % 256 < _baseRate - _baseRateReduction) { _stasisHitCount++; _totalLength += _zoneInfo.parts[i].stasisLength; } _randomNumber >>= 8; } } } } function _maxConstellationRankForLegionAndZone( string memory _zoneName, LegionMetadata memory _legionMetadata) private view returns(uint8) { uint8 _rankConstellation1 = _legionMetadata.constellationRanks[uint256(zoneNameToInfo[_zoneName].constellation1)]; uint8 _rankConstellation2 = _legionMetadata.constellationRanks[uint256(zoneNameToInfo[_zoneName].constellation2)]; if(_rankConstellation1 > _rankConstellation2) { return _rankConstellation1; } else { return _rankConstellation2; } } } struct Treasure { uint256 id; uint256 amount; } struct PlayTreasureTriadParams { uint256 legionId; UserMove[] playerMoves; bool restartQuestIfPossible; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "./AdvancedQuestingState.sol"; abstract contract AdvancedQuestingContracts is Initializable, AdvancedQuestingState { function __AdvancedQuestingContracts_init() internal initializer { AdvancedQuestingState.__AdvancedQuestingState_init(); } function setContracts( address _randomizerAddress, address _questingAddress, address _legionAddress, address _legionMetadataStoreAddress, address _treasureAddress, address _consumableAddress, address _treasureMetadataStoreAddress, address _treasureTriadAddress, address _treasureFragmentAddress) external onlyAdminOrOwner { randomizer = IRandomizer(_randomizerAddress); questing = IQuesting(_questingAddress); legion = ILegion(_legionAddress); legionMetadataStore = ILegionMetadataStore(_legionMetadataStoreAddress); treasure = ITreasure(_treasureAddress); consumable = IConsumable(_consumableAddress); treasureMetadataStore = ITreasureMetadataStore(_treasureMetadataStoreAddress); treasureTriad = ITreasureTriad(_treasureTriadAddress); treasureFragment = ITreasureFragment(_treasureFragmentAddress); } modifier contractsAreSet() { require(areContractsSet(), "Contracts aren't set"); _; } function areContractsSet() public view returns(bool) { return address(randomizer) != address(0) && address(questing) != address(0) && address(legion) != address(0) && address(legionMetadataStore) != address(0) && address(treasure) != address(0) && address(consumable) != address(0) && address(treasureMetadataStore) != address(0) && address(treasureTriad) != address(0) && address(treasureFragment) != address(0); } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "./AdvancedQuestingContracts.sol"; abstract contract AdvancedQuestingSettings is Initializable, AdvancedQuestingContracts { function __AdvancedQuestingSettings_init() internal initializer { AdvancedQuestingContracts.__AdvancedQuestingContracts_init(); } function setChanceUniversalLock( uint256 _chanceUniversalLock) external onlyAdminOrOwner { chanceUniversalLock = _chanceUniversalLock; } function addZone(string calldata _zoneName, ZoneInfo calldata _zone) external onlyAdminOrOwner { require(!compareStrings(_zoneName, ""), "Zone name cannot be blank"); require(!isValidZone(_zoneName), "Zone already exists"); require(_zone.zoneStartTime > 0, "Zone must have a start time"); zoneNameToInfo[_zoneName] = _zone; } function updatePartLengthsForZone( string calldata _zoneName, uint256[] calldata _partLengths, uint256[] calldata _stasisLengths) external onlyAdminOrOwner { require(isValidZone(_zoneName), "Zone is invalid"); ZoneInfo storage _zoneInfo = zoneNameToInfo[_zoneName]; require(_partLengths.length == _zoneInfo.parts.length && _partLengths.length == _stasisLengths.length, "Bad array lengths"); for(uint256 i = 0; i < _partLengths.length; i++) { _zoneInfo.parts[i].zonePartLength = _partLengths[i]; _zoneInfo.parts[i].stasisLength = _stasisLengths[i]; } } function updateQuestLevelBoosts( string calldata _zoneName, uint256 _partIndex, uint256 _rewardIndex, uint8[7] calldata _questLevelBoosts) external onlyAdminOrOwner { require(isValidZone(_zoneName), "Zone is invalid"); ZoneInfo storage _zoneInfo = zoneNameToInfo[_zoneName]; require(_partIndex < _zoneInfo.parts.length, "Bad part index"); ZonePart storage _zonePart = _zoneInfo.parts[_partIndex]; require(_rewardIndex < _zonePart.rewards.length, "Bad reward index"); zoneNameToPartIndexToRewardIndexToQuestBoosts[_zoneName][_partIndex][_rewardIndex] = _questLevelBoosts; } function setStasisLengthForCorruptedCard(uint256 _stasisLengthForCorruptedCard) external onlyAdminOrOwner { stasisLengthForCorruptedCard = _stasisLengthForCorruptedCard; } function setEndingPartToQPGained(EndingPartParams[] calldata _endingPartParams) external onlyAdminOrOwner { for(uint256 i = 0; i < _endingPartParams.length; i++) { endingPartToQPGained[_endingPartParams[i].endingPart] = _endingPartParams[i].qpGained; emit QPForEndingPart(_endingPartParams[i].endingPart, _endingPartParams[i].qpGained); } } function isValidZone(string memory _zoneName) public view returns(bool) { return zoneNameToInfo[_zoneName].zoneStartTime > 0; } function lengthForPartOfZone(string calldata _zoneName, uint8 _partIndex) public view returns(uint256) { return zoneNameToInfo[_zoneName].parts[_partIndex].zonePartLength; } } struct EndingPartParams { uint8 endingPart; uint248 qpGained; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC721/utils/ERC721HolderUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155HolderUpgradeable.sol"; import "../../shared/randomizer/IRandomizer.sol"; import "./IAdvancedQuesting.sol"; import "../../shared/AdminableUpgradeable.sol"; import "../questing/IQuesting.sol"; import "../legion/ILegion.sol"; import "../legionmetadatastore/ILegionMetadataStore.sol"; import "../external/ITreasure.sol"; import "../consumable/IConsumable.sol"; import "../treasuremetadatastore/ITreasureMetadataStore.sol"; import "../treasuretriad/ITreasureTriad.sol"; import "../treasurefragment/ITreasureFragment.sol"; abstract contract AdvancedQuestingState is Initializable, IAdvancedQuesting, AdminableUpgradeable, ERC721HolderUpgradeable, ERC1155HolderUpgradeable { event AdvancedQuestStarted(address _owner, uint256 _requestId, StartQuestParams _startQuestParams); event AdvancedQuestContinued(address _owner, uint256 _legionId, uint256 _requestId, uint8 _toPart); event TreasureTriadPlayed(address _owner, uint256 _legionId, bool _playerWon, uint8 _numberOfCardsFlipped, uint8 _numberOfCorruptedCardsRemaining); event AdvancedQuestEnded(address _owner, uint256 _legionId, AdvancedQuestReward[] _rewards); event QPForEndingPart(uint8 _endingPart, uint256 _qpGained); // Used for event. Free to change struct AdvancedQuestReward { uint256 consumableId; uint256 consumableAmount; uint256 treasureFragmentId; // Assumed to be 1. uint256 treasureId; // Assumed to be 1. } IRandomizer public randomizer; IQuesting public questing; ILegion public legion; ILegionMetadataStore public legionMetadataStore; ITreasure public treasure; IConsumable public consumable; ITreasureMetadataStore public treasureMetadataStore; ITreasureTriad public treasureTriad; ITreasureFragment public treasureFragment; // The length of stasis per corrupted card. uint256 public stasisLengthForCorruptedCard; // The name of the zone to all of mapping(string => ZoneInfo) public zoneNameToInfo; // For a given generation, returns if they can experience stasis. mapping(LegionGeneration => bool) generationToCanHaveStasis; // The highest constellation rank for the given zone to how much the chance of stasis is reduced. // The value that is stored is out of 256, as is the probability calculation. mapping(uint8 => uint8) maxConstellationRankToReductionInStasis; mapping(uint256 => LegionQuestingInfoV1) internal legionIdToLegionQuestingInfoV1; // The optimized version of the questing info struct. // Blunder on my part for not optimizing for gas better before launch. mapping(uint256 => LegionQuestingInfoV2) internal legionIdToLegionQuestingInfoV2; // The chance of a universal lock out of 100,000. uint256 public chanceUniversalLock; // Putting this storage in ZoneInfo after the fact rekt it. A mapping will // be nice as if there are any out of bounds index, it will return 0. mapping(string => mapping(uint256 => mapping(uint256 => uint8[7]))) public zoneNameToPartIndexToRewardIndexToQuestBoosts; mapping(uint8 => uint256) public endingPartToQPGained; function __AdvancedQuestingState_init() internal initializer { AdminableUpgradeable.__Adminable_init(); ERC721HolderUpgradeable.__ERC721Holder_init(); ERC1155HolderUpgradeable.__ERC1155Holder_init(); stasisLengthForCorruptedCard = 1 days; generationToCanHaveStasis[LegionGeneration.GENESIS] = false; generationToCanHaveStasis[LegionGeneration.AUXILIARY] = true; maxConstellationRankToReductionInStasis[1] = 10; maxConstellationRankToReductionInStasis[2] = 15; maxConstellationRankToReductionInStasis[3] = 20; maxConstellationRankToReductionInStasis[4] = 23; maxConstellationRankToReductionInStasis[5] = 38; maxConstellationRankToReductionInStasis[6] = 51; maxConstellationRankToReductionInStasis[7] = 64; endingPartToQPGained[1] = 10; endingPartToQPGained[2] = 20; endingPartToQPGained[3] = 40; emit QPForEndingPart(1, 10); emit QPForEndingPart(2, 20); emit QPForEndingPart(3, 40); } } struct LegionQuestingInfoV1 { uint256 startTime; uint256 requestId; LegionTriadOutcomeV1 triadOutcome; EnumerableSetUpgradeable.UintSet treasureIds; mapping(uint256 => uint256) treasureIdToAmount; string zoneName; address owner; uint8 advanceToPart; uint8 currentPart; } struct LegionTriadOutcomeV1 { // If 0, triad has not been played for current part. uint256 timeTriadWasPlayed; // Indicates the number of corrupted cards that were left for the current part the legion is on. uint8 corruptedCellsRemainingForCurrentPart; // Number of cards flipped uint8 cardsFlipped; } struct LegionQuestingInfoV2 { // Will be 0 if not on a quest. // The time that the legion started the CURRENT part. uint120 startTime; // If 0, triad has not been played for current part. uint120 timeTriadWasPlayed; // Indicates the number of corrupted cards that were left for the current part the legion is on. uint8 corruptedCellsRemainingForCurrentPart; // Number of cards flipped uint8 cardsFlipped; // The owner of this questing. This value only should be trusted if startTime > 0 and the legion is staked here. address owner; // The current random request for the legion. // There may be multiple requests through the zone parts depending // on if they auto-advanced or not. uint80 requestId; // Indicates how far the legion wants to go automatically. uint8 advanceToPart; // Which part the legion is currently at. May be 0 if they have not made it to part 1. uint8 currentPart; // The zone they are currently at. string zoneName; // All the treasures that may be staked. Stored this way for effeciency. Treasures treasures; } struct ZoneInfo { // The time this zone becomes active. If 0, zone does not exist. uint256 zoneStartTime; TreasureCategory categoryBoost1; TreasureCategory categoryBoost2; // The constellations that are considered for this zone. Constellation constellation1; Constellation constellation2; ZonePart[] parts; } struct ZonePart { // The length of time this zone takes to complete. uint256 zonePartLength; // The length of time added to the journey if the legion gets stasis. uint256 stasisLength; // The base rate of statis for the part of the zone. Out of 256. uint8 stasisBaseRate; // The quest level minimum required to proceed to this part of the zone. uint8 questingLevelRequirement; // DEPRECATED uint8 questingXpGained; // Indicates if the user needs to play treasure triad to complete this part of the journey. bool playTreasureTriad; // The different rewards given if the user ends their adventure on this part of the zone. ZoneReward[] rewards; } struct ZoneReward { // Out of 256 (255 max). How likely this reward group will be given to the user. uint8 baseRateRewardOdds; // Certain generations/rarities get a rate boost. // For example, only genesis legions are able to get full treasures from the zone. // And each rarity of legions (genesis and auxiliary) have a better chance for treasure pieces. uint8[][] generationToRarityToBoost; // Applies only when this zone part requires the user to play treasure triad. // This is the boost this reward gains per card that was flipped by the user. uint8 boostPerFlippedCard; // The different options for this reward. ZoneRewardOption[] rewardOptions; } struct ZoneRewardOption { // The consumable id associated with this reward option. // May be 0. uint256 consumableId; // The amount of the consumable given. uint256 consumableAmount; // ID associated to this treasure fragment. May be 0. uint256 treasureFragmentId; // The treasure tier if this option is to receive a full treasure. // May be 0 indicating no treasures uint8 treasureTier; // The category of treasure that will be minted for the given tier. TreasureCategory treasureCategory; // The odds out of 256 that this reward is picked from the options uint8 rewardOdds; } struct StartQuestParams { uint256 legionId; string zoneName; // What part to advance to. Should be between 1-maxParts. uint8 advanceToPart; // The treasures to stake with the legion. uint256[] treasureIds; uint256[] treasureAmounts; } // Pack the struct. 7 is the maximum number of treasures that can be staked. struct Treasures { uint8 numberOfTypesOfTreasures; uint16 treasure1Id; uint8 treasure1Amount; uint16 treasure2Id; uint8 treasure2Amount; uint16 treasure3Id; uint8 treasure3Amount; uint16 treasure4Id; uint8 treasure4Amount; uint16 treasure5Id; uint8 treasure5Amount; uint16 treasure6Id; uint8 treasure6Amount; uint16 treasure7Id; uint8 treasure7Amount; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IAdvancedQuesting { function emergencyEndQuesting( EmergencyEndQuestingParams[] calldata _endParams) external; } struct EmergencyEndQuestingParams { uint256 legionId; address owner; string zone; uint256[] treasureIds; uint256[] treasureAmounts; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol"; interface IConsumable is IERC1155Upgradeable { function mint(address _to, uint256 _id, uint256 _amount) external; function burn(address account, uint256 id, uint256 value) external; function burnBatch(address account, uint256[] memory ids, uint256[] memory values) external; function adminSafeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount) external; function adminSafeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _amounts) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ITreasure { // Transfers the treasure at the given ID of the given amount. // Requires that the legions are pre-approved. // function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _amounts, bytes memory data) external; // Transfers the treasure at the given ID of the given amount. // function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount, bytes memory data) external; // Admin only. // function mint(address _account, uint256 _tokenId, uint256 _amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol"; interface ILegion is IERC721MetadataUpgradeable { // Mints a legion to the given address. Returns the token ID. // Admin only. function safeMint(address _to) external returns(uint256); // Sets the URI for the given token id. Token must exist. // Admin only. function setTokenURI(uint256 _tokenId, string calldata _tokenURI) external; // Transfers the token to the given address. Does not need approval. _from still must be the owner of the token. // Admin only. function adminSafeTransferFrom(address _from, address _to, uint256 _tokenId) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./LegionMetadataStoreState.sol"; interface ILegionMetadataStore { // Sets the intial metadata for a token id. // Admin only. function setInitialMetadataForLegion(address _owner, uint256 _tokenId, LegionGeneration _generation, LegionClass _class, LegionRarity _rarity, uint256 _oldId) external; // Increases the quest level by one. It is up to the calling contract to regulate the max quest level. No validation. // Admin only. function increaseQuestLevel(uint256 _tokenId) external; // Increases the craft level by one. It is up to the calling contract to regulate the max craft level. No validation. // Admin only. function increaseCraftLevel(uint256 _tokenId) external; // Increases the rank of the given constellation to the given number. It is up to the calling contract to regulate the max constellation rank. No validation. // Admin only. function increaseConstellationRank(uint256 _tokenId, Constellation _constellation, uint8 _to) external; // Returns the metadata for the given legion. function metadataForLegion(uint256 _tokenId) external view returns(LegionMetadata memory); // Returns the tokenUri for the given token. function tokenURI(uint256 _tokenId) external view returns(string memory); } // As this will likely change in the future, this should not be used to store state, but rather // as parameters and return values from functions. struct LegionMetadata { LegionGeneration legionGeneration; LegionClass legionClass; LegionRarity legionRarity; uint8 questLevel; uint8 craftLevel; uint8[6] constellationRanks; uint256 oldId; } enum Constellation { FIRE, EARTH, WIND, WATER, LIGHT, DARK } enum LegionRarity { LEGENDARY, RARE, SPECIAL, UNCOMMON, COMMON, RECRUIT } enum LegionClass { RECRUIT, SIEGE, FIGHTER, ASSASSIN, RANGED, SPELLCASTER, RIVERMAN, NUMERAIRE, ALL_CLASS, ORIGIN } enum LegionGeneration { GENESIS, AUXILIARY, RECRUIT }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "../../shared/AdminableUpgradeable.sol"; import "./ILegionMetadataStore.sol"; abstract contract LegionMetadataStoreState is Initializable, AdminableUpgradeable { event LegionQuestLevelUp(uint256 indexed _tokenId, uint8 _questLevel); event LegionCraftLevelUp(uint256 indexed _tokenId, uint8 _craftLevel); event LegionConstellationRankUp(uint256 indexed _tokenId, Constellation indexed _constellation, uint8 _rank); event LegionCreated(address indexed _owner, uint256 indexed _tokenId, LegionGeneration _generation, LegionClass _class, LegionRarity _rarity); mapping(uint256 => LegionGeneration) internal idToGeneration; mapping(uint256 => LegionClass) internal idToClass; mapping(uint256 => LegionRarity) internal idToRarity; mapping(uint256 => uint256) internal idToOldId; mapping(uint256 => uint8) internal idToQuestLevel; mapping(uint256 => uint8) internal idToCraftLevel; mapping(uint256 => uint8[6]) internal idToConstellationRanks; mapping(LegionGeneration => mapping(LegionClass => mapping(LegionRarity => mapping(uint256 => string)))) internal _genToClassToRarityToOldIdToUri; function __LegionMetadataStoreState_init() internal initializer { AdminableUpgradeable.__Adminable_init(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IQuesting { function processQPGainAndLevelUp(uint256 _tokenId, uint8 _currentQuestLevel, uint256 _qpGained) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol"; interface ITreasureFragment is IERC1155Upgradeable { function mint(address _to, uint256 _id, uint256 _amount) external; function burn(address account, uint256 id, uint256 value) external; function burnBatch(address account, uint256[] memory ids, uint256[] memory values) external; function adminSafeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount) external; function adminSafeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _amounts) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./TreasureMetadataStoreState.sol"; interface ITreasureMetadataStore { // Sets the metadata for the given Ids. // Admin only. function setMetadataForIds(uint256[] calldata _ids, TreasureMetadata[] calldata _metadatas) external; // Returns if the given ID has metadata set. function hasMetadataForTreasureId(uint256 _treasureId) external view returns(bool); // Returns the metadata for the given ID. Reverts if no metadata for the ID is set. function getMetadataForTreasureId(uint256 _treasureId) external view returns(TreasureMetadata memory); // For the given tier, gets a random MINTABLE treasure id. function getRandomTreasureForTier(uint8 _tier, uint256 _randomNumber) external view returns(uint256); // For the given tier AND category, gets a random MINTABLE treasure id. function getRandomTreasureForTierAndCategory( uint8 _tier, TreasureCategory _category, uint256 _randomNumber) external view returns(uint256); // For the given tier, gets a random treasure id, MINTABLE OR NOT. function getAnyRandomTreasureForTier(uint8 _tier, uint256 _randomNumber) external view returns(uint256); } // Do not change. Stored in state. struct TreasureMetadata { TreasureCategory category; uint8 tier; // Out of 100,000 uint32 craftingBreakOdds; bool isMintable; uint256 consumableIdDropWhenBreak; } enum TreasureCategory { ALCHEMY, ARCANA, BREWING, ENCHANTER, LEATHERWORKING, SMITHING }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../shared/AdminableUpgradeable.sol"; import "./ITreasureMetadataStore.sol"; import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol"; abstract contract TreasureMetadataStoreState is AdminableUpgradeable { mapping(uint8 => EnumerableSetUpgradeable.UintSet) internal tierToMintableTreasureIds; mapping(uint256 => TreasureMetadata) internal treasureIdToMetadata; mapping(uint8 => mapping(TreasureCategory => EnumerableSetUpgradeable.UintSet)) internal tierToCategoryToMintableTreasureIds; mapping(uint8 => EnumerableSetUpgradeable.UintSet) internal tierToTreasureIds; function __TreasureMetadataStoreState_init() internal initializer { AdminableUpgradeable.__Adminable_init(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../treasuremetadatastore/ITreasureMetadataStore.sol"; import "../legionmetadatastore/ILegionMetadataStore.sol"; interface ITreasureTriad { function generateBoardAndPlayGame( uint256 _randomNumber, LegionClass _legionClass, UserMove[] calldata _userMoves) external view returns(GameOutcome memory); } enum PlayerType { NONE, NATURE, USER } // Represents the information contained in a single cell of the game grid. struct GridCell { // The treasure played on this cell. May be 0 if PlayerType == NONE uint256 treasureId; // The type of player that has played on this cell. PlayerType playerType; // In the case that playerType == NATURE, if this is true, the player has flipped this card to their side. bool isFlipped; // Indicates if the cell is corrupted. // If the cell is empty, the player must place a card on it to make it uncorrupted. // If the cell has a contract/nature card, the player must flip the card to make it uncorrupted. bool isCorrupted; // Indicates if this cell has an affinity. If so, look at the affinity field. bool hasAffinity; // The affinity of this field. Only consider this field if hasAffinity is true. TreasureCategory affinity; } // Represents a move the end user will make. struct UserMove { // The x coordinate of the location uint8 x; // The y coordinate of the location. uint8 y; // The treasure to place at this location. uint256 treasureId; } struct GameOutcome { uint8 numberOfFlippedCards; uint8 numberOfCorruptedCardsLeft; bool playerWon; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "./UtilitiesUpgradeable.sol"; // Do not add state to this contract. // contract AdminableUpgradeable is UtilitiesUpgradeable { mapping(address => bool) private admins; function __Adminable_init() internal initializer { UtilitiesUpgradeable.__Utilities__init(); } function addAdmin(address _address) external onlyOwner { admins[_address] = true; } function addAdmins(address[] calldata _addresses) external onlyOwner { for(uint256 i = 0; i < _addresses.length; i++) { admins[_addresses[i]] = true; } } function removeAdmin(address _address) external onlyOwner { admins[_address] = false; } function removeAdmins(address[] calldata _addresses) external onlyOwner { for(uint256 i = 0; i < _addresses.length; i++) { admins[_addresses[i]] = false; } } function setPause(bool _shouldPause) external onlyAdminOrOwner { if(_shouldPause) { _pause(); } else { _unpause(); } } function isAdmin(address _address) public view returns(bool) { return admins[_address]; } modifier onlyAdmin() { require(admins[msg.sender], "Not admin"); _; } modifier onlyAdminOrOwner() { require(admins[msg.sender] || isOwner(), "Not admin or owner"); _; } uint256[50] private __gap; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; contract UtilitiesUpgradeable is Initializable, OwnableUpgradeable, PausableUpgradeable { function __Utilities__init() internal initializer { OwnableUpgradeable.__Ownable_init(); PausableUpgradeable.__Pausable_init(); _pause(); } modifier nonZeroAddress(address _address) { require(address(0) != _address, "0 address"); _; } modifier nonZeroLength(uint[] memory _array) { require(_array.length > 0, "Empty array"); _; } modifier lengthsAreEqual(uint[] memory _array1, uint[] memory _array2) { require(_array1.length == _array2.length, "Unequal lengths"); _; } modifier onlyEOA() { /* solhint-disable avoid-tx-origin */ require(msg.sender == tx.origin, "No contracts"); _; } function isOwner() internal view returns(bool) { return owner() == msg.sender; } function compareStrings(string memory a, string memory b) internal pure returns (bool) { return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b)))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IRandomizer { // Sets the number of blocks that must pass between increment the commitId and seeding the random // Admin function setNumBlocksAfterIncrement(uint8 _numBlocksAfterIncrement) external; // Increments the commit id. // Admin function incrementCommitId() external; // Adding the random number needs to be done AFTER incrementing the commit id on a separate transaction. If // these are done together, there is a potential vulnerability to front load a commit when the bad actor // sees the value of the random number. function addRandomForCommit(uint256 _seed) external; // Returns a request ID for a random number. This is unique. function requestRandomNumber() external returns(uint256); // Returns the random number for the given request ID. Will revert // if the random is not ready. function revealRandomNumber(uint256 _requestId) external view returns(uint256); // Returns if the random number for the given request ID is ready or not. Call // before calling revealRandomNumber. function isRandomReady(uint256 _requestId) external view returns(bool); }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"_legionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_requestId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"_toPart","type":"uint8"}],"name":"AdvancedQuestContinued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"_legionId","type":"uint256"},{"components":[{"internalType":"uint256","name":"consumableId","type":"uint256"},{"internalType":"uint256","name":"consumableAmount","type":"uint256"},{"internalType":"uint256","name":"treasureFragmentId","type":"uint256"},{"internalType":"uint256","name":"treasureId","type":"uint256"}],"indexed":false,"internalType":"struct AdvancedQuestingState.AdvancedQuestReward[]","name":"_rewards","type":"tuple[]"}],"name":"AdvancedQuestEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"_requestId","type":"uint256"},{"components":[{"internalType":"uint256","name":"legionId","type":"uint256"},{"internalType":"string","name":"zoneName","type":"string"},{"internalType":"uint8","name":"advanceToPart","type":"uint8"},{"internalType":"uint256[]","name":"treasureIds","type":"uint256[]"},{"internalType":"uint256[]","name":"treasureAmounts","type":"uint256[]"}],"indexed":false,"internalType":"struct StartQuestParams","name":"_startQuestParams","type":"tuple"}],"name":"AdvancedQuestStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"_endingPart","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"_qpGained","type":"uint256"}],"name":"QPForEndingPart","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"_legionId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_playerWon","type":"bool"},{"indexed":false,"internalType":"uint8","name":"_numberOfCardsFlipped","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"_numberOfCorruptedCardsRemaining","type":"uint8"}],"name":"TreasureTriadPlayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"}],"name":"addAdmins","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_zoneName","type":"string"},{"components":[{"internalType":"uint256","name":"zoneStartTime","type":"uint256"},{"internalType":"enum TreasureCategory","name":"categoryBoost1","type":"uint8"},{"internalType":"enum TreasureCategory","name":"categoryBoost2","type":"uint8"},{"internalType":"enum Constellation","name":"constellation1","type":"uint8"},{"internalType":"enum Constellation","name":"constellation2","type":"uint8"},{"components":[{"internalType":"uint256","name":"zonePartLength","type":"uint256"},{"internalType":"uint256","name":"stasisLength","type":"uint256"},{"internalType":"uint8","name":"stasisBaseRate","type":"uint8"},{"internalType":"uint8","name":"questingLevelRequirement","type":"uint8"},{"internalType":"uint8","name":"questingXpGained","type":"uint8"},{"internalType":"bool","name":"playTreasureTriad","type":"bool"},{"components":[{"internalType":"uint8","name":"baseRateRewardOdds","type":"uint8"},{"internalType":"uint8[][]","name":"generationToRarityToBoost","type":"uint8[][]"},{"internalType":"uint8","name":"boostPerFlippedCard","type":"uint8"},{"components":[{"internalType":"uint256","name":"consumableId","type":"uint256"},{"internalType":"uint256","name":"consumableAmount","type":"uint256"},{"internalType":"uint256","name":"treasureFragmentId","type":"uint256"},{"internalType":"uint8","name":"treasureTier","type":"uint8"},{"internalType":"enum TreasureCategory","name":"treasureCategory","type":"uint8"},{"internalType":"uint8","name":"rewardOdds","type":"uint8"}],"internalType":"struct ZoneRewardOption[]","name":"rewardOptions","type":"tuple[]"}],"internalType":"struct ZoneReward[]","name":"rewards","type":"tuple[]"}],"internalType":"struct ZonePart[]","name":"parts","type":"tuple[]"}],"internalType":"struct ZoneInfo","name":"_zone","type":"tuple"}],"name":"addZone","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"areContractsSet","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chanceUniversalLock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"consumable","outputs":[{"internalType":"contract IConsumable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_legionIds","type":"uint256[]"}],"name":"continueAdvancedQuesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"legionId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"string","name":"zone","type":"string"},{"internalType":"uint256[]","name":"treasureIds","type":"uint256[]"},{"internalType":"uint256[]","name":"treasureAmounts","type":"uint256[]"}],"internalType":"struct EmergencyEndQuestingParams[]","name":"_endParams","type":"tuple[]"}],"name":"emergencyEndQuesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_legionIds","type":"uint256[]"},{"internalType":"bool[]","name":"_restartQuesting","type":"bool[]"}],"name":"endQuesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_legionId","type":"uint256"}],"name":"endTimeForLegion","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"endingPartToQPGained","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_legionId","type":"uint256"}],"name":"isLegionQuesting","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_zoneName","type":"string"}],"name":"isValidZone","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"legion","outputs":[{"internalType":"contract ILegion","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"legionMetadataStore","outputs":[{"internalType":"contract ILegionMetadataStore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_zoneName","type":"string"},{"internalType":"uint8","name":"_partIndex","type":"uint8"}],"name":"lengthForPartOfZone","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"legionId","type":"uint256"},{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"},{"internalType":"uint256","name":"treasureId","type":"uint256"}],"internalType":"struct UserMove[]","name":"playerMoves","type":"tuple[]"},{"internalType":"bool","name":"restartQuestIfPossible","type":"bool"}],"internalType":"struct PlayTreasureTriadParams[]","name":"_params","type":"tuple[]"}],"name":"playTreasureTriad","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"questing","outputs":[{"internalType":"contract IQuesting","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"randomizer","outputs":[{"internalType":"contract IRandomizer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"}],"name":"removeAdmins","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chanceUniversalLock","type":"uint256"}],"name":"setChanceUniversalLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_randomizerAddress","type":"address"},{"internalType":"address","name":"_questingAddress","type":"address"},{"internalType":"address","name":"_legionAddress","type":"address"},{"internalType":"address","name":"_legionMetadataStoreAddress","type":"address"},{"internalType":"address","name":"_treasureAddress","type":"address"},{"internalType":"address","name":"_consumableAddress","type":"address"},{"internalType":"address","name":"_treasureMetadataStoreAddress","type":"address"},{"internalType":"address","name":"_treasureTriadAddress","type":"address"},{"internalType":"address","name":"_treasureFragmentAddress","type":"address"}],"name":"setContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"endingPart","type":"uint8"},{"internalType":"uint248","name":"qpGained","type":"uint248"}],"internalType":"struct EndingPartParams[]","name":"_endingPartParams","type":"tuple[]"}],"name":"setEndingPartToQPGained","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_shouldPause","type":"bool"}],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stasisLengthForCorruptedCard","type":"uint256"}],"name":"setStasisLengthForCorruptedCard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"legionId","type":"uint256"},{"internalType":"string","name":"zoneName","type":"string"},{"internalType":"uint8","name":"advanceToPart","type":"uint8"},{"internalType":"uint256[]","name":"treasureIds","type":"uint256[]"},{"internalType":"uint256[]","name":"treasureAmounts","type":"uint256[]"}],"internalType":"struct StartQuestParams[]","name":"_params","type":"tuple[]"}],"name":"startAdvancedQuesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stasisLengthForCorruptedCard","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasure","outputs":[{"internalType":"contract ITreasure","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasureFragment","outputs":[{"internalType":"contract ITreasureFragment","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasureMetadataStore","outputs":[{"internalType":"contract ITreasureMetadataStore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasureTriad","outputs":[{"internalType":"contract ITreasureTriad","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_zoneName","type":"string"},{"internalType":"uint256[]","name":"_partLengths","type":"uint256[]"},{"internalType":"uint256[]","name":"_stasisLengths","type":"uint256[]"}],"name":"updatePartLengthsForZone","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_zoneName","type":"string"},{"internalType":"uint256","name":"_partIndex","type":"uint256"},{"internalType":"uint256","name":"_rewardIndex","type":"uint256"},{"internalType":"uint8[7]","name":"_questLevelBoosts","type":"uint8[7]"}],"name":"updateQuestLevelBoosts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"zoneNameToInfo","outputs":[{"internalType":"uint256","name":"zoneStartTime","type":"uint256"},{"internalType":"enum TreasureCategory","name":"categoryBoost1","type":"uint8"},{"internalType":"enum TreasureCategory","name":"categoryBoost2","type":"uint8"},{"internalType":"enum Constellation","name":"constellation1","type":"uint8"},{"internalType":"enum Constellation","name":"constellation2","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"zoneNameToPartIndexToRewardIndexToQuestBoosts","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50617e4380620000216000396000f3fe608060405234801561001057600080fd5b506004361061028a5760003560e01c80638129fc1c1161015c578063bedb86fb116100ce578063e520fc7e11610087578063e520fc7e1461063e578063ec27109214610652578063f10fb58414610673578063f23a6e6114610687578063f2fde38b146106a6578063f61f2a37146106b957600080fd5b8063bedb86fb146105b2578063c43c074c146105c5578063c87d4e07146105ef578063cfe5190314610602578063d3f6760914610616578063d7dfe4dd1461062a57600080fd5b80639c54df64116101205780639c54df64146105335780639efbfd7114610546578063a0122ec614610559578063a88830601461056d578063abfe37b914610580578063bc197c811461059357600080fd5b80638129fc1c146104eb578063821cab0b146104f35780638a7bf804146105065780638cdcc4b41461051a5780638da5cb5b1461052257600080fd5b80633ea86bfe1161020057806370480275116101b9578063704802751461048d578063715018a6146104a0578063715e1e49146104a857806372748fc3146104b25780637608223d146104c55780637d7aa1bc146104d857600080fd5b80633ea86bfe146103cd5780634bec7954146103e557806350cbc4851461044857806353c409321461045b5780635c975abb1461046e578063675857eb1461047957600080fd5b80631785f53c116102525780631785f53c146103425780631b2378c51461035557806324d7806c146103685780632847a62d14610394578063377e11e0146103a75780633c06ef4e146103ba57600080fd5b806301ffc9a71461028f5780630a0e28d4146102b757806311ee3cf1146102cc57806313bc0b8d146102df578063150b7a021461030b575b600080fd5b6102a261029d366004616274565b6106de565b60405190151581526020015b60405180910390f35b6102ca6102c53660046162e9565b610715565b005b6102ca6102da3660046162e9565b61083b565b610193546102f3906001600160a01b031681565b6040516001600160a01b0390911681526020016102ae565b610329610319366004616439565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020016102ae565b6102ca6103503660046164a0565b610997565b6102a26103633660046164bb565b6109e2565b6102a26103763660046164a0565b6001600160a01b031660009081526097602052604090205460ff1690565b6102a26103a23660046164f7565b610a0d565b6102ca6103b53660046162e9565b610a44565b6102ca6103c83660046164f7565b610ae0565b6103d761019b5481565b6040519081526020016102ae565b6104376103f33660046164bb565b805160208183018101805161019c825292820191909301209152805460019091015460ff808216916101008104821691620100008204811691630100000090041685565b6040516102ae959493929190616536565b6102ca6104563660046165c4565b610b23565b6102ca6104693660046164f7565b610d05565b60655460ff166102a2565b610194546102f3906001600160a01b031681565b6102ca61049b3660046164a0565b610d48565b6102ca610d96565b6103d76101a15481565b6102ca6104c03660046162e9565b610dcc565b6102ca6104d3366004616634565b6112ee565b6102ca6104e63660046166a8565b611441565b6102ca611612565b6102ca6105013660046162e9565b61168c565b610195546102f3906001600160a01b031681565b6102a2611793565b6033546001600160a01b03166102f3565b6102ca6105413660046162e9565b611862565b6102ca610554366004616741565b6118fe565b610198546102f3906001600160a01b031681565b6102ca61057b3660046167ac565b611a87565b6102ca61058e366004616854565b611b6a565b6103296105a1366004616937565b63bc197c8160e01b95945050505050565b6102ca6105c03660046169ee565b611d45565b6105d86105d33660046164f7565b611d98565b6040805192835260ff9091166020830152016102ae565b6103d76105fd366004616a25565b61200d565b61019a546102f3906001600160a01b031681565b610199546102f3906001600160a01b031681565b610197546102f3906001600160a01b031681565b610196546102f3906001600160a01b031681565b6103d7610660366004616a70565b6101a36020526000908152604090205481565b610192546102f3906001600160a01b031681565b610329610695366004616a8d565b63f23a6e6160e01b95945050505050565b6102ca6106b43660046164a0565b612063565b6106cc6106c7366004616af1565b6120fb565b60405160ff90911681526020016102ae565b60006001600160e01b03198216630271189760e51b148061070f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60655460ff16156107415760405162461bcd60e51b815260040161073890616b44565b60405180910390fd5b610749611793565b6107655760405162461bcd60e51b815260040161073890616b6e565b3332146107845760405162461bcd60e51b815260040161073890616b9c565b818180806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508251151591506107f790505760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b6044820152606401610738565b60005b828110156108355761082384848381811061081757610817616bc2565b90506020020135612156565b8061082d81616bee565b9150506107fa565b50505050565b60655460ff161561085e5760405162461bcd60e51b815260040161073890616b44565b610866611793565b6108825760405162461bcd60e51b815260040161073890616b6e565b3332146108a15760405162461bcd60e51b815260040161073890616b9c565b806108e15760405162461bcd60e51b815260206004820152601060248201526f084c2c840c2e4e4c2f240d8cadccee8d60831b6044820152606401610738565b60005b818110156109925761098083838381811061090157610901616bc2565b90506020028101906109139190616c09565b3584848481811061092657610926616bc2565b90506020028101906109389190616c09565b610946906020810190616c29565b86868681811061095857610958616bc2565b905060200281019061096a9190616c09565b61097b9060608101906040016169ee565b612714565b8061098a81616bee565b9150506108e4565b505050565b6033546001600160a01b031633146109c15760405162461bcd60e51b815260040161073890616c71565b6001600160a01b03166000908152609760205260409020805460ff19169055565b60008061019c836040516109f69190616cd2565b908152604051908190036020019020541192915050565b600081815261019f602052604081205415158061070f57505060009081526101a060205260409020546001600160781b0316151590565b6033546001600160a01b03163314610a6e5760405162461bcd60e51b815260040161073890616c71565b60005b8181101561099257600060976000858585818110610a9157610a91616bc2565b9050602002016020810190610aa691906164a0565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905580610ad881616bee565b915050610a71565b3360009081526097602052604090205460ff1680610b015750610b01612b57565b610b1d5760405162461bcd60e51b815260040161073890616ce4565b61019b55565b3360009081526097602052604090205460ff1680610b445750610b44612b57565b610b605760405162461bcd60e51b815260040161073890616ce4565b610b9f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506109e292505050565b610bdd5760405162461bcd60e51b815260206004820152600f60248201526e169bdb99481a5cc81a5b9d985b1a59608a1b6044820152606401610738565b600061019c8686604051610bf2929190616d10565b90815260405190819003602001902060028101549091508410610c485760405162461bcd60e51b815260206004820152600e60248201526d084c2c840e0c2e4e840d2dcc8caf60931b6044820152606401610738565b6000816002018581548110610c5f57610c5f616bc2565b9060005260206000209060040201905080600301805490508410610cb85760405162461bcd60e51b815260206004820152601060248201526f084c2c840e4caeec2e4c840d2dcc8caf60831b6044820152606401610738565b826101a28888604051610ccc929190616d10565b908152604080516020928190038301902060008981529083528181208882529092529020610cfb916007616155565b5050505050505050565b3360009081526097602052604090205460ff1680610d265750610d26612b57565b610d425760405162461bcd60e51b815260040161073890616ce4565b6101a155565b6033546001600160a01b03163314610d725760405162461bcd60e51b815260040161073890616c71565b6001600160a01b03166000908152609760205260409020805460ff19166001179055565b6033546001600160a01b03163314610dc05760405162461bcd60e51b815260040161073890616c71565b610dca6000612b7b565b565b60655460ff1615610def5760405162461bcd60e51b815260040161073890616b44565b610df7611793565b610e135760405162461bcd60e51b815260040161073890616b6e565b3360009081526097602052604090205460ff1680610e345750610e34612b57565b610e505760405162461bcd60e51b815260040161073890616ce4565b60005b818110156109925736838383818110610e6e57610e6e616bc2565b9050602002810190610e809190616d20565b8035600090815261019f602052604081206001015491925090610ed8576040805144602082015242918101919091524360608201526080016040516020818303038152906040528051906020012060001c9050610f74565b610192548235600090815261019f602052604090819020600101549051634ad30a7560e01b81526001600160a01b0390921691634ad30a7591610f219160040190815260200190565b60206040518083038186803b158015610f3957600080fd5b505afa158015610f4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f719190616d36565b90505b610195546040516378afdef960e11b8152833560048201526000916001600160a01b03169063f15fbdf2906024016101806040518083038186803b158015610fbb57600080fd5b505afa158015610fcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff39190616df7565b610193546060820151604051630a39d94760e11b81528635600482015260ff9091166024820152602860448201529192506001600160a01b031690631473b28e90606401600060405180830381600087803b15801561105157600080fd5b505af1158015611065573d6000803e3d6000fd5b50505050600061019c84806040019061107e9190616e8c565b60405161108c929190616d10565b9081526020016040518091039020905060006111268580604001906110b19190616e8c565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060028481018054829081106110fc576110fc616bc2565b90600052602060002090600402018689602001602081019061111e91906164a0565b896003612bcd565b610194549091506001600160a01b03166383291f873061114c6040890160208a016164a0565b60405160e084901b6001600160e01b03191681526001600160a01b0392831660048201529116602482015287356044820152606401600060405180830381600087803b15801561119b57600080fd5b505af11580156111af573d6000803e3d6000fd5b50600092506111c49150506060870187616ed2565b9050111561125d57610196546001600160a01b0316632eb2c2d6306111ef6040890160208a016164a0565b6111fc60608a018a616ed2565b61120960808c018c616ed2565b6040518763ffffffff1660e01b815260040161122a96959493929190616f51565b600060405180830381600087803b15801561124457600080fd5b505af1158015611258573d6000803e3d6000fd5b505050505b8435600090815261019f602090815260408083208390556101a082529182902080546001600160781b03191690557f9949f99e59b9a76e12491767b7369cea6085b2e0f953d867d6a20484c12b105c916112bc919088019088016164a0565b6040516112ce91908835908590616fb0565b60405180910390a1505050505080806112e690616bee565b915050610e53565b3360009081526097602052604090205460ff168061130f575061130f612b57565b61132b5760405162461bcd60e51b815260040161073890616ce4565b60005b818110156109925782828281811061134857611348616bc2565b9050604002016020016020810190611360919061702d565b6001600160f81b03166101a3600085858581811061138057611380616bc2565b6113969260206040909202019081019150616a70565b60ff168152602081019190915260400160002055600080516020617dee8339815191528383838181106113cb576113cb616bc2565b6113e19260206040909202019081019150616a70565b8484848181106113f3576113f3616bc2565b905060400201602001602081019061140b919061702d565b6040805160ff90931683526001600160f81b0390911660208301520160405180910390a18061143981616bee565b91505061132e565b3360009081526097602052604090205460ff16806114625750611462612b57565b61147e5760405162461bcd60e51b815260040161073890616ce4565b6114bd86868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506109e292505050565b6114fb5760405162461bcd60e51b815260206004820152600f60248201526e169bdb99481a5cc81a5b9d985b1a59608a1b6044820152606401610738565b600061019c8787604051611510929190616d10565b90815260405190819003602001902060028101549091508414801561153457508382145b6115745760405162461bcd60e51b8152602060048201526011602482015270426164206172726179206c656e6774687360781b6044820152606401610738565b60005b84811015610cfb5785858281811061159157611591616bc2565b905060200201358260020182815481106115ad576115ad616bc2565b60009182526020909120600490910201558383828181106115d0576115d0616bc2565b905060200201358260020182815481106115ec576115ec616bc2565b60009182526020909120600160049092020101558061160a81616bee565b915050611577565b600054610100900460ff1661162d5760005460ff1615611631565b303b155b61164d5760405162461bcd60e51b815260040161073890617056565b600054610100900460ff1615801561166f576000805461ffff19166101011790555b611677612fc4565b8015611689576000805461ff00191690555b50565b60655460ff16156116af5760405162461bcd60e51b815260040161073890616b44565b6116b7611793565b6116d35760405162461bcd60e51b815260040161073890616b6e565b3332146116f25760405162461bcd60e51b815260040161073890616b9c565b8061173f5760405162461bcd60e51b815260206004820152601b60248201527f4e6f20737461727420717565737420706172616d7320676976656e00000000006044820152606401610738565b60005b818110156109925761178183838381811061175f5761175f616bc2565b90506020028101906117719190616d20565b61177a906170a4565b6000613029565b8061178b81616bee565b915050611742565b610192546000906001600160a01b0316158015906117bc5750610193546001600160a01b031615155b80156117d35750610194546001600160a01b031615155b80156117ea5750610195546001600160a01b031615155b80156118015750610196546001600160a01b031615155b80156118185750610197546001600160a01b031615155b801561182f5750610198546001600160a01b031615155b80156118465750610199546001600160a01b031615155b801561185d575061019a546001600160a01b031615155b905090565b6033546001600160a01b0316331461188c5760405162461bcd60e51b815260040161073890616c71565b60005b81811015610992576001609760008585858181106118af576118af616bc2565b90506020020160208101906118c491906164a0565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055806118f681616bee565b91505061188f565b60655460ff16156119215760405162461bcd60e51b815260040161073890616b44565b611929611793565b6119455760405162461bcd60e51b815260040161073890616b6e565b3332146119645760405162461bcd60e51b815260040161073890616b9c565b838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508251151591506119d790505760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b6044820152606401610738565b838214611a1a5760405162461bcd60e51b8152602060048201526011602482015270426164206172726179206c656e6774687360781b6044820152606401610738565b60005b84811015611a7f57611a6d868683818110611a3a57611a3a616bc2565b90506020020135858584818110611a5357611a53616bc2565b9050602002016020810190611a6891906169ee565b6138a7565b80611a7781616bee565b915050611a1d565b505050505050565b3360009081526097602052604090205460ff1680611aa85750611aa8612b57565b611ac45760405162461bcd60e51b815260040161073890616ce4565b61019280546001600160a01b03199081166001600160a01b039b8c161790915561019380548216998b169990991790985561019480548916978a16979097179096556101958054881695891695909517909455610196805487169388169390931790925561019780548616918716919091179055610198805485169186169190911790556101998054841691851691909117905561019a80549092169216919091179055565b3360009081526097602052604090205460ff1680611b8b5750611b8b612b57565b611ba75760405162461bcd60e51b815260040161073890616ce4565b611bf483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051602081019091529081529250613adf915050565b15611c415760405162461bcd60e51b815260206004820152601960248201527f5a6f6e65206e616d652063616e6e6f7420626520626c616e6b000000000000006044820152606401610738565b611c8083838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506109e292505050565b15611cc35760405162461bcd60e51b81526020600482015260136024820152725a6f6e6520616c72656164792065786973747360681b6044820152606401610738565b8035611d115760405162461bcd60e51b815260206004820152601b60248201527f5a6f6e65206d757374206861766520612073746172742074696d6500000000006044820152606401610738565b8061019c8484604051611d25929190616d10565b908152604051908190036020019020611d3e82826177cd565b5050505050565b3360009081526097602052604090205460ff1680611d665750611d66612b57565b611d825760405162461bcd60e51b815260040161073890616ce4565b8015611d9057611689613b38565b611689613bad565b610195546040516378afdef960e11b815260048101839052600091829182916001600160a01b03169063f15fbdf2906024016101806040518083038186803b158015611de357600080fd5b505afa158015611df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1b9190616df7565b600085815261019f602052604081205491925090151590611ece611e3f8388613c27565b8054611e4a90617976565b80601f0160208091040260200160405190810160405280929190818152602001828054611e7690617976565b8015611ec35780601f10611e9857610100808354040283529160200191611ec3565b820191906000526020600020905b815481529060010190602001808311611ea657829003601f168201915b505050505084613c5d565b610192549091506000906001600160a01b0316634ad30a75611ef0858a613d38565b6040518263ffffffff1660e01b8152600401611f0e91815260200190565b60206040518083038186803b158015611f2657600080fd5b505afa158015611f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5e9190616d36565b90506120008784611f6f868b613c27565b8054611f7a90617976565b80601f0160208091040260200160405190810160405280929190818152602001828054611fa690617976565b8015611ff35780601f10611fc857610100808354040283529160200191611ff3565b820191906000526020600020905b815481529060010190602001808311611fd657829003601f168201915b5050505050878686613d83565b9550955050505050915091565b600061019c8484604051612022929190616d10565b90815260200160405180910390206002018260ff168154811061204757612047616bc2565b90600052602060002090600402016000015490505b9392505050565b6033546001600160a01b0316331461208d5760405162461bcd60e51b815260040161073890616c71565b6001600160a01b0381166120f25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610738565b61168981612b7b565b83516020818601810180516101a28252928201828801209290529081526000848152604080822090925283815220816007811061213757600080fd5b602081049091015460ff601f9092166101000a90041693508492505050565b600081815261019f60205260408120541515906121738284613c27565b805461217e90617976565b80601f01602080910402602001604051908101604052809291908181526020018280546121aa90617976565b80156121f75780601f106121cc576101008083540402835291602001916121f7565b820191906000526020600020905b8154815290600101906020018083116121da57829003601f168201915b5050610195546040516378afdef960e11b8152600481018990529495506000946001600160a01b03909116935063f15fbdf2925060240190506101806040518083038186803b15801561224957600080fd5b505afa15801561225d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122819190616df7565b9050600061019c836040516122969190616cd2565b9081526040519081900360200190209050336122b28587613f57565b6001600160a01b0316146122d85760405162461bcd60e51b8152600401610738906179b1565b610192546000906001600160a01b0316634ad30a756122f78789613d38565b6040518263ffffffff1660e01b815260040161231591815260200190565b60206040518083038186803b15801561232d57600080fd5b505afa158015612341573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123659190616d36565b90506123778685878686866001613fa1565b60006123838688614103565b60028401549091506123968260016179de565b60ff1611156123de5760405162461bcd60e51b8152602060048201526014602482015273105b1c9958591e48185d081b185cdd081c185c9d60621b6044820152606401610738565b826002018160ff16815481106123f6576123f6616bc2565b6000918252602090912060026004909202010154606085015160ff6101009092048216911610156124395760405162461bcd60e51b815260040161073890617a03565b826002018160ff168154811061245157612451616bc2565b906000526020600020906004020160020160039054906101000a900460ff1615806124815750612481868861414f565b6124cd5760405162461bcd60e51b815260206004820152601d60248201527f4e6f207472656173757265207374616b656420666f72206c6567696f6e0000006044820152606401610738565b610192546040805163433c53d960e11b815290516000926001600160a01b031691638678a7b291600480830192602092919082900301818787803b15801561251457600080fd5b505af1158015612528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254c9190616d36565b905086156125e657600088815261019f60205260409020428155600801805460ff808516600160a81b0260ff60a81b1990921691909117808355600160a01b90041690601461259a83617a48565b825460ff9182166101009390930a928302919092021990911617905550600088815261019f60205260408120600281019190915560038101805461ffff191690556001018190556126ab565b60008881526101a06020526040902080546001600160781b031916426001600160781b031617815560010180546001600160f81b0316600160f81b60ff8581169190910291909117808355600160f01b90041690601e61264583617a48565b82546101009290920a60ff8181021990931691909216919091021790555060008881526101a06020526040902080546001600160781b03168155600101805469ffffffffffffffffffff60a01b1916600160a01b69ffffffffffffffffffff8416021790555b7f6637022d9de6a2060f00e17833969643de3940f9fc4ea37f4e755ae5121b13c33389836126da8660016179de565b604080516001600160a01b03909516855260208501939093529183015260ff16606082015260800160405180910390a15050505050505050565b600084815261019f60205260408120541515906127318287613c27565b805461273c90617976565b80601f016020809104026020016040519081016040528092919081815260200182805461276890617976565b80156127b55780601f1061278a576101008083540402835291602001916127b5565b820191906000526020600020905b81548152906001019060200180831161279857829003601f168201915b5050610195546040516378afdef960e11b8152600481018c90529495506000946001600160a01b03909116935063f15fbdf2925060240190506101806040518083038186803b15801561280757600080fd5b505afa15801561281b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061283f9190616df7565b9050600061019c836040516128549190616cd2565b908152604051908190036020019020905033612870858a613f57565b6001600160a01b0316146128965760405162461bcd60e51b8152600401610738906179b1565b610192546000906001600160a01b0316634ad30a756128b5878c613d38565b6040518263ffffffff1660e01b81526004016128d391815260200190565b60206040518083038186803b1580156128eb57600080fd5b505afa1580156128ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129239190616d36565b90506129358985878686866000613fa1565b6129418888878c61419c565b6101995460208401516040516330019d4b60e01b81526000926001600160a01b0316916330019d4b9161297c9186918e908e90600401617a68565b60606040518083038186803b15801561299457600080fd5b505afa1580156129a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129cc9190617ae4565b90508515612a1a5760008a815261019f602090815260409091204260028201559082015160039091018054835160ff9081166101000261ffff19909216931692909217919091179055612a8a565b60008a81526101a06020908152604090912080549183015183516fffffffffffffffffffffffffffffffff60781b19909316600160781b426001600160781b03160260ff60f01b191617600160f01b60ff92831602176001600160f81b0316600160f81b91909316029190911790555b604081810151825160208085015184513381529182018f90529215158185015260ff91821660608201529116608082015290517f9cc74f6243b89778b7e86d5b933c4146bd93203932a12bfe7ad7625d433e67ae9181900360a00190a1602081015160ff161580612b38575061019d600085600001516002811115612b1157612b11616510565b6002811115612b2257612b22616510565b815260208101919091526040016000205460ff16155b15612b4b57612b4b8a878686868c614401565b50505050505050505050565b600033612b6c6033546001600160a01b031690565b6001600160a01b031614905090565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6060827f270403fba6eda13e1a219e01f1fb9cac4267cb529255cf0cb111921f93124218604051602001612c0b929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c9250600085600001516002811115612c3e57612c3e616510565b9050600086604001516005811115612c5857612c58616510565b6003890154909150600090612c6e906001617b55565b6001600160401b03811115612c8557612c8561633a565b604051908082528060200260200182016040528015612ce157816020015b612cce6040518060800160405280600081526020016000815260200160008152602001600081525090565b815260200190600190039081612ca35790505b50905060005b60038a0154811015612ea75760008a6003018281548110612d0a57612d0a616bc2565b9060005260206000209060040201905060006101a28e604051612d2d9190616cd2565b908152602001604051809103902060008e815260200190815260200160002060008481526020019081526020016000208b6060015160ff1660078110612d7557612d75616bc2565b6020810490910154600284015460ff601f9093166101000a909104821691612da1918b82169116617166565b836001018881548110612db657612db6616bc2565b906000526020600020018781548110612dd157612dd1616bc2565b6000918252602091829020918104909101548554612dff92601f166101000a90910460ff9081169116617b55565b612e099190617b55565b612e139190617b55565b9050600060ff8210612e2757506001612e4c565b8115612e4c5781612e3a6101008c617b6d565b1015612e44575060015b60088a901c99505b8015612e91576000612e5e8b8561466d565b9050612e6b818c8e614783565b868681518110612e7d57612e7d616bc2565b602002602001018190525060088b901c9a50505b5050508080612e9f90616bee565b915050612ce7565b506101a15415612fb657604080516020810188905290810187905260600160408051601f19818403018152919052805160209091012095506000612eee620186a088617b6d565b90506101a154811015612fb45761019754604051630ab714fb60e11b81526001600160a01b039091169063156e29f690612f32908b90600a90600190600401617b8f565b600060405180830381600087803b158015612f4c57600080fd5b505af1158015612f60573d6000803e3d6000fd5b505050506040518060800160405280600a8152602001600181526020016000815260200160008152508260018451612f989190617bb0565b81518110612fa857612fa8616bc2565b60200260200101819052505b505b9a9950505050505050505050565b600054610100900460ff16612fdf5760005460ff1615612fe3565b303b155b612fff5760405162461bcd60e51b815260040161073890617056565b600054610100900460ff16158015613021576000805461ffff19166101011790555b6116776149d5565b815161303481610a0d565b156130815760405162461bcd60e51b815260206004820152601a60248201527f4c6567696f6e20697320616c7265616479207175657374696e670000000000006044820152606401610738565b61308e83602001516109e2565b6130c95760405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964207a6f6e6560a01b6044820152606401610738565b600061019c84602001516040516130e09190616cd2565b90815260200160405180910390206002018054905090506000846040015160ff16118015613115575080846040015160ff1611155b6131615760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420616476616e636520746f20706172740000000000000000006044820152606401610738565b610195546040516378afdef960e11b8152600481018490526000916001600160a01b03169063f15fbdf2906024016101806040518083038186803b1580156131a857600080fd5b505afa1580156131bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e09190616df7565b90506002815160028111156131f7576131f7616510565b14156132455760405162461bcd60e51b815260206004820152601d60248201527f526563727569742063616e6e6f7420616476616e6365642071756573740000006044820152606401610738565b6000805b866040015160ff168110156133e257600061019c886020015160405161326f9190616cd2565b9081526020016040518091039020600201828154811061329157613291616bc2565b6000918252602090912060026004909202010154606085015160ff61010090920482169250168111156132d65760405162461bcd60e51b815260040161073890617a03565b600061019c89602001516040516132ed9190616cd2565b9081526020016040518091039020600201838154811061330f5761330f616bc2565b906000526020600020906004020160020160039054906101000a900460ff16905083806133395750805b93506001896040015161334c9190617bc7565b60ff168310801561335a5750805b156133cd5760405162461bcd60e51b815260206004820152603860248201527f43616e6e6f7420616476616e636564207061737420612070617274207468617460448201527f20726571756972657320747265617375726520747269616400000000000000006064820152608401610738565b505080806133da90616bee565b915050613249565b50856080015151866060015151146134335760405162461bcd60e51b8152602060048201526014602482015273426164207472656173757265206c656e6774687360601b6044820152606401610738565b80158061344557506000866060015151115b61349d5760405162461bcd60e51b8152602060048201526024808201527f4e65656420747265617375726520746f20706c617920747265617375726520746044820152631c9a585960e21b6064820152608401610738565b6000806134ae886020015185613c5d565b905060005b8860600151518110156135f8576000896060015182815181106134d8576134d8616bc2565b602002602001015111801561350a575060008960800151828151811061350057613500616bc2565b6020026020010151115b6135565760405162461bcd60e51b815260206004820152601960248201527f426164207472656173757265206964206f7220616d6f756e74000000000000006044820152606401610738565b8860800151818151811061356c5761356c616bc2565b60200260200101518361357f9190617b55565b92508160ff168311156135e65760405162461bcd60e51b815260206004820152602960248201527f546f6f206d616e792074726561737572657320666f7220636f6e7374656c6c6160448201526874696f6e2072616e6b60b81b6064820152608401610738565b806135f081616bee565b9150506134b3565b50610192546040805163433c53d960e11b815290516000926001600160a01b031691638678a7b291600480830192602092919082900301818787803b15801561364057600080fd5b505af1158015613654573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136789190616d36565b60008881526101a06020908152604090912080546001600160781b031916426001600160781b031617815560018101805469ffffffffffffffffffff60a01b1916600160a01b69ffffffffffffffffffff8616021790558b82015180519394506136e99360029092019201906161eb565b5060008781526101a0602052604090819020600181018054928c01517fff00ffffffffffffffffffff00000000000000000000000000000000000000009093163360ff60f01b191617600160f01b60ff90941693909302929092176001600160f81b031690915580546001600160781b0316905561376689614a3a565b876137d757610194546040516383291f8760e01b8152336004820152306024820152604481018990526001600160a01b03909116906383291f8790606401600060405180830381600087803b1580156137be57600080fd5b505af11580156137d2573d6000803e3d6000fd5b505050505b871580156137ea57506000896060015151115b15613861576101965460608a015160808b0151604051631759616b60e11b81526001600160a01b0390931692632eb2c2d69261382e92339230929190600401617c25565b600060405180830381600087803b15801561384857600080fd5b505af115801561385c573d6000803e3d6000fd5b505050505b7f6c0d8f3939be2a5b9dcf5ce392c338774f1e1fce2cfa6a61a9ad81ad1dd3dd1933828b60405161389493929190617c80565b60405180910390a1505050505050505050565b600082815261019f60205260408120541515906138c48285613c27565b80546138cf90617976565b80601f01602080910402602001604051908101604052809291908181526020018280546138fb90617976565b80156139485780601f1061391d57610100808354040283529160200191613948565b820191906000526020600020905b81548152906001019060200180831161392b57829003601f168201915b5050610195546040516378afdef960e11b8152600481018a90529495506000946001600160a01b03909116935063f15fbdf2925060240190506101806040518083038186803b15801561399a57600080fd5b505afa1580156139ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139d29190616df7565b9050600061019c836040516139e79190616cd2565b908152604051908190036020019020905033613a038588613f57565b6001600160a01b031614613a295760405162461bcd60e51b8152600401610738906179b1565b610192546000906001600160a01b0316634ad30a75613a48878a613d38565b6040518263ffffffff1660e01b8152600401613a6691815260200190565b60206040518083038186803b158015613a7e57600080fd5b505afa158015613a92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ab69190616d36565b9050613ac88785878686866001613fa1565b613ad687868585858b614401565b50505050505050565b600081604051602001613af29190616cd2565b6040516020818303038152906040528051906020012083604051602001613b199190616cd2565b6040516020818303038152906040528051906020012014905092915050565b60655460ff1615613b5b5760405162461bcd60e51b815260040161073890616b44565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613b903390565b6040516001600160a01b03909116815260200160405180910390a1565b60655460ff16613bf65760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610738565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33613b90565b600082613c455760008281526101a06020526040902060020161205c565b50600090815261019f60205260409020600701919050565b6000808260a0015161019c85604051613c769190616cd2565b9081526040519081900360200190206001015460ff62010000909104166005811115613ca457613ca4616510565b60068110613cb457613cb4616bc2565b6020020151905060008360a0015161019c86604051613cd39190616cd2565b9081526040519081900360200190206001015460ff6301000000909104166005811115613d0257613d02616510565b60068110613d1257613d12616bc2565b602002015190508060ff168260ff161115613d2f5750905061070f565b915061070f9050565b600082613d6a5760008281526101a06020526040902060010154600160a01b900469ffffffffffffffffffff1661205c565b50600090815261019f6020526040902060010154919050565b600080613d8f88610a0d565b613dd45760405162461bcd60e51b81526020600482015260166024820152754c6567696f6e206973206e6f74207175657374696e6760501b6044820152606401610738565b6000613de0888a61505c565b90506000613dee898b6150a1565b90506000613dfc8a8c614103565b90506000613e0a8b8d6150e3565b905061019c8a604051613e1d9190616cd2565b908152604051908190036020019020600201613e3a600184617bc7565b60ff1681548110613e4d57613e4d616bc2565b906000526020600020906004020160020160039054906101000a900460ff168015613e785750600084115b8015613e87575060008360ff16115b8015613ecf575061019d60008a600001516002811115613ea957613ea9616510565b6002811115613eba57613eba616510565b815260208101919091526040016000205460ff165b15613efd5761019b54613ee59060ff8516617166565b613eef9085617b55565b839550955050505050613f4c565b6000613f2b61019c8c604051613f139190616cd2565b90815260200160405180910390208b8a8c868861512f565b9650905080613f3a8d8f615297565b613f449190617b55565b965050505050505b965096945050505050565b600082613f7f5760008281526101a060205260409020600101546001600160a01b031661205c565b50600090815261019f60205260409020600801546001600160a01b0316919050565b6000613fad8786613c5d565b90506000613fbf89888a898689613d83565b5090508042101561402c5760405162461bcd60e51b815260206004820152603160248201527f4c6567696f6e20686173206e6f742066696e69736865642074686973207061726044820152701d081bd9881d1a19481e9bdb99481e595d607a1b6064820152608401610738565b8280156140815750846002016001614044898c614103565b61404e9190617bc7565b60ff168154811061406157614061616bc2565b906000526020600020906004020160020160039054906101000a900460ff165b80156140945750614092878a61505c565b155b156140f85760405162461bcd60e51b815260206004820152602e60248201527f486173206e6f7420706c6179656420747265617375726520747269616420666f60448201526d1c8818dd5c9c995b9d081c185c9d60921b6064820152608401610738565b505050505050505050565b60008261412c5760008281526101a06020526040902060010154600160f01b900460ff1661205c565b50600090815261019f6020526040902060080154600160a01b900460ff16919050565b6000826141795760008281526101a06020526040902060030154610100900461ffff16151561205c565b600082815261019f60205260408120614194906004016152d2565b119392505050565b82158015906141ab5750600483105b6142025760405162461bcd60e51b815260206004820152602260248201527f426164206e756d626572206f66207472656173757265207472696164206d6f76604482015261657360f01b6064820152608401610738565b6000836001600160401b0381111561421c5761421c61633a565b60405190808252806020026020018201604052801561426157816020015b604080518082019091526000808252602082015281526020019060019003908161423a5790505b5090506000805b85811015613ad657600087878381811061428457614284616bc2565b905060600201604001359050600061429d8288886152dc565b90506000805b865181101561439857838782815181106142bf576142bf616bc2565b602002602001015160000151141561438657600191508681815181106142e7576142e7616bc2565b602002602001015160200151600014156143535760405162461bcd60e51b815260206004820152602760248201527f55736564206d6f7265207472656173757265207468616e207768617420776173604482015266081cdd185ad95960ca1b6064820152608401610738565b86818151811061436557614365616bc2565b6020026020010151602001805180919061437e90617d1f565b905250614398565b8061439081616bee565b9150506142a3565b50806143eb5760405180604001604052808481526020016001846143bc9190617bb0565b8152508686815181106143d1576143d1616bc2565b602002602001018190525084806143e790616bee565b9550505b50505080806143f990616bee565b915050614268565b600061440d8688614103565b61019354606087015160ff83811660009081526101a3602052604090819020549051630a39d94760e11b8152600481018d905291909216602482015260448101919091529192506001600160a01b031690631473b28e90606401600060405180830381600087803b15801561448157600080fd5b505af1158015614495573d6000803e3d6000fd5b5050505060006144a9888884888a8961553e565b905086156144c657600088815261019f60205260408120556144e4565b60008881526101a06020526040902080546001600160781b03191690555b8261455557610194546040516383291f8760e01b8152306004820152336024820152604481018a90526001600160a01b03909116906383291f8790606401600060405180830381600087803b15801561453c57600080fd5b505af1158015614550573d6000803e3d6000fd5b505050505b6000806145638a8a87615633565b915091507f9949f99e59b9a76e12491767b7369cea6085b2e0f953d867d6a20484c12b105c338b8560405161459a93929190616fb0565b60405180910390a18415612b4b57612b4b6040518060a001604052808c81526020016145c68c8e613c27565b80546145d190617976565b80601f01602080910402602001604051908101604052809291908181526020018280546145fd90617976565b801561464a5780601f1061461f5761010080835404028352916020019161464a565b820191906000526020600020905b81548152906001019060200180831161462d57829003601f168201915b505050505081526020018660ff1681526020018481526020018381525086613029565b6003810154600090600114156146a8578160030160008154811061469357614693616bc2565b9060005260206000209060040201905061070f565b60006146b661010085617b6d565b90506000600885901c945060005b600385015481101561473a5760008560030182815481106146e7576146e7616bc2565b6000918252602090912060049091020160038101549091506147129062010000900460ff1684617b55565b92508284101561472757935061070f92505050565b508061473281616bee565b9150506146c4565b5060405162461bcd60e51b815260206004820152601860248201527f426164206f64647320666f72207a6f6e652072657761726400000000000000006044820152606401610738565b6147ae6040518060800160405280600081526020016000815260200160008152602001600081525090565b8354158015906147c2575060008460010154115b1561483e57835480825260018501546020830181905261019754604051630ab714fb60e11b81526001600160a01b039091169263156e29f69261480b9287929190600401617b8f565b600060405180830381600087803b15801561482557600080fd5b505af1158015614839573d6000803e3d6000fd5b505050505b6002840154156148bb576002840154604080830182905261019a549051630ab714fb60e11b81526001600160a01b039091169163156e29f691614888918691600190600401617b8f565b600060405180830381600087803b1580156148a257600080fd5b505af11580156148b6573d6000803e3d6000fd5b505050505b600384015460ff161561205c576101985460038501546040516302c01b2760e51b81526000926001600160a01b03169163580364e09161490d9160ff8082169261010090920416908990600401617d36565b60206040518083038186803b15801561492557600080fd5b505afa158015614939573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061495d9190616d36565b6060830181905261019654604051630ab714fb60e11b81529192506001600160a01b03169063156e29f69061499b9086908590600190600401617b8f565b600060405180830381600087803b1580156149b557600080fd5b505af11580156149c9573d6000803e3d6000fd5b50505050509392505050565b600054610100900460ff166149f05760005460ff16156149f4565b303b155b614a105760405162461bcd60e51b815260040161073890617056565b600054610100900460ff16158015614a32576000805461ffff19166101011790555b611677615bc8565b604080516101e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081019190915260608201515160ff811682528015614b1a578260600151600081518110614adc57614adc616bc2565b60209081029190910181015161ffff169083015260808301518051600090614b0657614b06616bc2565b602090810291909101015160ff1660408301525b6001811115614b7a578260600151600181518110614b3a57614b3a616bc2565b602090810291909101015161ffff166060830152608083015180516001908110614b6657614b66616bc2565b602090810291909101015160ff1660808301525b6002811115614bda578260600151600281518110614b9a57614b9a616bc2565b602090810291909101015161ffff1660a0830152608083015180516002908110614bc657614bc6616bc2565b602090810291909101015160ff1660c08301525b6003811115614c3b578260600151600381518110614bfa57614bfa616bc2565b602090810291909101015161ffff1660e0830152608083015180516003908110614c2657614c26616bc2565b602090810291909101015160ff166101008301525b6004811115614c9d578260600151600481518110614c5b57614c5b616bc2565b602090810291909101015161ffff16610120830152608083015180516004908110614c8857614c88616bc2565b602090810291909101015160ff166101408301525b6005811115614cff578260600151600581518110614cbd57614cbd616bc2565b602090810291909101015161ffff16610160830152608083015180516005908110614cea57614cea616bc2565b602090810291909101015160ff166101808301525b6006811115614d61578260600151600681518110614d1f57614d1f616bc2565b602090810291909101015161ffff166101a0830152608083015180516006908110614d4c57614d4c616bc2565b602090810291909101015160ff166101c08301525b60005b81811015614e33576000614d79826001617b55565b90505b82811015614e205784606001518181518110614d9a57614d9a616bc2565b602002602001015185606001518381518110614db857614db8616bc2565b60200260200101511415614e0e5760405162461bcd60e51b815260206004820152601e60248201527f4475706c696361746520747265617375726520696420696e20617272617900006044820152606401610738565b80614e1881616bee565b915050614d7c565b5080614e2b81616bee565b915050614d64565b50816101a060008560000151815260200190815260200160002060030160008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548160ff021916908360ff16021790555060608201518160000160046101000a81548161ffff021916908361ffff16021790555060808201518160000160066101000a81548160ff021916908360ff16021790555060a08201518160000160076101000a81548161ffff021916908361ffff16021790555060c08201518160000160096101000a81548160ff021916908360ff16021790555060e082015181600001600a6101000a81548161ffff021916908361ffff16021790555061010082015181600001600c6101000a81548160ff021916908360ff16021790555061012082015181600001600d6101000a81548161ffff021916908361ffff16021790555061014082015181600001600f6101000a81548160ff021916908360ff1602179055506101608201518160000160106101000a81548161ffff021916908361ffff1602179055506101808201518160000160126101000a81548160ff021916908360ff1602179055506101a08201518160000160136101000a81548161ffff021916908361ffff1602179055506101c08201518160000160156101000a81548160ff021916908360ff160217905550905050505050565b6000826150885760008281526101a06020526040902054600160781b90046001600160781b031661205c565b50600090815261019f6020526040902060020154919050565b6000826150c75760008281526101a06020526040902054600160f01b900460ff1661205c565b50600090815261019f602052604090206003015460ff16919050565b60008261510c5760008281526101a06020526040902060010154600160f81b900460ff1661205c565b50600090815261019f6020526040902060080154600160a81b900460ff16919050565b60ff808416600090815261019e60205260408120549091829181169085165b8460ff1681101561528a5789600201818154811061516e5761516e616bc2565b9060005260206000209060040201600001548461518b9190617b55565b935061019d60008a6000015160028111156151a8576151a8616510565b60028111156151b9576151b9616510565b815260208101919091526040016000205460ff16156152785760008a60020182815481106151e9576151e9616bc2565b600091825260209091206002600490920201015460ff90811691508316811115615276576152178382617bc7565b60ff166152266101008b617b6d565b101561526e578361523681617a48565b9450508a600201828154811061524e5761524e616bc2565b9060005260206000209060040201600101548561526b9190617b55565b94505b600889901c98505b505b8061528281616bee565b91505061514e565b5050965096945050505050565b6000826152bc5760008281526101a060205260409020546001600160781b031661205c565b50600090815261019f6020526040902054919050565b600061070f825490565b6000821561534057600082815261019f602052604090206153009060040185615ecb565b61531c5760405162461bcd60e51b815260040161073890617d5a565b50600081815261019f6020908152604080832086845260060190915290205461205c565b60008281526101a0602081815260409283902083516101e08101855260039091015460ff808216835261ffff610100808404821695850195909552630100000083048216968401969096526401000000008204861660608401526601000000000000820481166080840152600160381b8204861660a0840152600160481b8204811660c0840152600160501b8204861660e0840152600160601b8204811693830193909352600160681b81048516610120830152600160781b81048316610140830152600160801b81048516610160830152600160901b81048316610180830152600160981b810490941692810192909252600160a81b9092049091166101c08201528461544d57600080fd5b84816020015161ffff16141561546b576040015160ff16905061205c565b84816060015161ffff161415615489576080015160ff16905061205c565b848160a0015161ffff1614156154a75760c0015160ff16905061205c565b848160e0015161ffff1614156154c657610100015160ff16905061205c565b8481610120015161ffff1614156154e657610140015160ff16905061205c565b8481610160015161ffff16141561550657610180015160ff16905061205c565b84816101a0015161ffff161415615526576101c0015160ff16905061205c565b60405162461bcd60e51b815260040161073890617d5a565b606061562861554d8789613c27565b805461555890617976565b80601f016020809104026020016040519081016040528092919081815260200182805461558490617976565b80156155d15780601f106155a6576101008083540402835291602001916155d1565b820191906000526020600020905b8154815290600101906020018083116155b457829003601f168201915b50505050506001876155e39190617bc7565b60ff16600287016155f560018a617bc7565b60ff168154811061560857615608616bc2565b90600052602060002090600402018633876156238d8f615ee3565b612bcd565b979650505050505050565b606080606080851561572457600087815261019f6020526040902061565a90600401615f2a565b915081516001600160401b038111156156755761567561633a565b60405190808252806020026020018201604052801561569e578160200160208202803683370190505b50905060005b825181101561571e5761019f600089815260200190815260200160002060060160008483815181106156d8576156d8616bc2565b602002602001015181526020019081526020016000205482828151811061570157615701616bc2565b60209081029190910101528061571681616bee565b9150506156a4565b50615b3e565b60008781526101a0602081815260409283902083516101e08101855260039091015460ff80821680845261010080840461ffff90811696860196909652630100000084048316978501979097526401000000008304851660608501526601000000000000830482166080850152600160381b8304851660a0850152600160481b8304821660c0850152600160501b8304851660e0850152600160601b8304821696840196909652600160681b82048416610120840152600160781b82048116610140840152600160801b82048416610160840152600160901b82048116610180840152600160981b820490931693820193909352600160a81b909204166101c082015290806001600160401b038111156158405761584061633a565b604051908082528060200260200182016040528015615869578160200160208202803683370190505b5093508060ff166001600160401b038111156158875761588761633a565b6040519080825280602002602001820160405280156158b0578160200160208202803683370190505b50925060ff81161561590c57816020015161ffff16846000815181106158d8576158d8616bc2565b602002602001018181525050816040015160ff16836000815181106158ff576158ff616bc2565b6020026020010181815250505b60018160ff16111561596857816060015161ffff168460018151811061593457615934616bc2565b602002602001018181525050816080015160ff168360018151811061595b5761595b616bc2565b6020026020010181815250505b60028160ff1611156159c4578160a0015161ffff168460028151811061599057615990616bc2565b6020026020010181815250508160c0015160ff16836002815181106159b7576159b7616bc2565b6020026020010181815250505b60038160ff161115615a21578160e0015161ffff16846003815181106159ec576159ec616bc2565b60200260200101818152505081610100015160ff1683600381518110615a1457615a14616bc2565b6020026020010181815250505b60048160ff161115615a7f5781610120015161ffff1684600481518110615a4a57615a4a616bc2565b60200260200101818152505081610140015160ff1683600481518110615a7257615a72616bc2565b6020026020010181815250505b60058160ff161115615add5781610160015161ffff1684600581518110615aa857615aa8616bc2565b60200260200101818152505081610180015160ff1683600581518110615ad057615ad0616bc2565b6020026020010181815250505b60068160ff161115615b3b57816101a0015161ffff1684600681518110615b0657615b06616bc2565b602002602001018181525050816101c0015160ff1683600681518110615b2e57615b2e616bc2565b6020026020010181815250505b50505b84158015615b4d575060008251115b15615bbc5761019654604051631759616b60e11b81526001600160a01b0390911690632eb2c2d690615b89903090339087908790600401617c25565b600060405180830381600087803b158015615ba357600080fd5b505af1158015615bb7573d6000803e3d6000fd5b505050505b90969095509350505050565b600054610100900460ff16615be35760005460ff1615615be7565b303b155b615c035760405162461bcd60e51b815260040161073890617056565b600054610100900460ff16158015615c25576000805461ffff19166101011790555b615c2d615f37565b615c35615f9c565b615c3d615f9c565b6201518061019b557f13dcb3c6205eccc5df5a4a7821d488c75d9d361908855b59d022fe13c7bb4f1d805460ff199081169091557f228719b3ab53201bbb41968c40b0b5cdf287f8c98ba3ec9532f722219a6d86ff8054821660019081179091557f2d695d1bdc89be0990c9b1cefd0e589f7fbb3368bfb8d91126956a95dcf1607380548316600a9081179091557f1482f8fde77c2e0a1223b839dd85e5e0d40575a23bb6b13896f241a0b36fe0d880548416600f1790557f819c8b3e70c1a841f15170a81b2fad3b9dd6363490e4d79d5e443edaf01bbd658054841660149081179091557ff166615731f9a0da5f995c890da9823aee980021e1f67a3a50824b9391ea855f8054851660171790557f5fc73781db4fef9135a7751bb16b9dc0cf5d8f49924b6290e697d3ce5362e55b8054851660261790557f0c0534c4fd269d874c4e3ccf61cdfc386596ea47184f1d857725cfeaab13fd508054851660331790557f52fc7babecae6ce4e4dc8870a20313c060d91987e43bc7d10bf81d0e02b5bebc805460409516851790556101a360209081527ea6105fd2503f629683224b65ba1a1aa197137922f1053ab400f69d8246ddf98390557fcb77f04b1e92abe5d71426bab37a70753e0413ae4da109a6065d514b684219d291909155600360005260287fb05e572c3921facf13d4b7cacb7d6a98218537e6faccf664e60dbbbc40fd0ba75583519283528201528151600080516020617dee833981519152929181900390910190a1604080516002815260146020820152600080516020617dee833981519152910160405180910390a1604080516003815260286020820152600080516020617dee833981519152910160405180910390a18015611689576000805461ff001916905550565b6000818152600183016020526040812054151561205c565b600082615f095760008281526101a06020526040902054600160f81b900460ff1661205c565b50600090815261019f6020526040902060030154610100900460ff16919050565b6060600061205c83615fc3565b600054610100900460ff16615f525760005460ff1615615f56565b303b155b615f725760405162461bcd60e51b815260040161073890617056565b600054610100900460ff16158015615f94576000805461ffff19166101011790555b61167761601f565b600054610100900460ff16610dca5760405162461bcd60e51b815260040161073890617da2565b60608160000180548060200260200160405190810160405280929190818152602001828054801561601357602002820191906000526020600020905b815481526020019060010190808311615fff575b50505050509050919050565b600054610100900460ff1661603a5760005460ff161561603e565b303b155b61605a5760405162461bcd60e51b815260040161073890617056565b600054610100900460ff1615801561607c576000805461ffff19166101011790555b616084616094565b61608c6160c3565b611677613b38565b600054610100900460ff166160bb5760405162461bcd60e51b815260040161073890617da2565b610dca6160f2565b600054610100900460ff166160ea5760405162461bcd60e51b815260040161073890617da2565b610dca616122565b600054610100900460ff166161195760405162461bcd60e51b815260040161073890617da2565b610dca33612b7b565b600054610100900460ff166161495760405162461bcd60e51b815260040161073890617da2565b6065805460ff19169055565b6001830191839082156161db5791602002820160005b838211156161ac57833560ff1683826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030261616b565b80156161d95782816101000a81549060ff02191690556001016020816000010492830192600103026161ac565b505b506161e792915061625f565b5090565b8280546161f790617976565b90600052602060002090601f01602090048101928261621957600085556161db565b82601f1061623257805160ff19168380011785556161db565b828001600101855582156161db579182015b828111156161db578251825591602001919060010190616244565b5b808211156161e75760008155600101616260565b60006020828403121561628657600080fd5b81356001600160e01b03198116811461205c57600080fd5b60008083601f8401126162b057600080fd5b5081356001600160401b038111156162c757600080fd5b6020830191508360208260051b85010111156162e257600080fd5b9250929050565b600080602083850312156162fc57600080fd5b82356001600160401b0381111561631257600080fd5b615bbc8582860161629e565b80356001600160a01b038116811461633557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b03811182821017156163725761637261633a565b60405290565b60405160a081016001600160401b03811182821017156163725761637261633a565b604051601f8201601f191681016001600160401b03811182821017156163c2576163c261633a565b604052919050565b600082601f8301126163db57600080fd5b81356001600160401b038111156163f4576163f461633a565b616407601f8201601f191660200161639a565b81815284602083860101111561641c57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561644f57600080fd5b6164588561631e565b93506164666020860161631e565b92506040850135915060608501356001600160401b0381111561648857600080fd5b616494878288016163ca565b91505092959194509250565b6000602082840312156164b257600080fd5b61205c8261631e565b6000602082840312156164cd57600080fd5b81356001600160401b038111156164e357600080fd5b6164ef848285016163ca565b949350505050565b60006020828403121561650957600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6006811061168957611689616510565b85815260a0810161654686616526565b85602083015261655585616526565b84604083015261656484616526565b83606083015261657383616526565b8260808301529695505050505050565b60008083601f84011261659557600080fd5b5081356001600160401b038111156165ac57600080fd5b6020830191508360208285010111156162e257600080fd5b60008060008060006101408087890312156165de57600080fd5b86356001600160401b038111156165f457600080fd5b61660089828a01616583565b909750955050602087013593506040870135925080870188101561662357600080fd5b506060860190509295509295909350565b6000806020838503121561664757600080fd5b82356001600160401b038082111561665e57600080fd5b818501915085601f83011261667257600080fd5b81358181111561668157600080fd5b8660208260061b850101111561669657600080fd5b60209290920196919550909350505050565b600080600080600080606087890312156166c157600080fd5b86356001600160401b03808211156166d857600080fd5b6166e48a838b01616583565b909850965060208901359150808211156166fd57600080fd5b6167098a838b0161629e565b9096509450604089013591508082111561672257600080fd5b5061672f89828a0161629e565b979a9699509497509295939492505050565b6000806000806040858703121561675757600080fd5b84356001600160401b038082111561676e57600080fd5b61677a8883890161629e565b9096509450602087013591508082111561679357600080fd5b506167a08782880161629e565b95989497509550505050565b60008060008060008060008060006101208a8c0312156167cb57600080fd5b6167d48a61631e565b98506167e260208b0161631e565b97506167f060408b0161631e565b96506167fe60608b0161631e565b955061680c60808b0161631e565b945061681a60a08b0161631e565b935061682860c08b0161631e565b925061683660e08b0161631e565b91506168456101008b0161631e565b90509295985092959850929598565b60008060006040848603121561686957600080fd5b83356001600160401b038082111561688057600080fd5b61688c87838801616583565b909550935060208601359150808211156168a557600080fd5b50840160c081870312156168b857600080fd5b809150509250925092565b600082601f8301126168d457600080fd5b813560206001600160401b038211156168ef576168ef61633a565b8160051b6168fe82820161639a565b928352848101820192828101908785111561691857600080fd5b83870192505b848310156156285782358252918301919083019061691e565b600080600080600060a0868803121561694f57600080fd5b6169588661631e565b94506169666020870161631e565b935060408601356001600160401b038082111561698257600080fd5b61698e89838a016168c3565b945060608801359150808211156169a457600080fd5b6169b089838a016168c3565b935060808801359150808211156169c657600080fd5b506169d3888289016163ca565b9150509295509295909350565b801515811461168957600080fd5b600060208284031215616a0057600080fd5b813561205c816169e0565b60ff8116811461168957600080fd5b803561633581616a0b565b600080600060408486031215616a3a57600080fd5b83356001600160401b03811115616a5057600080fd5b616a5c86828701616583565b90945092505060208401356168b881616a0b565b600060208284031215616a8257600080fd5b813561205c81616a0b565b600080600080600060a08688031215616aa557600080fd5b616aae8661631e565b9450616abc6020870161631e565b9350604086013592506060860135915060808601356001600160401b03811115616ae557600080fd5b6169d3888289016163ca565b60008060008060808587031215616b0757600080fd5b84356001600160401b03811115616b1d57600080fd5b616b29878288016163ca565b97602087013597506040870135966060013595509350505050565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b60208082526014908201527310dbdb9d1c9858dd1cc8185c995b89dd081cd95d60621b604082015260600190565b6020808252600c908201526b4e6f20636f6e74726163747360a01b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415616c0257616c02616bd8565b5060010190565b60008235605e19833603018112616c1f57600080fd5b9190910192915050565b6000808335601e19843603018112616c4057600080fd5b8301803591506001600160401b03821115616c5a57600080fd5b60200191506060810236038213156162e257600080fd5b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60005b83811015616cc1578181015183820152602001616ca9565b838111156108355750506000910152565b60008251616c1f818460208701616ca6565b6020808252601290820152712737ba1030b236b4b71037b91037bbb732b960711b604082015260600190565b8183823760009101908152919050565b60008235609e19833603018112616c1f57600080fd5b600060208284031215616d4857600080fd5b5051919050565b8051600a811061633557600080fd5b6006811061168957600080fd5b805161633581616d5e565b805161633581616a0b565b600082601f830112616d9257600080fd5b60405160c081018181106001600160401b0382111715616db457616db461633a565b6040528060c0840185811115616dc957600080fd5b845b81811015616dec578051616dde81616a0b565b835260209283019201616dcb565b509195945050505050565b60006101808284031215616e0a57600080fd5b616e12616350565b825160038110616e2157600080fd5b8152616e2f60208401616d4f565b6020820152616e4060408401616d6b565b6040820152616e5160608401616d76565b6060820152616e6260808401616d76565b6080820152616e748460a08501616d81565b60a0820152610160929092015160c083015250919050565b6000808335601e19843603018112616ea357600080fd5b8301803591506001600160401b03821115616ebd57600080fd5b6020019150368190038213156162e257600080fd5b6000808335601e19843603018112616ee957600080fd5b8301803591506001600160401b03821115616f0357600080fd5b6020019150600581901b36038213156162e257600080fd5b81835260006001600160fb1b03831115616f3457600080fd5b8260051b8083602087013760009401602001938452509192915050565b6001600160a01b0387811682528616602082015260a060408201819052600090616f7e9083018688616f1b565b8281036060840152616f91818587616f1b565b8381036080909401939093525050600081526020019695505050505050565b6001600160a01b03841681526020808201849052606060408084018290528451848301819052600093608092909183870190888401875b8281101561701c5781518051855286810151878601528581015186860152880151888501529286019290850190600101616fe7565b50919b9a5050505050505050505050565b60006020828403121561703f57600080fd5b81356001600160f81b038116811461205c57600080fd5b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b600060a082360312156170b657600080fd5b6170be616378565b8235815260208301356001600160401b03808211156170dc57600080fd5b6170e8368387016163ca565b60208401526170f960408601616a1a565b6040840152606085013591508082111561711257600080fd5b61711e368387016168c3565b6060840152608085013591508082111561713757600080fd5b50617144368286016168c3565b60808301525092915050565b6000823560de19833603018112616c1f57600080fd5b600081600019048311821515161561718057617180616bd8565b500290565b8054600080835581156109925782815260208120601f830160051c81015b80821015611d3e578282556001820191506171a3565b600160401b8211156171cd576171cd61633a565b80548282558083101561099257600082815260208120601f850160051c8101601f840160051c82019150601f86168015617218576000198083018054828460200360031b1c16815550505b505b81811015611a7f5782815560010161721a565b8054600082558015617262578160005260206000208181015b808210156108355761725782617185565b600182019150617246565b5050565b600160401b82111561727a5761727a61633a565b805482825580831015610992576000828152602090208381019082015b80821015611d3e576172a882617185565b600182019150617297565b8054600080835581156109925760016001600160fe1b0383118116156172db576172db616bd8565b60028483526020832084821b81015b80821015613ad657848255848483015584838301558460038301556004820191506172ea565b600160401b8211156173245761732461633a565b805482825580831015610992576001600160fe1b03600181831181161561734d5761734d616bd8565b600282861182161561736157617361616bd8565b60008581526020812090935086821b81019085831b015b80821015610cfb5784825584848301558483830155846003830155600482019150617378565b8054600080835581156109925760016001600160fe1b0383118116156173c6576173c6616bd8565b60028483526020832084821b81015b80821015613ad6578482556173eb84830161722d565b84838301556173fc600383016172b3565b6004820191506173d5565b600160401b82111561741b5761741b61633a565b805482825580831015610992576001600160fe1b03600181831181161561744457617444616bd8565b600282861182161561745857617458616bd8565b60008581526020812090935086821b81019085831b015b80821015610cfb5784825561748584830161722d565b8483830155617496600383016172b3565b60048201915061746f565b6000813561070f81616a0b565b6000808335601e198436030181126174c557600080fd5b8301803591506001600160401b038211156174df57600080fd5b602001915060c0810236038213156162e257600080fd5b6175008382617310565b818160005260208060002060005b86811015613ad657833582558284013560018301556040840135600283015560038201606085013561753f81616a0b565b815460ff191660ff821617825550608085013561755b81616d5e565b61756481616526565b815461ff001916600882901b61ff00161782555060a085013561758681616a0b565b815462ff00001916601082901b62ff000016178255505060c093909301926004919091019060010161750e565b81358155602082013560018201556002810160408301356175d381616a0b565b815460ff191660ff82161782555060608301356175ef81616a0b565b815461ff001916600882901b61ff0016179050808255608084013561761381616a0b565b62ff0000601082901b1662ff00001983161791505080825560a0840135617639816169e0565b63ff000000199190911690151560181b63ff0000001617905561765f60c0830183616ed2565b61766c8160038501617407565b81600060038501815260208120815b84811015610cfb57607e1986360301843512617695578283fd5b833586016176a38135616a0b565b825460ff191660ff823516178355600183016176c26020830183616ed2565b6176cc8184617266565b918652602086209181875b8281101561776f576176e98285616ed2565b6176f381886171b9565b868b5260208b208b8c5b838110156177535761770f8535616a0b565b82548260031b60ff811b8060ff893516831b1681198416178655505050602085019450600182019150601f82111561774b578d91506001830192505b6001016176fd565b50505050506020820191506001850194506001810190506176d7565b5050505050617798617783604083016174a1565b6002850160ff821660ff198254161781555050565b6177a560608201826174ae565b91506177b58282600387016174f6565b5050602093909301926004919091019060010161767b565b8135815560018082016020808501356177e581616d5e565b6177ee81616526565b60ff1983541660ff82168117915050808355604086013561780e81616d5e565b61781781616526565b61ff00600882901b1661ff0019831617915050808355606086013561783b81616d5e565b61784481616526565b62ff0000601082901b1662ff000019831617915050808355608086013561786a81616d5e565b61787381616526565b63ff000000601882901b1663ff00000019831617845550506002915081840161789f60a0870187616ed2565b600160401b8111156178b3576178b361633a565b825481845580821015617930576001600160fe1b038082118816156178da576178da616bd8565b8083118816156178ec576178ec616bd8565b50600084815285812083881b81019083891b015b8082101561792c57828255828a83015582898301556179216003830161739e565b600482019150617900565b5050505b508194506179448360009081526020902090565b925060005b818110156140f85761796461795e8785617150565b856175b3565b94840194600493909301928601617949565b600181811c9082168061798a57607f821691505b602082108114156179ab57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252601390820152724c6567696f6e206973206e6f7420796f75727360681b604082015260600190565b600060ff821660ff84168060ff038211156179fb576179fb616bd8565b019392505050565b60208082526025908201527f4c6567696f6e206e6f74206869676820656e6f756768207175657374696e67206040820152641b195d995b60da1b606082015260800190565b600060ff821660ff811415617a5f57617a5f616bd8565b60010192915050565b600060608083018784526020600a8810617a8457617a84616510565b84810188905260408086018490529186905286916080860160005b88811015612fb4578435617ab281616a0b565b60ff90811683528585013590617ac782616a0b565b168285015284830135838301529385019390850190600101617a9f565b600060608284031215617af657600080fd5b604051606081018181106001600160401b0382111715617b1857617b1861633a565b6040528251617b2681616a0b565b81526020830151617b3681616a0b565b60208201526040830151617b49816169e0565b60408201529392505050565b60008219821115617b6857617b68616bd8565b500190565b600082617b8a57634e487b7160e01b600052601260045260246000fd5b500690565b6001600160a01b039390931683526020830191909152604082015260600190565b600082821015617bc257617bc2616bd8565b500390565b600060ff821660ff841680821015617be157617be1616bd8565b90039392505050565b600081518084526020808501945080840160005b83811015617c1a57815187529582019590820190600101617bfe565b509495945050505050565b6001600160a01b0385811682528416602082015260a060408201819052600090617c5190830185617bea565b8281036060840152617c638185617bea565b838103608090940193909352505060008152602001949350505050565b60018060a01b038416815282602082015260606040820152815160608201526000602083015160a06080840152805180610100850152610120617cc98282870160208601616ca6565b601f19601f8301168501925060ff60408701511660a08601526060860151915060c08584030160c0860152617d0081840183617bea565b925050506080840151605f198483030160e08501526156288282617bea565b600081617d2e57617d2e616bd8565b506000190190565b60ff8416815260608101617d4984616526565b602082019390935260400152919050565b60208082526028908201527f43616e6e6f7420706c6179207472656173757265207468617420776173206e6f6040820152671d081cdd185ad95960c21b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fe46e94ca82929a29fb265e8a82065128e24df1a088936385add2bcce27623f651a26469706673582212206bf49ff0ce1bbc727abae5b6c6559ead58cc48a8c25a714838b047f6ae718db264736f6c63430008090033
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.