Contract Overview
Balance:
0 ETH
ETH Value:
$0.00
My Name Tag:
Not Available
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0x1c30b83d3b3e4dcbf8edf6b4a6fbdc9102037f4f54723cd31dfe538f3104b0bc | 0x60806040 | 11861970 | 268 days 18 hrs ago | 0xb013abd83f0bd173e9f14ce7d6e420ad711483b4 | IN | Create: AdvancedQuesting | 0 ETH | 0.122485626858 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]); } } function _startAdvancedQuesting(StartQuestParams calldata _startQuestParams) 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); // Transfer legion and treasure to this contract. legion.adminSafeTransferFrom(msg.sender, address(this), _legionId); if(_startQuestParams.treasureIds.length > 0) { treasure.safeBatchTransferFrom( msg.sender, address(this), _startQuestParams.treasureIds, _startQuestParams.treasureAmounts, ""); } emit AdvancedQuestStarted( msg.sender, _requestId, _startQuestParams); } function _saveStakedTreasures( StartQuestParams calldata _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]; 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); } // Ends questing at the current part. Must have played triad if triad is required on current part. function endQuesting( uint256[] calldata _legionIds) external whenNotPaused contractsAreSet onlyEOA nonZeroLength(_legionIds) { for(uint256 i = 0; i < _legionIds.length; i++) { _endQuesting(_legionIds[i]); } } function _endQuesting(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); _endQuestingPostValidation(_legionId, _usingOldSchema, _legionMetadata, _zoneInfo, _randomNumber); } function _endQuestingPostValidation( uint256 _legionId, bool _usingOldSchema, LegionMetadata memory _legionMetadata, ZoneInfo storage _zoneInfo, uint256 _randomNumber) private { questing.processQPGainAndLevelUp(_legionId, _legionMetadata.questLevel); AdvancedQuestReward[] memory _earnedRewards = _distributeRewards(_legionId, _usingOldSchema, _legionMetadata, _zoneInfo, _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; } // Send back legion and treasure legion.adminSafeTransferFrom(address(this), msg.sender, _legionId); _unstakeTreasures(_legionId, _usingOldSchema); emit AdvancedQuestEnded(msg.sender, _legionId, _earnedRewards); } function _unstakeTreasures( uint256 _legionId, bool _usingOldSchema) private { 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(_treasureIds.length > 0) { treasure.safeBatchTransferFrom( address(this), msg.sender, _treasureIds, _treasureAmounts, ""); } } function _distributeRewards( uint256 _legionId, bool _usingOldSchema, LegionMetadata memory _legionMetadata, ZoneInfo storage _zoneInfo, uint256 _randomNumber) private returns(AdvancedQuestReward[] memory) { // Gain Rewards! ZonePart storage _endingPart = _zoneInfo.parts[_advanceToPartForLegion(_usingOldSchema, _legionId) - 1]; // 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); AdvancedQuestReward[] memory _earnedRewards = new AdvancedQuestReward[](_endingPart.rewards.length); uint8 _cardsFlipped = _cardsFlippedForLegion(_usingOldSchema, _legionId); for(uint256 i = 0; i < _endingPart.rewards.length; i++) { ZoneReward storage _reward = _endingPart.rewards[i]; uint256 _odds = _reward.baseRateRewardOdds + _reward.generationToRarityToBoost[_legionGeneration][_legionRarity] + (_reward.boostPerFlippedCard * _cardsFlipped); 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); _randomNumber >>= 8; } } return _earnedRewards; } function _mintHitReward( ZoneRewardOption storage _zoneRewardOption, uint256 _randomNumber) private returns(AdvancedQuestReward memory _earnedReward) { if(_zoneRewardOption.consumableId > 0 && _zoneRewardOption.consumableAmount > 0) { _earnedReward.consumableId = _zoneRewardOption.consumableId; _earnedReward.consumableAmount = _zoneRewardOption.consumableAmount; consumable.mint( msg.sender, _zoneRewardOption.consumableId, _zoneRewardOption.consumableAmount); } if(_zoneRewardOption.treasureFragmentId > 0) { _earnedReward.treasureFragmentId = _zoneRewardOption.treasureFragmentId; treasureFragment.mint( msg.sender, _zoneRewardOption.treasureFragmentId, 1); } if(_zoneRewardOption.treasureTier > 0) { uint256 _treasureId = treasureMetadataStore.getRandomTreasureForTierAndCategory( _zoneRewardOption.treasureTier, _zoneRewardOption.treasureCategory, _randomNumber); _earnedReward.treasureId = _treasureId; treasure.mint( msg.sender, _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( uint256[] calldata _legionIds, UserMove[][] calldata _playerMoves, bool[] calldata _endQuestingAfterPlayingIfPossible) external whenNotPaused contractsAreSet onlyEOA nonZeroLength(_legionIds) { require(_legionIds.length == _playerMoves.length && _legionIds.length == _endQuestingAfterPlayingIfPossible.length, "Bad array lengths for play"); for(uint256 i = 0; i < _legionIds.length; i++) { _playTreasureTriad(_legionIds[i], _playerMoves[i], _endQuestingAfterPlayingIfPossible[i]); } } function _playTreasureTriad(uint256 _legionId, UserMove[] calldata _playerMoves, bool _endQuestingIfPossible) 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(_endQuestingIfPossible && _outcome.numberOfCorruptedCardsLeft == 0) { _endQuestingPostValidation(_legionId, _usingOldSchema, _legionMetadata, _zoneInfo, _randomNumber); } } 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) { 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; }
//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 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 setStasisLengthForCorruptedCard(uint256 _stasisLengthForCorruptedCard) external onlyAdminOrOwner { stasisLengthForCorruptedCard = _stasisLengthForCorruptedCard; } function isValidZone(string calldata _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; } }
//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); // 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; 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; } } 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 { }
// 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) 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":"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":"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":[{"internalType":"uint256[]","name":"_legionIds","type":"uint256[]"}],"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":[],"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":[{"internalType":"uint256[]","name":"_legionIds","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":"_endQuestingAfterPlayingIfPossible","type":"bool[]"}],"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":"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":[{"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":"","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"}]
Contract Creation Code
608060405234801561001057600080fd5b50616f0680620000216000396000f3fe608060405234801561001057600080fd5b506004361061023d5760003560e01c8063821cab0b1161013b578063c43c074c116100b8578063d7dfe4dd1161007c578063d7dfe4dd14610587578063e520fc7e1461059b578063f10fb584146105af578063f23a6e61146105c3578063f2fde38b146105e257600080fd5b8063c43c074c1461050f578063c87d4e0714610539578063cedec2ff1461054c578063cfe519031461055f578063d3f676091461057357600080fd5b8063a0122ec6116100ff578063a0122ec6146104a3578063a8883060146104b7578063abfe37b9146104ca578063bc197c81146104dd578063bedb86fb146104fc57600080fd5b8063821cab0b146104505780638a7bf804146104635780638cdcc4b4146104775780638da5cb5b1461047f5780639c54df641461049057600080fd5b80633c06ef4e116101c9578063704802751161018d578063704802751461040757806370e419451461041a578063715018a61461042d5780637d7aa1bc146104355780638129fc1c1461044857600080fd5b80633c06ef4e1461035a5780633ea86bfe1461036d5780634bec7954146103855780635c975abb146103e8578063675857eb146103f357600080fd5b80631785f53c116102105780631785f53c146102e25780631b2378c5146102f557806324d7806c146103085780632847a62d14610334578063377e11e01461034757600080fd5b806301ffc9a7146102425780630a0e28d41461026a57806313bc0b8d1461027f578063150b7a02146102ab575b600080fd5b61025561025036600461546e565b6105f5565b60405190151581526020015b60405180910390f35b61027d6102783660046154e3565b61062c565b005b61019354610293906001600160a01b031681565b6040516001600160a01b039091168152602001610261565b6102c96102b9366004615625565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610261565b61027d6102f036600461568c565b610734565b6102556103033660046156e8565b61077f565b61025561031636600461568c565b6001600160a01b031660009081526097602052604090205460ff1690565b61025561034236600461571d565b6107ae565b61027d6103553660046154e3565b6107e5565b61027d61036836600461571d565b610886565b61037761019b5481565b604051908152602001610261565b6103d7610393366004615736565b805160208183018101805161019c825292820191909301209152805460019091015460ff808216916101008104821691620100008204811691630100000090041685565b6040516102619594939291906157ac565b60655460ff16610255565b61019454610293906001600160a01b031681565b61027d61041536600461568c565b6108c9565b61027d6104283660046154e3565b610917565b61027d610a10565b61027d6104433660046157f9565b610a46565b61027d610bec565b61027d61045e3660046154e3565b610c66565b61019554610293906001600160a01b031681565b610255610d62565b6033546001600160a01b0316610293565b61027d61049e3660046154e3565b610e31565b61019854610293906001600160a01b031681565b61027d6104c5366004615892565b610ecd565b61027d6104d836600461593a565b610fb0565b6102c96104eb366004615a28565b63bc197c8160e01b95945050505050565b61027d61050a366004615adf565b611156565b61052261051d36600461571d565b6111a9565b6040805192835260ff909116602083015201610261565b610377610547366004615b16565b61141e565b61027d61055a366004615b61565b611474565b61019a54610293906001600160a01b031681565b61019954610293906001600160a01b031681565b61019754610293906001600160a01b031681565b61019654610293906001600160a01b031681565b61019254610293906001600160a01b031681565b6102c96105d1366004615b9d565b63f23a6e6160e01b95945050505050565b61027d6105f036600461568c565b611612565b60006001600160e01b03198216630271189760e51b148061062657506301ffc9a760e01b6001600160e01b03198316145b92915050565b60655460ff16156106585760405162461bcd60e51b815260040161064f90615c01565b60405180910390fd5b610660610d62565b61067c5760405162461bcd60e51b815260040161064f90615c2b565b33321461069b5760405162461bcd60e51b815260040161064f90615c59565b818180806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508251151591506106f090505760405162461bcd60e51b815260040161064f90615c7f565b60005b8281101561072e5761071c84848381811061071057610710615ca4565b905060200201356116aa565b8061072681615cd0565b9150506106f3565b50505050565b6033546001600160a01b0316331461075e5760405162461bcd60e51b815260040161064f90615ceb565b6001600160a01b03166000908152609760205260409020805460ff19169055565b60008061019c8484604051610795929190615d20565b9081526040519081900360200190205411905092915050565b600081815261019f602052604081205415158061062657505060009081526101a060205260409020546001600160781b0316151590565b6033546001600160a01b0316331461080f5760405162461bcd60e51b815260040161064f90615ceb565b60005b818110156108815760006097600085858581811061083257610832615ca4565b9050602002016020810190610847919061568c565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790558061087981615cd0565b915050610812565b505050565b3360009081526097602052604090205460ff16806108a757506108a7611cb8565b6108c35760405162461bcd60e51b815260040161064f90615d30565b61019b55565b6033546001600160a01b031633146108f35760405162461bcd60e51b815260040161064f90615ceb565b6001600160a01b03166000908152609760205260409020805460ff19166001179055565b60655460ff161561093a5760405162461bcd60e51b815260040161064f90615c01565b610942610d62565b61095e5760405162461bcd60e51b815260040161064f90615c2b565b33321461097d5760405162461bcd60e51b815260040161064f90615c59565b818180806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508251151591506109d290505760405162461bcd60e51b815260040161064f90615c7f565b60005b8281101561072e576109fe8484838181106109f2576109f2615ca4565b90506020020135611cdc565b80610a0881615cd0565b9150506109d5565b6033546001600160a01b03163314610a3a5760405162461bcd60e51b815260040161064f90615ceb565b610a446000611f12565b565b3360009081526097602052604090205460ff1680610a675750610a67611cb8565b610a835760405162461bcd60e51b815260040161064f90615d30565b610a8d868661077f565b610acb5760405162461bcd60e51b815260206004820152600f60248201526e169bdb99481a5cc81a5b9d985b1a59608a1b604482015260640161064f565b600061019c8787604051610ae0929190615d20565b908152604051908190036020019020600281015490915084148015610b0457508382145b610b445760405162461bcd60e51b8152602060048201526011602482015270426164206172726179206c656e6774687360781b604482015260640161064f565b60005b84811015610be257858582818110610b6157610b61615ca4565b90506020020135826002018281548110610b7d57610b7d615ca4565b6000918252602090912060049091020155838382818110610ba057610ba0615ca4565b90506020020135826002018281548110610bbc57610bbc615ca4565b600091825260209091206001600490920201015580610bda81615cd0565b915050610b47565b5050505050505050565b600054610100900460ff16610c075760005460ff1615610c0b565b303b155b610c275760405162461bcd60e51b815260040161064f90615d5c565b600054610100900460ff16158015610c49576000805461ffff19166101011790555b610c51611f64565b8015610c63576000805461ff00191690555b50565b60655460ff1615610c895760405162461bcd60e51b815260040161064f90615c01565b610c91610d62565b610cad5760405162461bcd60e51b815260040161064f90615c2b565b333214610ccc5760405162461bcd60e51b815260040161064f90615c59565b80610d195760405162461bcd60e51b815260206004820152601b60248201527f4e6f20737461727420717565737420706172616d7320676976656e0000000000604482015260640161064f565b60005b8181101561088157610d50838383818110610d3957610d39615ca4565b9050602002810190610d4b9190615daa565b611fc9565b80610d5a81615cd0565b915050610d1c565b610192546000906001600160a01b031615801590610d8b5750610193546001600160a01b031615155b8015610da25750610194546001600160a01b031615155b8015610db95750610195546001600160a01b031615155b8015610dd05750610196546001600160a01b031615155b8015610de75750610197546001600160a01b031615155b8015610dfe5750610198546001600160a01b031615155b8015610e155750610199546001600160a01b031615155b8015610e2c575061019a546001600160a01b031615155b905090565b6033546001600160a01b03163314610e5b5760405162461bcd60e51b815260040161064f90615ceb565b60005b8181101561088157600160976000858585818110610e7e57610e7e615ca4565b9050602002016020810190610e93919061568c565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905580610ec581615cd0565b915050610e5e565b3360009081526097602052604090205460ff1680610eee5750610eee611cb8565b610f0a5760405162461bcd60e51b815260040161064f90615d30565b61019280546001600160a01b03199081166001600160a01b039b8c161790915561019380548216998b169990991790985561019480548916978a16979097179096556101958054881695891695909517909455610196805487169388169390931790925561019780548616918716919091179055610198805485169186169190911790556101998054841691851691909117905561019a80549092169216919091179055565b3360009081526097602052604090205460ff1680610fd15750610fd1611cb8565b610fed5760405162461bcd60e51b815260040161064f90615d30565b61103a83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506040805160208101909152908152925061291b915050565b156110875760405162461bcd60e51b815260206004820152601960248201527f5a6f6e65206e616d652063616e6e6f7420626520626c616e6b00000000000000604482015260640161064f565b611091838361077f565b156110d45760405162461bcd60e51b81526020600482015260136024820152725a6f6e6520616c72656164792065786973747360681b604482015260640161064f565b80356111225760405162461bcd60e51b815260206004820152601b60248201527f5a6f6e65206d757374206861766520612073746172742074696d650000000000604482015260640161064f565b8061019c8484604051611136929190615d20565b90815260405190819003602001902061114f828261649d565b5050505050565b3360009081526097602052604090205460ff16806111775750611177611cb8565b6111935760405162461bcd60e51b815260040161064f90615d30565b80156111a157610c63612974565b610c636129e9565b610195546040516378afdef960e11b815260048101839052600091829182916001600160a01b03169063f15fbdf2906024016101806040518083038186803b1580156111f457600080fd5b505afa158015611208573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122c91906166e1565b600085815261019f6020526040812054919250901515906112df6112508388612a63565b805461125b90616776565b80601f016020809104026020016040519081016040528092919081815260200182805461128790616776565b80156112d45780601f106112a9576101008083540402835291602001916112d4565b820191906000526020600020905b8154815290600101906020018083116112b757829003601f168201915b505050505084612a99565b610192549091506000906001600160a01b0316634ad30a75611301858a612b74565b6040518263ffffffff1660e01b815260040161131f91815260200190565b60206040518083038186803b15801561133757600080fd5b505afa15801561134b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136f91906167b1565b90506114118784611380868b612a63565b805461138b90616776565b80601f01602080910402602001604051908101604052809291908181526020018280546113b790616776565b80156114045780601f106113d957610100808354040283529160200191611404565b820191906000526020600020905b8154815290600101906020018083116113e757829003601f168201915b5050505050878686612bbf565b9550955050505050915091565b600061019c8484604051611433929190615d20565b90815260200160405180910390206002018260ff168154811061145857611458615ca4565b90600052602060002090600402016000015490505b9392505050565b60655460ff16156114975760405162461bcd60e51b815260040161064f90615c01565b61149f610d62565b6114bb5760405162461bcd60e51b815260040161064f90615c2b565b3332146114da5760405162461bcd60e51b815260040161064f90615c59565b8585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505082511515915061152f90505760405162461bcd60e51b815260040161064f90615c7f565b858414801561153d57508582145b6115895760405162461bcd60e51b815260206004820152601a60248201527f426164206172726179206c656e6774687320666f7220706c6179000000000000604482015260640161064f565b60005b86811015610be2576116008888838181106115a9576115a9615ca4565b905060200201358787848181106115c2576115c2615ca4565b90506020028101906115d491906167ca565b8787868181106115e6576115e6615ca4565b90506020020160208101906115fb9190615adf565b612d4b565b8061160a81615cd0565b91505061158c565b6033546001600160a01b0316331461163c5760405162461bcd60e51b815260040161064f90615ceb565b6001600160a01b0381166116a15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161064f565b610c6381611f12565b600081815261019f60205260408120541515906116c78284612a63565b80546116d290616776565b80601f01602080910402602001604051908101604052809291908181526020018280546116fe90616776565b801561174b5780601f106117205761010080835404028352916020019161174b565b820191906000526020600020905b81548152906001019060200180831161172e57829003601f168201915b5050610195546040516378afdef960e11b8152600481018990529495506000946001600160a01b03909116935063f15fbdf2925060240190506101806040518083038186803b15801561179d57600080fd5b505afa1580156117b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d591906166e1565b9050600061019c836040516117ea9190616812565b908152604051908190036020019020905033611806858761314e565b6001600160a01b03161461182c5760405162461bcd60e51b815260040161064f9061684d565b610192546000906001600160a01b0316634ad30a7561184b8789612b74565b6040518263ffffffff1660e01b815260040161186991815260200190565b60206040518083038186803b15801561188157600080fd5b505afa158015611895573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b991906167b1565b90506118cb8685878686866001613198565b60006118d786886132fa565b60028401549091506118ea82600161687a565b60ff1611156119325760405162461bcd60e51b8152602060048201526014602482015273105b1c9958591e48185d081b185cdd081c185c9d60621b604482015260640161064f565b826002018160ff168154811061194a5761194a615ca4565b6000918252602090912060026004909202010154606085015160ff61010090920482169116101561198d5760405162461bcd60e51b815260040161064f9061689f565b826002018160ff16815481106119a5576119a5615ca4565b906000526020600020906004020160020160039054906101000a900460ff1615806119d557506119d58688613346565b611a215760405162461bcd60e51b815260206004820152601d60248201527f4e6f207472656173757265207374616b656420666f72206c6567696f6e000000604482015260640161064f565b610192546040805163433c53d960e11b815290516000926001600160a01b031691638678a7b291600480830192602092919082900301818787803b158015611a6857600080fd5b505af1158015611a7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa091906167b1565b90508615611b8957600088815261019f60205260409020428155600801805460ff808516600160a81b0260ff60a81b1990921691909117808355600160a01b900416906014611aee836168e4565b825460ff9182166101009390930a928302919092021990911617905550600088815261019f60205260408120818155600181018290556002810182905560038101805461ffff191690559060048201818181611b4a828261537d565b50611b5d9250505060078301600061539b565b5060080180546001600160b01b0319169055600088815261019f60205260409020600101819055611c4e565b60008881526101a06020526040902080546001600160781b031916426001600160781b031617815560010180546001600160f81b0316600160f81b60ff8581169190910291909117808355600160f01b90041690601e611be8836168e4565b82546101009290920a60ff8181021990931691909216919091021790555060008881526101a06020526040902080546001600160781b03168155600101805469ffffffffffffffffffff60a01b1916600160a01b69ffffffffffffffffffff8416021790555b7f6637022d9de6a2060f00e17833969643de3940f9fc4ea37f4e755ae5121b13c3338983611c7d86600161687a565b604080516001600160a01b03909516855260208501939093529183015260ff1660608201526080015b60405180910390a15050505050505050565b600033611ccd6033546001600160a01b031690565b6001600160a01b031614905090565b600081815261019f6020526040812054151590611cf98284612a63565b8054611d0490616776565b80601f0160208091040260200160405190810160405280929190818152602001828054611d3090616776565b8015611d7d5780601f10611d5257610100808354040283529160200191611d7d565b820191906000526020600020905b815481529060010190602001808311611d6057829003601f168201915b5050610195546040516378afdef960e11b8152600481018990529495506000946001600160a01b03909116935063f15fbdf2925060240190506101806040518083038186803b158015611dcf57600080fd5b505afa158015611de3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e0791906166e1565b9050600061019c83604051611e1c9190616812565b908152604051908190036020019020905033611e38858761314e565b6001600160a01b031614611e5e5760405162461bcd60e51b815260040161064f9061684d565b610192546000906001600160a01b0316634ad30a75611e7d8789612b74565b6040518263ffffffff1660e01b8152600401611e9b91815260200190565b60206040518083038186803b158015611eb357600080fd5b505afa158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb91906167b1565b9050611efd8685878686866001613198565b611f0a8686858585613393565b505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611f7f5760005460ff1615611f83565b303b155b611f9f5760405162461bcd60e51b815260040161064f90615d5c565b600054610100900460ff16158015611fc1576000805461ffff19166101011790555b610c51613503565b8035611fd4816107ae565b156120215760405162461bcd60e51b815260206004820152601a60248201527f4c6567696f6e20697320616c7265616479207175657374696e67000000000000604482015260640161064f565b6120316103036020840184616904565b61206c5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964207a6f6e6560a01b604482015260640161064f565b600061019c61207e6020850185616904565b60405161208c929190615d20565b90815260408051918290036020019091206002015491506000906120b6906060860190860161694a565b60ff161180156120d85750806120d2606085016040860161694a565b60ff1611155b6121245760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420616476616e636520746f2070617274000000000000000000604482015260640161064f565b610195546040516378afdef960e11b8152600481018490526000916001600160a01b03169063f15fbdf2906024016101806040518083038186803b15801561216b57600080fd5b505afa15801561217f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a391906166e1565b90506002815160028111156121ba576121ba615786565b14156122085760405162461bcd60e51b815260206004820152601d60248201527f526563727569742063616e6e6f7420616476616e636564207175657374000000604482015260640161064f565b6000805b61221c606087016040880161694a565b60ff168110156123cd57600061019c6122386020890189616904565b604051612246929190615d20565b9081526020016040518091039020600201828154811061226857612268615ca4565b6000918252602090912060026004909202010154606085015160ff61010090920482169250168111156122ad5760405162461bcd60e51b815260040161064f9061689f565b600061019c6122bf60208a018a616904565b6040516122cd929190615d20565b908152602001604051809103902060020183815481106122ef576122ef615ca4565b906000526020600020906004020160020160039054906101000a900460ff16905083806123195750805b9350600161232d60608a0160408b0161694a565b6123379190616967565b60ff16831080156123455750805b156123b85760405162461bcd60e51b815260206004820152603860248201527f43616e6e6f7420616476616e636564207061737420612070617274207468617460448201527f2072657175697265732074726561737572652074726961640000000000000000606482015260840161064f565b505080806123c590615cd0565b91505061220c565b506123db6080860186615dd7565b90506123ea6060870187615dd7565b9050146124305760405162461bcd60e51b8152602060048201526014602482015273426164207472656173757265206c656e6774687360601b604482015260640161064f565b80158061244b575060006124476060870187615dd7565b9050115b6124a35760405162461bcd60e51b8152602060048201526024808201527f4e65656420747265617375726520746f20706c617920747265617375726520746044820152631c9a585960e21b606482015260840161064f565b6000806124f26124b66020890189616904565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250612a99915050565b905060005b6125046060890189615dd7565b905081101561265757600061251c60608a018a615dd7565b8381811061252c5761252c615ca4565b905060200201351180156125635750600061254a60808a018a615dd7565b8381811061255a5761255a615ca4565b90506020020135115b6125af5760405162461bcd60e51b815260206004820152601960248201527f426164207472656173757265206964206f7220616d6f756e7400000000000000604482015260640161064f565b6125bc6080890189615dd7565b828181106125cc576125cc615ca4565b90506020020135836125de919061698a565b92508160ff168311156126455760405162461bcd60e51b815260206004820152602960248201527f546f6f206d616e792074726561737572657320666f7220636f6e7374656c6c6160448201526874696f6e2072616e6b60b81b606482015260840161064f565b8061264f81615cd0565b9150506124f7565b50610192546040805163433c53d960e11b815290516000926001600160a01b031691638678a7b291600480830192602092919082900301818787803b15801561269f57600080fd5b505af11580156126b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d791906167b1565b60008881526101a06020908152604090912080546001600160781b031916426001600160781b0316178155600101805469ffffffffffffffffffff60a01b1916600160a01b69ffffffffffffffffffff85160217905590915061273c90890189616904565b60008981526101a06020526040902061275a926002909101916153d5565b5060008781526101a060205260409081902060010180546001600160a01b0319163317905561278f9060608a01908a0161694a565b60008881526101a0602052604090206001810180546001600160f01b0316600160f01b60ff94909416939093026001600160f81b03169290921790915580546001600160781b031690556127e288613568565b610194546040516383291f8760e01b8152336004820152306024820152604481018990526001600160a01b03909116906383291f8790606401600060405180830381600087803b15801561283557600080fd5b505af1158015612849573d6000803e3d6000fd5b506000925061285e91505060608a018a615dd7565b905011156128e857610196546001600160a01b0316632eb2c2d6333061288760608d018d615dd7565b61289460808f018f615dd7565b6040518763ffffffff1660e01b81526004016128b5969594939291906169d8565b600060405180830381600087803b1580156128cf57600080fd5b505af11580156128e3573d6000803e3d6000fd5b505050505b7f6c0d8f3939be2a5b9dcf5ce392c338774f1e1fce2cfa6a61a9ad81ad1dd3dd1933828a604051611ca693929190616aa8565b60008160405160200161292e9190616812565b60405160208183030381529060405280519060200120836040516020016129559190616812565b6040516020818303038152906040528051906020012014905092915050565b60655460ff16156129975760405162461bcd60e51b815260040161064f90615c01565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586129cc3390565b6040516001600160a01b03909116815260200160405180910390a1565b60655460ff16612a325760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161064f565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336129cc565b600082612a815760008281526101a06020526040902060020161146d565b50600090815261019f60205260409020600701919050565b6000808260a0015161019c85604051612ab29190616812565b9081526040519081900360200190206001015460ff62010000909104166005811115612ae057612ae0615786565b60068110612af057612af0615ca4565b6020020151905060008360a0015161019c86604051612b0f9190616812565b9081526040519081900360200190206001015460ff6301000000909104166005811115612b3e57612b3e615786565b60068110612b4e57612b4e615ca4565b602002015190508060ff168260ff161115612b6b57509050610626565b91506106269050565b600082612ba65760008281526101a06020526040902060010154600160a01b900469ffffffffffffffffffff1661146d565b50600090815261019f6020526040902060010154919050565b600080612bcb886107ae565b612c105760405162461bcd60e51b81526020600482015260166024820152754c6567696f6e206973206e6f74207175657374696e6760501b604482015260640161064f565b6000612c1c888a613bea565b90506000612c2a898b613c2f565b90506000612c388a8c6132fa565b90506000612c468b8d613c71565b905061019c8a604051612c599190616812565b908152604051908190036020019020600201612c76600184616967565b60ff1681548110612c8957612c89615ca4565b906000526020600020906004020160020160039054906101000a900460ff168015612cb45750600084115b8015612cc3575060008360ff16115b15612cf15761019b54612cd99060ff8516615e36565b612ce3908561698a565b839550955050505050612d40565b6000612d1f61019c8c604051612d079190616812565b90815260200160405180910390208b8a8c8688613cbd565b9650905080612d2e8d8f613e25565b612d38919061698a565b965050505050505b965096945050505050565b600084815261019f6020526040812054151590612d688287612a63565b8054612d7390616776565b80601f0160208091040260200160405190810160405280929190818152602001828054612d9f90616776565b8015612dec5780601f10612dc157610100808354040283529160200191612dec565b820191906000526020600020905b815481529060010190602001808311612dcf57829003601f168201915b5050610195546040516378afdef960e11b8152600481018c90529495506000946001600160a01b03909116935063f15fbdf2925060240190506101806040518083038186803b158015612e3e57600080fd5b505afa158015612e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e7691906166e1565b9050600061019c83604051612e8b9190616812565b908152604051908190036020019020905033612ea7858a61314e565b6001600160a01b031614612ecd5760405162461bcd60e51b815260040161064f9061684d565b610192546000906001600160a01b0316634ad30a75612eec878c612b74565b6040518263ffffffff1660e01b8152600401612f0a91815260200190565b60206040518083038186803b158015612f2257600080fd5b505afa158015612f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5a91906167b1565b9050612f6c8985878686866000613198565b612f788888878c613e60565b6101995460208401516040516330019d4b60e01b81526000926001600160a01b0316916330019d4b91612fb39186918e908e90600401616b91565b60606040518083038186803b158015612fcb57600080fd5b505afa158015612fdf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130039190616c1c565b905085156130515760008a815261019f602090815260409091204260028201559082015160039091018054835160ff9081166101000261ffff199092169316929092179190911790556130c1565b60008a81526101a06020908152604090912080549183015183516fffffffffffffffffffffffffffffffff60781b19909316600160781b426001600160781b03160260ff60f01b191617600160f01b60ff92831602176001600160f81b0316600160f81b91909316029190911790555b604081810151825160208085015184513381529182018f90529215158185015260ff91821660608201529116608082015290517f9cc74f6243b89778b7e86d5b933c4146bd93203932a12bfe7ad7625d433e67ae9181900360a00190a18680156131305750602081015160ff16155b15613142576131428a87868686613393565b50505050505050505050565b6000826131765760008281526101a060205260409020600101546001600160a01b031661146d565b50600090815261019f60205260409020600801546001600160a01b0316919050565b60006131a48786612a99565b905060006131b689888a898689612bbf565b509050804210156132235760405162461bcd60e51b815260206004820152603160248201527f4c6567696f6e20686173206e6f742066696e69736865642074686973207061726044820152701d081bd9881d1a19481e9bdb99481e595d607a1b606482015260840161064f565b828015613278575084600201600161323b898c6132fa565b6132459190616967565b60ff168154811061325857613258615ca4565b906000526020600020906004020160020160039054906101000a900460ff165b801561328b5750613289878a613bea565b155b156132ef5760405162461bcd60e51b815260206004820152602e60248201527f486173206e6f7420706c6179656420747265617375726520747269616420666f60448201526d1c8818dd5c9c995b9d081c185c9d60921b606482015260840161064f565b505050505050505050565b6000826133235760008281526101a06020526040902060010154600160f01b900460ff1661146d565b50600090815261019f6020526040902060080154600160a01b900460ff16919050565b6000826133705760008281526101a06020526040902060030154610100900461ffff16151561146d565b600082815261019f6020526040812061338b906004016140ce565b119392505050565b610193546060840151604051632fb44d2760e11b81526004810188905260ff90911660248201526001600160a01b0390911690635f689a4e90604401600060405180830381600087803b1580156133e957600080fd5b505af11580156133fd573d6000803e3d6000fd5b50505050600061341086868686866140d8565b9050841561342d57600086815261019f602052604081205561344b565b60008681526101a06020526040902080546001600160781b03191690555b610194546040516383291f8760e01b8152306004820152336024820152604481018890526001600160a01b03909116906383291f8790606401600060405180830381600087803b15801561349e57600080fd5b505af11580156134b2573d6000803e3d6000fd5b505050506134c0868661438b565b7f9949f99e59b9a76e12491767b7369cea6085b2e0f953d867d6a20484c12b105c3387836040516134f393929190616c8d565b60405180910390a1505050505050565b600054610100900460ff1661351e5760005460ff1615613522565b303b155b61353e5760405162461bcd60e51b815260040161064f90615d5c565b600054610100900460ff16158015613560576000805461ffff19166101011790555b610c516148ff565b604080516101e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081019190915260006135f06060840184615dd7565b60ff8116845291505080156136635761360c6060840184615dd7565b600081811061361d5761361d615ca4565b6020908102929092013561ffff1691840191909152506136406080840184615dd7565b600081811061365157613651615ca4565b602002919091013560ff166040840152505b60018111156136cc576136796060840184615dd7565b600181811061368a5761368a615ca4565b602002919091013561ffff166060840152506136a96080840184615dd7565b60018181106136ba576136ba615ca4565b602002919091013560ff166080840152505b6002811115613735576136e26060840184615dd7565b60028181106136f3576136f3615ca4565b602002919091013561ffff1660a0840152506137126080840184615dd7565b600281811061372357613723615ca4565b602002919091013560ff1660c0840152505b600381111561379f5761374b6060840184615dd7565b600381811061375c5761375c615ca4565b602002919091013561ffff1660e08401525061377b6080840184615dd7565b600381811061378c5761378c615ca4565b602002919091013560ff16610100840152505b600481111561380a576137b56060840184615dd7565b60048181106137c6576137c6615ca4565b602002919091013561ffff16610120840152506137e66080840184615dd7565b60048181106137f7576137f7615ca4565b602002919091013560ff16610140840152505b6005811115613875576138206060840184615dd7565b600581811061383157613831615ca4565b602002919091013561ffff16610160840152506138516080840184615dd7565b600581811061386257613862615ca4565b602002919091013560ff16610180840152505b60068111156138e05761388b6060840184615dd7565b600681811061389c5761389c615ca4565b602002919091013561ffff166101a0840152506138bc6080840184615dd7565b60068181106138cd576138cd615ca4565b602002919091013560ff166101c0840152505b60005b818110156139c15760006138f882600161698a565b90505b828110156139ae576139106060860186615dd7565b8281811061392057613920615ca4565b905060200201358580606001906139379190615dd7565b8481811061394757613947615ca4565b90506020020135141561399c5760405162461bcd60e51b815260206004820152601e60248201527f4475706c696361746520747265617375726520696420696e2061727261790000604482015260640161064f565b806139a681615cd0565b9150506138fb565b50806139b981615cd0565b9150506138e3565b50816101a060008560000135815260200190815260200160002060030160008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548160ff021916908360ff16021790555060608201518160000160046101000a81548161ffff021916908361ffff16021790555060808201518160000160066101000a81548160ff021916908360ff16021790555060a08201518160000160076101000a81548161ffff021916908361ffff16021790555060c08201518160000160096101000a81548160ff021916908360ff16021790555060e082015181600001600a6101000a81548161ffff021916908361ffff16021790555061010082015181600001600c6101000a81548160ff021916908360ff16021790555061012082015181600001600d6101000a81548161ffff021916908361ffff16021790555061014082015181600001600f6101000a81548160ff021916908360ff1602179055506101608201518160000160106101000a81548161ffff021916908361ffff1602179055506101808201518160000160126101000a81548160ff021916908360ff1602179055506101a08201518160000160136101000a81548161ffff021916908361ffff1602179055506101c08201518160000160156101000a81548160ff021916908360ff160217905550905050505050565b600082613c165760008281526101a06020526040902054600160781b90046001600160781b031661146d565b50600090815261019f6020526040902060020154919050565b600082613c555760008281526101a06020526040902054600160f01b900460ff1661146d565b50600090815261019f602052604090206003015460ff16919050565b600082613c9a5760008281526101a06020526040902060010154600160f81b900460ff1661146d565b50600090815261019f6020526040902060080154600160a81b900460ff16919050565b60ff808416600090815261019e60205260408120549091829181169085165b8460ff16811015613e1857896002018181548110613cfc57613cfc615ca4565b90600052602060002090600402016000015484613d19919061698a565b935061019d60008a600001516002811115613d3657613d36615786565b6002811115613d4757613d47615786565b815260208101919091526040016000205460ff1615613e065760008a6002018281548110613d7757613d77615ca4565b600091825260209091206002600490920201015460ff90811691508316811115613e0457613da58382616967565b60ff16613db46101008b616d0a565b1015613dfc5783613dc4816168e4565b9450508a6002018281548110613ddc57613ddc615ca4565b90600052602060002090600402016001015485613df9919061698a565b94505b600889901c98505b505b80613e1081615cd0565b915050613cdc565b5050965096945050505050565b600082613e4a5760008281526101a060205260409020546001600160781b031661146d565b50600090815261019f6020526040902054919050565b8215801590613e6f5750600483105b613ec65760405162461bcd60e51b815260206004820152602260248201527f426164206e756d626572206f66207472656173757265207472696164206d6f76604482015261657360f01b606482015260840161064f565b6000836001600160401b03811115613ee057613ee0615540565b604051908082528060200260200182016040528015613f2557816020015b6040805180820190915260008082526020820152815260200190600190039081613efe5790505b5090506000805b858110156140c5576000878783818110613f4857613f48615ca4565b9050606002016040013590506000613f61828888614b1a565b90506000805b865181101561405c5783878281518110613f8357613f83615ca4565b602002602001015160000151141561404a5760019150868181518110613fab57613fab615ca4565b602002602001015160200151600014156140175760405162461bcd60e51b815260206004820152602760248201527f55736564206d6f7265207472656173757265207468616e207768617420776173604482015266081cdd185ad95960ca1b606482015260840161064f565b86818151811061402957614029615ca4565b6020026020010151602001805180919061404290616d2c565b90525061405c565b8061405481615cd0565b915050613f67565b50806140af5760405180604001604052808481526020016001846140809190616d43565b81525086868151811061409557614095615ca4565b602002602001018190525084806140ab90615cd0565b9550505b50505080806140bd90615cd0565b915050613f2c565b50505050505050565b6000610626825490565b606060008360020160016140ec888a6132fa565b6140f69190616967565b60ff168154811061410957614109615ca4565b90600052602060002090600402019050827f270403fba6eda13e1a219e01f1fb9cac4267cb529255cf0cb111921f93124218604051602001614155929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c925060008560000151600281111561418857614188615786565b90506000866040015160058111156141a2576141a2615786565b60038401549091506000906001600160401b038111156141c4576141c4615540565b60405190808252806020026020018201604052801561422057816020015b61420d6040518060800160405280600081526020016000815260200160008152602001600081525090565b8152602001906001900390816141e25790505b509050600061422f8a8c614d7c565b905060005b600386015481101561437b57600086600301828154811061425757614257615ca4565b60009182526020822060026004909202019081015490925061427d90859060ff16616d5a565b82600101888154811061429257614292615ca4565b9060005260206000200187815481106142ad576142ad615ca4565b60009182526020918290209181049091015484546142db92601f166101000a90910460ff908116911661687a565b6142e5919061687a565b60ff169050600060ff82106142fc57506001614321565b8115614321578161430f6101008d616d0a565b1015614319575060015b60088b901c9a505b80156143655760006143338c85614dc3565b905061433f818d614ed9565b87868151811061435157614351615ca4565b602002602001018190525060088c901c9b50505b505050808061437390615cd0565b915050614234565b50909a9950505050505050505050565b606080821561447957600084815261019f602052604090206143af9060040161513a565b915081516001600160401b038111156143ca576143ca615540565b6040519080825280602002602001820160405280156143f3578160200160208202803683370190505b50905060005b82518110156144735761019f6000868152602001908152602001600020600601600084838151811061442d5761442d615ca4565b602002602001015181526020019081526020016000205482828151811061445657614456615ca4565b60209081029190910101528061446b81615cd0565b9150506143f9565b50614893565b60008481526101a0602081815260409283902083516101e08101855260039091015460ff80821680845261010080840461ffff90811696860196909652630100000084048316978501979097526401000000008304851660608501526601000000000000830482166080850152600160381b8304851660a0850152600160481b8304821660c0850152600160501b8304851660e0850152600160601b8304821696840196909652600160681b82048416610120840152600160781b82048116610140840152600160801b82048416610160840152600160901b82048116610180840152600160981b820490931693820193909352600160a81b909204166101c082015290806001600160401b0381111561459557614595615540565b6040519080825280602002602001820160405280156145be578160200160208202803683370190505b5093508060ff166001600160401b038111156145dc576145dc615540565b604051908082528060200260200182016040528015614605578160200160208202803683370190505b50925060ff81161561466157816020015161ffff168460008151811061462d5761462d615ca4565b602002602001018181525050816040015160ff168360008151811061465457614654615ca4565b6020026020010181815250505b60018160ff1611156146bd57816060015161ffff168460018151811061468957614689615ca4565b602002602001018181525050816080015160ff16836001815181106146b0576146b0615ca4565b6020026020010181815250505b60028160ff161115614719578160a0015161ffff16846002815181106146e5576146e5615ca4565b6020026020010181815250508160c0015160ff168360028151811061470c5761470c615ca4565b6020026020010181815250505b60038160ff161115614776578160e0015161ffff168460038151811061474157614741615ca4565b60200260200101818152505081610100015160ff168360038151811061476957614769615ca4565b6020026020010181815250505b60048160ff1611156147d45781610120015161ffff168460048151811061479f5761479f615ca4565b60200260200101818152505081610140015160ff16836004815181106147c7576147c7615ca4565b6020026020010181815250505b60058160ff1611156148325781610160015161ffff16846005815181106147fd576147fd615ca4565b60200260200101818152505081610180015160ff168360058151811061482557614825615ca4565b6020026020010181815250505b60068160ff16111561489057816101a0015161ffff168460068151811061485b5761485b615ca4565b602002602001018181525050816101c0015160ff168360068151811061488357614883615ca4565b6020026020010181815250505b50505b81511561072e5761019654604051631759616b60e11b81526001600160a01b0390911690632eb2c2d6906148d1903090339087908790600401616dbe565b600060405180830381600087803b1580156148eb57600080fd5b505af1158015610be2573d6000803e3d6000fd5b600054610100900460ff1661491a5760005460ff161561491e565b303b155b61493a5760405162461bcd60e51b815260040161064f90615d5c565b600054610100900460ff1615801561495c576000805461ffff19166101011790555b614964615147565b61496c6151ac565b6149746151ac565b6201518061019b557f13dcb3c6205eccc5df5a4a7821d488c75d9d361908855b59d022fe13c7bb4f1d805460ff199081169091557f228719b3ab53201bbb41968c40b0b5cdf287f8c98ba3ec9532f722219a6d86ff80548216600117905561019e6020527f2d695d1bdc89be0990c9b1cefd0e589f7fbb3368bfb8d91126956a95dcf1607380548216600a1790557f1482f8fde77c2e0a1223b839dd85e5e0d40575a23bb6b13896f241a0b36fe0d880548216600f1790557f819c8b3e70c1a841f15170a81b2fad3b9dd6363490e4d79d5e443edaf01bbd658054821660141790557ff166615731f9a0da5f995c890da9823aee980021e1f67a3a50824b9391ea855f8054821660171790557f5fc73781db4fef9135a7751bb16b9dc0cf5d8f49924b6290e697d3ce5362e55b8054821660261790557f0c0534c4fd269d874c4e3ccf61cdfc386596ea47184f1d857725cfeaab13fd5080548216603317905560076000527f52fc7babecae6ce4e4dc8870a20313c060d91987e43bc7d10bf81d0e02b5bebc8054604092169190911790558015610c63576000805461ff001916905550565b60008215614b7e57600082815261019f60205260409020614b3e90600401856151d3565b614b5a5760405162461bcd60e51b815260040161064f90616e19565b50600081815261019f6020908152604080832086845260060190915290205461146d565b60008281526101a0602081815260409283902083516101e08101855260039091015460ff808216835261ffff610100808404821695850195909552630100000083048216968401969096526401000000008204861660608401526601000000000000820481166080840152600160381b8204861660a0840152600160481b8204811660c0840152600160501b8204861660e0840152600160601b8204811693830193909352600160681b81048516610120830152600160781b81048316610140830152600160801b81048516610160830152600160901b81048316610180830152600160981b810490941692810192909252600160a81b9092049091166101c082015284614c8b57600080fd5b84816020015161ffff161415614ca9576040015160ff16905061146d565b84816060015161ffff161415614cc7576080015160ff16905061146d565b848160a0015161ffff161415614ce55760c0015160ff16905061146d565b848160e0015161ffff161415614d0457610100015160ff16905061146d565b8481610120015161ffff161415614d2457610140015160ff16905061146d565b8481610160015161ffff161415614d4457610180015160ff16905061146d565b84816101a0015161ffff161415614d64576101c0015160ff16905061146d565b60405162461bcd60e51b815260040161064f90616e19565b600082614da25760008281526101a06020526040902054600160f81b900460ff1661146d565b50600090815261019f6020526040902060030154610100900460ff16919050565b600381015460009060011415614dfe5781600301600081548110614de957614de9615ca4565b90600052602060002090600402019050610626565b6000614e0c61010085616d0a565b90506000600885901c945060005b6003850154811015614e90576000856003018281548110614e3d57614e3d615ca4565b600091825260209091206004909102016003810154909150614e689062010000900460ff168461698a565b925082841015614e7d57935061062692505050565b5080614e8881615cd0565b915050614e1a565b5060405162461bcd60e51b815260206004820152601860248201527f426164206f64647320666f72207a6f6e65207265776172640000000000000000604482015260640161064f565b614f046040518060800160405280600081526020016000815260200160008152602001600081525090565b825415801590614f18575060008360010154115b15614f9b57825480825260018401546020830181905261019754604051630ab714fb60e11b8152336004820152602481019390935260448301919091526001600160a01b03169063156e29f690606401600060405180830381600087803b158015614f8257600080fd5b505af1158015614f96573d6000803e3d6000fd5b505050505b60028301541561501d576002830154604082810182905261019a549051630ab714fb60e11b81523360048201526024810192909252600160448301526001600160a01b03169063156e29f690606401600060405180830381600087803b15801561500457600080fd5b505af1158015615018573d6000803e3d6000fd5b505050505b600383015460ff1615610626576101985460038401546040516302c01b2760e51b81526000926001600160a01b03169163580364e09161506f9160ff8082169261010090920416908890600401616e61565b60206040518083038186803b15801561508757600080fd5b505afa15801561509b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150bf91906167b1565b6060830181905261019654604051630ab714fb60e11b815233600482015260248101839052600160448201529192506001600160a01b03169063156e29f690606401600060405180830381600087803b15801561511b57600080fd5b505af115801561512f573d6000803e3d6000fd5b505050505092915050565b6060600061146d836151eb565b600054610100900460ff166151625760005460ff1615615166565b303b155b6151825760405162461bcd60e51b815260040161064f90615d5c565b600054610100900460ff161580156151a4576000805461ffff19166101011790555b610c51615247565b600054610100900460ff16610a445760405162461bcd60e51b815260040161064f90616e85565b6000818152600183016020526040812054151561146d565b60608160000180548060200260200160405190810160405280929190818152602001828054801561523b57602002820191906000526020600020905b815481526020019060010190808311615227575b50505050509050919050565b600054610100900460ff166152625760005460ff1615615266565b303b155b6152825760405162461bcd60e51b815260040161064f90615d5c565b600054610100900460ff161580156152a4576000805461ffff19166101011790555b6152ac6152bc565b6152b46152eb565b610c51612974565b600054610100900460ff166152e35760405162461bcd60e51b815260040161064f90616e85565b610a4461531a565b600054610100900460ff166153125760405162461bcd60e51b815260040161064f90616e85565b610a4461534a565b600054610100900460ff166153415760405162461bcd60e51b815260040161064f90616e85565b610a4433611f12565b600054610100900460ff166153715760405162461bcd60e51b815260040161064f90616e85565b6065805460ff19169055565b5080546000825590600052602060002090810190610c639190615459565b5080546153a790616776565b6000825580601f106153b7575050565b601f016020900490600052602060002090810190610c639190615459565b8280546153e190616776565b90600052602060002090601f0160209004810192826154035760008555615449565b82601f1061541c5782800160ff19823516178555615449565b82800160010185558215615449579182015b8281111561544957823582559160200191906001019061542e565b50615455929150615459565b5090565b5b80821115615455576000815560010161545a565b60006020828403121561548057600080fd5b81356001600160e01b03198116811461146d57600080fd5b60008083601f8401126154aa57600080fd5b5081356001600160401b038111156154c157600080fd5b6020830191508360208260051b85010111156154dc57600080fd5b9250929050565b600080602083850312156154f657600080fd5b82356001600160401b0381111561550c57600080fd5b61551885828601615498565b90969095509350505050565b80356001600160a01b038116811461553b57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b038111828210171561557857615578615540565b60405290565b604051601f8201601f191681016001600160401b03811182821017156155a6576155a6615540565b604052919050565b60006001600160401b038311156155c7576155c7615540565b6155da601f8401601f191660200161557e565b90508281528383830111156155ee57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261561657600080fd5b61146d838335602085016155ae565b6000806000806080858703121561563b57600080fd5b61564485615524565b935061565260208601615524565b92506040850135915060608501356001600160401b0381111561567457600080fd5b61568087828801615605565b91505092959194509250565b60006020828403121561569e57600080fd5b61146d82615524565b60008083601f8401126156b957600080fd5b5081356001600160401b038111156156d057600080fd5b6020830191508360208285010111156154dc57600080fd5b600080602083850312156156fb57600080fd5b82356001600160401b0381111561571157600080fd5b615518858286016156a7565b60006020828403121561572f57600080fd5b5035919050565b60006020828403121561574857600080fd5b81356001600160401b0381111561575e57600080fd5b8201601f8101841361576f57600080fd5b61577e848235602084016155ae565b949350505050565b634e487b7160e01b600052602160045260246000fd5b60068110610c6357610c63615786565b85815260a081016157bc8661579c565b8560208301526157cb8561579c565b8460408301526157da8461579c565b8360608301526157e98361579c565b8260808301529695505050505050565b6000806000806000806060878903121561581257600080fd5b86356001600160401b038082111561582957600080fd5b6158358a838b016156a7565b9098509650602089013591508082111561584e57600080fd5b61585a8a838b01615498565b9096509450604089013591508082111561587357600080fd5b5061588089828a01615498565b979a9699509497509295939492505050565b60008060008060008060008060006101208a8c0312156158b157600080fd5b6158ba8a615524565b98506158c860208b01615524565b97506158d660408b01615524565b96506158e460608b01615524565b95506158f260808b01615524565b945061590060a08b01615524565b935061590e60c08b01615524565b925061591c60e08b01615524565b915061592b6101008b01615524565b90509295985092959850929598565b60008060006040848603121561594f57600080fd5b83356001600160401b038082111561596657600080fd5b615972878388016156a7565b9095509350602086013591508082111561598b57600080fd5b50840160c0818703121561599e57600080fd5b809150509250925092565b600082601f8301126159ba57600080fd5b813560206001600160401b038211156159d5576159d5615540565b8160051b6159e482820161557e565b92835284810182019282810190878511156159fe57600080fd5b83870192505b84831015615a1d57823582529183019190830190615a04565b979650505050505050565b600080600080600060a08688031215615a4057600080fd5b615a4986615524565b9450615a5760208701615524565b935060408601356001600160401b0380821115615a7357600080fd5b615a7f89838a016159a9565b94506060880135915080821115615a9557600080fd5b615aa189838a016159a9565b93506080880135915080821115615ab757600080fd5b50615ac488828901615605565b9150509295509295909350565b8015158114610c6357600080fd5b600060208284031215615af157600080fd5b813561146d81615ad1565b60ff81168114610c6357600080fd5b803561553b81615afc565b600080600060408486031215615b2b57600080fd5b83356001600160401b03811115615b4157600080fd5b615b4d868287016156a7565b909450925050602084013561599e81615afc565b60008060008060008060608789031215615b7a57600080fd5b86356001600160401b0380821115615b9157600080fd5b6158358a838b01615498565b600080600080600060a08688031215615bb557600080fd5b615bbe86615524565b9450615bcc60208701615524565b9350604086013592506060860135915060808601356001600160401b03811115615bf557600080fd5b615ac488828901615605565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b60208082526014908201527310dbdb9d1c9858dd1cc8185c995b89dd081cd95d60621b604082015260600190565b6020808252600c908201526b4e6f20636f6e74726163747360a01b604082015260600190565b6020808252600b908201526a456d70747920617272617960a81b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415615ce457615ce4615cba565b5060010190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b8183823760009101908152919050565b6020808252601290820152712737ba1030b236b4b71037b91037bbb732b960711b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60008235609e19833603018112615dc057600080fd5b9190910192915050565b60068110610c6357600080fd5b6000808335601e19843603018112615dee57600080fd5b8301803591506001600160401b03821115615e0857600080fd5b6020019150600581901b36038213156154dc57600080fd5b6000823560de19833603018112615dc057600080fd5b6000816000190483118215151615615e5057615e50615cba565b500290565b8054600080835581156108815782815260208120601f830160051c81015b8082101561114f57828255600182019150615e73565b600160401b821115615e9d57615e9d615540565b80548282558083101561088157600082815260208120601f850160051c8101601f840160051c82019150601f86168015615ee8576000198083018054828460200360031b1c16815550505b505b81811015611f0a57828155600101615eea565b8054600082558015615f32578160005260206000208181015b8082101561072e57615f2782615e55565b600182019150615f16565b5050565b600160401b821115615f4a57615f4a615540565b805482825580831015610881576000828152602090208381019082015b8082101561114f57615f7882615e55565b600182019150615f67565b8054600080835581156108815760016001600160fe1b038311811615615fab57615fab615cba565b60028483526020832084821b81015b808210156140c55784825584848301558483830155846003830155600482019150615fba565b600160401b821115615ff457615ff4615540565b805482825580831015610881576001600160fe1b03600181831181161561601d5761601d615cba565b600282861182161561603157616031615cba565b60008581526020812090935086821b81019085831b015b80821015610be25784825584848301558483830155846003830155600482019150616048565b8054600080835581156108815760016001600160fe1b03831181161561609657616096615cba565b60028483526020832084821b81015b808210156140c5578482556160bb848301615efd565b84838301556160cc60038301615f83565b6004820191506160a5565b600160401b8211156160eb576160eb615540565b805482825580831015610881576001600160fe1b03600181831181161561611457616114615cba565b600282861182161561612857616128615cba565b60008581526020812090935086821b81019085831b015b80821015610be257848255616155848301615efd565b848383015561616660038301615f83565b60048201915061613f565b6000813561062681615afc565b6000808335601e1984360301811261619557600080fd5b8301803591506001600160401b038211156161af57600080fd5b602001915060c0810236038213156154dc57600080fd5b6161d08382615fe0565b818160005260208060002060005b868110156140c557833582558284013560018301556040840135600283015560038201606085013561620f81615afc565b815460ff191660ff821617825550608085013561622b81615dca565b6162348161579c565b815461ff001916600882901b61ff00161782555060a085013561625681615afc565b815462ff00001916601082901b62ff000016178255505060c09390930192600491909101906001016161de565b81358155602082013560018201556002810160408301356162a381615afc565b815460ff191660ff82161782555060608301356162bf81615afc565b815461ff001916600882901b61ff001617905080825560808401356162e381615afc565b62ff0000601082901b1662ff00001983161791505080825560a084013561630981615ad1565b63ff000000199190911690151560181b63ff0000001617905561632f60c0830183615dd7565b61633c81600385016160d7565b81600060038501815260208120815b84811015610be257607e1986360301843512616365578283fd5b833586016163738135615afc565b825460ff191660ff823516178355600183016163926020830183615dd7565b61639c8184615f36565b918652602086209181875b8281101561643f576163b98285615dd7565b6163c38188615e89565b868b5260208b208b8c5b83811015616423576163df8535615afc565b82548260031b60ff811b8060ff893516831b1681198416178655505050602085019450600182019150601f82111561641b578d91506001830192505b6001016163cd565b50505050506020820191506001850194506001810190506163a7565b505050505061646861645360408301616171565b6002850160ff821660ff198254161781555050565b616475606082018261617e565b91506164858282600387016161c6565b5050602093909301926004919091019060010161634b565b8135815560018082016020808501356164b581615dca565b6164be8161579c565b60ff1983541660ff8216811791505080835560408601356164de81615dca565b6164e78161579c565b61ff00600882901b1661ff0019831617915050808355606086013561650b81615dca565b6165148161579c565b62ff0000601082901b1662ff000019831617915050808355608086013561653a81615dca565b6165438161579c565b63ff000000601882901b1663ff00000019831617845550506002915081840161656f60a0870187615dd7565b600160401b81111561658357616583615540565b825481845580821015616600576001600160fe1b038082118816156165aa576165aa615cba565b8083118816156165bc576165bc615cba565b50600084815285812083881b81019083891b015b808210156165fc57828255828a83015582898301556165f16003830161606e565b6004820191506165d0565b5050505b508194506166148360009081526020902090565b925060005b818110156132ef5761663461662e8785615e20565b85616283565b94840194600493909301928601616619565b8051600a811061553b57600080fd5b805161553b81615dca565b805161553b81615afc565b600082601f83011261667c57600080fd5b60405160c081018181106001600160401b038211171561669e5761669e615540565b6040528060c08401858111156166b357600080fd5b845b818110156166d65780516166c881615afc565b8352602092830192016166b5565b509195945050505050565b600061018082840312156166f457600080fd5b6166fc615556565b82516003811061670b57600080fd5b815261671960208401616646565b602082015261672a60408401616655565b604082015261673b60608401616660565b606082015261674c60808401616660565b608082015261675e8460a0850161666b565b60a0820152610160929092015160c083015250919050565b600181811c9082168061678a57607f821691505b602082108114156167ab57634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156167c357600080fd5b5051919050565b6000808335601e198436030181126167e157600080fd5b8301803591506001600160401b038211156167fb57600080fd5b60200191506060810236038213156154dc57600080fd5b6000825160005b818110156168335760208186018101518583015201616819565b81811115616842576000828501525b509190910192915050565b6020808252601390820152724c6567696f6e206973206e6f7420796f75727360681b604082015260600190565b600060ff821660ff84168060ff0382111561689757616897615cba565b019392505050565b60208082526025908201527f4c6567696f6e206e6f74206869676820656e6f756768207175657374696e67206040820152641b195d995b60da1b606082015260800190565b600060ff821660ff8114156168fb576168fb615cba565b60010192915050565b6000808335601e1984360301811261691b57600080fd5b8301803591506001600160401b0382111561693557600080fd5b6020019150368190038213156154dc57600080fd5b60006020828403121561695c57600080fd5b813561146d81615afc565b600060ff821660ff84168082101561698157616981615cba565b90039392505050565b6000821982111561699d5761699d615cba565b500190565b81835260006001600160fb1b038311156169bb57600080fd5b8260051b8083602087013760009401602001938452509192915050565b6001600160a01b0387811682528616602082015260a060408201819052600090616a0590830186886169a2565b8281036060840152616a188185876169a2565b8381036080909401939093525050600081526020019695505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000808335601e19843603018112616a7757600080fd5b83016020810192503590506001600160401b03811115616a9657600080fd5b8060051b36038313156154dc57600080fd5b60018060a01b0384168152826020820152606060408201528135606082015260006020830135601e19843603018112616ae057600080fd5b830180356001600160401b03811115616af857600080fd5b803603851315616b0757600080fd5b60a06080850152616b2061010085018260208501616a37565b915050616b2f60408501615b0b565b60ff1660a0840152616b446060850185616a60565b605f19808685030160c0870152616b5c8483856169a2565b9350616b6b6080880188616a60565b93509150808685030160e087015250616b858383836169a2565b98975050505050505050565b600060608083018784526020600a8810616bad57616bad615786565b84810188905260408086018490529186905286916080860160005b88811015616c0d578435616bdb81615afc565b60ff90811683528585013590616bf082615afc565b168285015284830135838301529385019390850190600101616bc8565b509a9950505050505050505050565b600060608284031215616c2e57600080fd5b604051606081018181106001600160401b0382111715616c5057616c50615540565b6040528251616c5e81615afc565b81526020830151616c6e81615afc565b60208201526040830151616c8181615ad1565b60408201529392505050565b6001600160a01b03841681526020808201849052606060408084018290528451848301819052600093608092909183870190888401875b82811015616cf95781518051855286810151878601528581015186860152880151888501529286019290850190600101616cc4565b50919b9a5050505050505050505050565b600082616d2757634e487b7160e01b600052601260045260246000fd5b500690565b600081616d3b57616d3b615cba565b506000190190565b600082821015616d5557616d55615cba565b500390565b600060ff821660ff84168160ff0481118215151615616d7b57616d7b615cba565b029392505050565b600081518084526020808501945080840160005b83811015616db357815187529582019590820190600101616d97565b509495945050505050565b6001600160a01b0385811682528416602082015260a060408201819052600090616dea90830185616d83565b8281036060840152616dfc8185616d83565b838103608090940193909352505060008152602001949350505050565b60208082526028908201527f43616e6e6f7420706c6179207472656173757265207468617420776173206e6f6040820152671d081cdd185ad95960c21b606082015260800190565b60ff8416815260608101616e748461579c565b602082019390935260400152919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea264697066735822122088ec1a47137cbc352be0919da89d946e20016dd1604431a44949a7eb593d4f7164736f6c63430008090033
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.