Token MetaLine MysteryBox Semi-fungible Token

 

Overview ERC-1155

Total Supply:
0 MLMB

Holders:
1,888 addresses

Transfers:
-

Loading
[ Download CSV Export  ] 
Loading
Loading

Click here to update the token ICO / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
MysteryBox1155

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
File 1 of 43 : AccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (access/AccessControl.sol)

pragma solidity ^0.8.0;

import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `_msgSender()` is missing `role`.
     * Overriding this function changes the behavior of the {onlyRole} modifier.
     *
     * Format of the revert message is described in {_checkRole}.
     *
     * _Available since v4.6._
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(uint160(account), 20),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

File 2 of 43 : IAccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

File 3 of 43 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.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 Pausable is Context {
    /**
     * @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.
     */
    constructor() {
        _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());
    }
}

File 4 of 43 : ERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/ERC1155.sol)

pragma solidity ^0.8.0;

import "./IERC1155.sol";
import "./IERC1155Receiver.sol";
import "./extensions/IERC1155MetadataURI.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of the basic standard multi-token.
 * See https://eips.ethereum.org/EIPS/eip-1155
 * Originally based on code by Enjin: https://github.com/enjin/erc-1155
 *
 * _Available since v3.1._
 */
contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
    using Address for address;

    // Mapping from token ID to account balances
    mapping(uint256 => mapping(address => uint256)) private _balances;

    // Mapping from account to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
    string private _uri;

    /**
     * @dev See {_setURI}.
     */
    constructor(string memory uri_) {
        _setURI(uri_);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC1155).interfaceId ||
            interfaceId == type(IERC1155MetadataURI).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC1155MetadataURI-uri}.
     *
     * This implementation returns the same URI for *all* token types. It relies
     * on the token type ID substitution mechanism
     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
     *
     * Clients calling this function must replace the `\{id\}` substring with the
     * actual token type ID.
     */
    function uri(uint256) public view virtual override returns (string memory) {
        return _uri;
    }

    /**
     * @dev See {IERC1155-balanceOf}.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
        require(account != address(0), "ERC1155: balance query for the zero address");
        return _balances[id][account];
    }

    /**
     * @dev See {IERC1155-balanceOfBatch}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] memory accounts, uint256[] memory ids)
        public
        view
        virtual
        override
        returns (uint256[] memory)
    {
        require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");

        uint256[] memory batchBalances = new uint256[](accounts.length);

        for (uint256 i = 0; i < accounts.length; ++i) {
            batchBalances[i] = balanceOf(accounts[i], ids[i]);
        }

        return batchBalances;
    }

    /**
     * @dev See {IERC1155-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC1155-isApprovedForAll}.
     */
    function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[account][operator];
    }

    /**
     * @dev See {IERC1155-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) public virtual override {
        require(
            from == _msgSender() || isApprovedForAll(from, _msgSender()),
            "ERC1155: caller is not owner nor approved"
        );
        _safeTransferFrom(from, to, id, amount, data);
    }

    /**
     * @dev See {IERC1155-safeBatchTransferFrom}.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) public virtual override {
        require(
            from == _msgSender() || isApprovedForAll(from, _msgSender()),
            "ERC1155: transfer caller is not owner nor approved"
        );
        _safeBatchTransferFrom(from, to, ids, amounts, data);
    }

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function _safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual {
        require(to != address(0), "ERC1155: transfer to the zero address");

        address operator = _msgSender();
        uint256[] memory ids = _asSingletonArray(id);
        uint256[] memory amounts = _asSingletonArray(amount);

        _beforeTokenTransfer(operator, from, to, ids, amounts, data);

        uint256 fromBalance = _balances[id][from];
        require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
        unchecked {
            _balances[id][from] = fromBalance - amount;
        }
        _balances[id][to] += amount;

        emit TransferSingle(operator, from, to, id, amount);

        _afterTokenTransfer(operator, from, to, ids, amounts, data);

        _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function _safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
        require(to != address(0), "ERC1155: transfer to the zero address");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, from, to, ids, amounts, data);

        for (uint256 i = 0; i < ids.length; ++i) {
            uint256 id = ids[i];
            uint256 amount = amounts[i];

            uint256 fromBalance = _balances[id][from];
            require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
            unchecked {
                _balances[id][from] = fromBalance - amount;
            }
            _balances[id][to] += amount;
        }

        emit TransferBatch(operator, from, to, ids, amounts);

        _afterTokenTransfer(operator, from, to, ids, amounts, data);

        _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
    }

    /**
     * @dev Sets a new URI for all token types, by relying on the token type ID
     * substitution mechanism
     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
     *
     * By this mechanism, any occurrence of the `\{id\}` substring in either the
     * URI or any of the amounts in the JSON file at said URI will be replaced by
     * clients with the token type ID.
     *
     * For example, the `https://token-cdn-domain/\{id\}.json` URI would be
     * interpreted by clients as
     * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
     * for token type ID 0x4cce0.
     *
     * See {uri}.
     *
     * Because these URIs cannot be meaningfully represented by the {URI} event,
     * this function emits no events.
     */
    function _setURI(string memory newuri) internal virtual {
        _uri = newuri;
    }

    /**
     * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function _mint(
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual {
        require(to != address(0), "ERC1155: mint to the zero address");

        address operator = _msgSender();
        uint256[] memory ids = _asSingletonArray(id);
        uint256[] memory amounts = _asSingletonArray(amount);

        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);

        _balances[id][to] += amount;
        emit TransferSingle(operator, address(0), to, id, amount);

        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);

        _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function _mintBatch(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        require(to != address(0), "ERC1155: mint to the zero address");
        require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);

        for (uint256 i = 0; i < ids.length; i++) {
            _balances[ids[i]][to] += amounts[i];
        }

        emit TransferBatch(operator, address(0), to, ids, amounts);

        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);

        _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
    }

    /**
     * @dev Destroys `amount` tokens of token type `id` from `from`
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `from` must have at least `amount` tokens of token type `id`.
     */
    function _burn(
        address from,
        uint256 id,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC1155: burn from the zero address");

        address operator = _msgSender();
        uint256[] memory ids = _asSingletonArray(id);
        uint256[] memory amounts = _asSingletonArray(amount);

        _beforeTokenTransfer(operator, from, address(0), ids, amounts, "");

        uint256 fromBalance = _balances[id][from];
        require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
        unchecked {
            _balances[id][from] = fromBalance - amount;
        }

        emit TransferSingle(operator, from, address(0), id, amount);

        _afterTokenTransfer(operator, from, address(0), ids, amounts, "");
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     */
    function _burnBatch(
        address from,
        uint256[] memory ids,
        uint256[] memory amounts
    ) internal virtual {
        require(from != address(0), "ERC1155: burn from the zero address");
        require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, from, address(0), ids, amounts, "");

        for (uint256 i = 0; i < ids.length; i++) {
            uint256 id = ids[i];
            uint256 amount = amounts[i];

            uint256 fromBalance = _balances[id][from];
            require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
            unchecked {
                _balances[id][from] = fromBalance - amount;
            }
        }

        emit TransferBatch(operator, from, address(0), ids, amounts);

        _afterTokenTransfer(operator, from, address(0), ids, amounts, "");
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits a {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC1155: setting approval status for self");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning, as well as batched variants.
     *
     * The same hook is called on both single and batched variants. For single
     * transfers, the length of the `id` and `amount` arrays will be 1.
     *
     * Calling conditions (for each `id` and `amount` pair):
     *
     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * of token type `id` will be  transferred to `to`.
     * - When `from` is zero, `amount` tokens of token type `id` will be minted
     * for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
     * will be burned.
     * - `from` and `to` are never both zero.
     * - `ids` and `amounts` have the same, non-zero length.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {}

    /**
     * @dev Hook that is called after any token transfer. This includes minting
     * and burning, as well as batched variants.
     *
     * The same hook is called on both single and batched variants. For single
     * transfers, the length of the `id` and `amount` arrays will be 1.
     *
     * Calling conditions (for each `id` and `amount` pair):
     *
     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * of token type `id` will be  transferred to `to`.
     * - When `from` is zero, `amount` tokens of token type `id` will be minted
     * for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
     * will be burned.
     * - `from` and `to` are never both zero.
     * - `ids` and `amounts` have the same, non-zero length.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {}

    function _doSafeTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) private {
        if (to.isContract()) {
            try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
                if (response != IERC1155Receiver.onERC1155Received.selector) {
                    revert("ERC1155: ERC1155Receiver rejected tokens");
                }
            } catch Error(string memory reason) {
                revert(reason);
            } catch {
                revert("ERC1155: transfer to non ERC1155Receiver implementer");
            }
        }
    }

    function _doSafeBatchTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) private {
        if (to.isContract()) {
            try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
                bytes4 response
            ) {
                if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
                    revert("ERC1155: ERC1155Receiver rejected tokens");
                }
            } catch Error(string memory reason) {
                revert(reason);
            } catch {
                revert("ERC1155: transfer to non ERC1155Receiver implementer");
            }
        }
    }

    function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
        uint256[] memory array = new uint256[](1);
        array[0] = element;

        return array;
    }
}

File 5 of 43 : ERC1155Burnable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/ERC1155Burnable.sol)

pragma solidity ^0.8.0;

import "../ERC1155.sol";

/**
 * @dev Extension of {ERC1155} that allows token holders to destroy both their
 * own tokens and those that they have been approved to use.
 *
 * _Available since v3.1._
 */
abstract contract ERC1155Burnable is ERC1155 {
    function burn(
        address account,
        uint256 id,
        uint256 value
    ) public virtual {
        require(
            account == _msgSender() || isApprovedForAll(account, _msgSender()),
            "ERC1155: caller is not owner nor approved"
        );

        _burn(account, id, value);
    }

    function burnBatch(
        address account,
        uint256[] memory ids,
        uint256[] memory values
    ) public virtual {
        require(
            account == _msgSender() || isApprovedForAll(account, _msgSender()),
            "ERC1155: caller is not owner nor approved"
        );

        _burnBatch(account, ids, values);
    }
}

File 6 of 43 : ERC1155Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/ERC1155Pausable.sol)

pragma solidity ^0.8.0;

import "../ERC1155.sol";
import "../../../security/Pausable.sol";

/**
 * @dev ERC1155 token with pausable token transfers, minting and burning.
 *
 * Useful for scenarios such as preventing trades until the end of an evaluation
 * period, or having an emergency switch for freezing all token transfers in the
 * event of a large bug.
 *
 * _Available since v3.1._
 */
abstract contract ERC1155Pausable is ERC1155, Pausable {
    /**
     * @dev See {ERC1155-_beforeTokenTransfer}.
     *
     * Requirements:
     *
     * - the contract must not be paused.
     */
    function _beforeTokenTransfer(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual override {
        super._beforeTokenTransfer(operator, from, to, ids, amounts, data);

        require(!paused(), "ERC1155Pausable: token transfer while paused");
    }
}

File 7 of 43 : ERC1155Supply.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155Supply.sol)

pragma solidity ^0.8.0;

import "../ERC1155.sol";

/**
 * @dev Extension of ERC1155 that adds tracking of total supply per id.
 *
 * Useful for scenarios where Fungible and Non-fungible tokens have to be
 * clearly identified. Note: While a totalSupply of 1 might mean the
 * corresponding is an NFT, there is no guarantees that no other token with the
 * same id are not going to be minted.
 */
abstract contract ERC1155Supply is ERC1155 {
    mapping(uint256 => uint256) private _totalSupply;

    /**
     * @dev Total amount of tokens in with a given id.
     */
    function totalSupply(uint256 id) public view virtual returns (uint256) {
        return _totalSupply[id];
    }

    /**
     * @dev Indicates whether any token exist with a given id, or not.
     */
    function exists(uint256 id) public view virtual returns (bool) {
        return ERC1155Supply.totalSupply(id) > 0;
    }

    /**
     * @dev See {ERC1155-_beforeTokenTransfer}.
     */
    function _beforeTokenTransfer(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual override {
        super._beforeTokenTransfer(operator, from, to, ids, amounts, data);

        if (from == address(0)) {
            for (uint256 i = 0; i < ids.length; ++i) {
                _totalSupply[ids[i]] += amounts[i];
            }
        }

        if (to == address(0)) {
            for (uint256 i = 0; i < ids.length; ++i) {
                uint256 id = ids[i];
                uint256 amount = amounts[i];
                uint256 supply = _totalSupply[id];
                require(supply >= amount, "ERC1155: burn amount exceeds totalSupply");
                unchecked {
                    _totalSupply[id] = supply - amount;
                }
            }
        }
    }
}

File 8 of 43 : IERC1155MetadataURI.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)

pragma solidity ^0.8.0;

import "../IERC1155.sol";

/**
 * @dev Interface of the optional ERC1155MetadataExtension interface, as defined
 * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155MetadataURI is IERC1155 {
    /**
     * @dev Returns the URI for token type `id`.
     *
     * If the `\{id\}` substring is present in the URI, it must be replaced by
     * clients with the actual token type ID.
     */
    function uri(uint256 id) external view returns (string memory);
}

File 9 of 43 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the amount of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
        external
        view
        returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must 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;
}

File 10 of 43 : IERC1155Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev _Available since v3.1._
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}

File 11 of 43 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
        }
        _balances[to] += amount;

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

File 12 of 43 : ERC20Burnable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)

pragma solidity ^0.8.0;

import "../ERC20.sol";
import "../../../utils/Context.sol";

/**
 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
 */
abstract contract ERC20Burnable is Context, ERC20 {
    /**
     * @dev Destroys `amount` tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 amount) public virtual {
        _burn(_msgSender(), amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, deducting from the caller's
     * allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `amount`.
     */
    function burnFrom(address account, uint256 amount) public virtual {
        _spendAllowance(account, _msgSender(), amount);
        _burn(account, amount);
    }
}

File 13 of 43 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 14 of 43 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 15 of 43 : ERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;

import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @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.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, _data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        _afterTokenTransfer(address(0), to, tokenId);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);

        _afterTokenTransfer(owner, address(0), tokenId);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits a {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}

File 16 of 43 : ERC721Burnable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Burnable.sol)

pragma solidity ^0.8.0;

import "../ERC721.sol";
import "../../../utils/Context.sol";

/**
 * @title ERC721 Burnable Token
 * @dev ERC721 Token that can be irreversibly burned (destroyed).
 */
abstract contract ERC721Burnable is Context, ERC721 {
    /**
     * @dev Burns `tokenId`. See {ERC721-_burn}.
     *
     * Requirements:
     *
     * - The caller must own `tokenId` or be an approved operator.
     */
    function burn(uint256 tokenId) public virtual {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721Burnable: caller is not owner nor approved");
        _burn(tokenId);
    }
}

File 17 of 43 : ERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)

pragma solidity ^0.8.0;

import "../ERC721.sol";
import "./IERC721Enumerable.sol";

/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds
 * enumerability of all the token ids in the contract as well as all token ids owned by each
 * account.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) private _ownedTokensIndex;

    // Array with all token ids, used for enumeration
    uint256[] private _allTokens;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) private _allTokensIndex;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
        return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
        return _ownedTokens[owner][index];
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _allTokens.length;
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
        return _allTokens[index];
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId);

        if (from == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (from != to) {
            _removeTokenFromOwnerEnumeration(from, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (to != from) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        uint256 length = ERC721.balanceOf(to);
        _ownedTokens[to][length] = tokenId;
        _ownedTokensIndex[tokenId] = length;
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }
}

File 18 of 43 : ERC721Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Pausable.sol)

pragma solidity ^0.8.0;

import "../ERC721.sol";
import "../../../security/Pausable.sol";

/**
 * @dev ERC721 token with pausable token transfers, minting and burning.
 *
 * Useful for scenarios such as preventing trades until the end of an evaluation
 * period, or having an emergency switch for freezing all token transfers in the
 * event of a large bug.
 */
abstract contract ERC721Pausable is ERC721, Pausable {
    /**
     * @dev See {ERC721-_beforeTokenTransfer}.
     *
     * Requirements:
     *
     * - the contract must not be paused.
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId);

        require(!paused(), "ERC721Pausable: token transfer while paused");
    }
}

File 19 of 43 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

File 20 of 43 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @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);
}

File 21 of 43 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @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`.
     *
     * 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;

    /**
     * @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 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 the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @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);
}

File 22 of 43 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (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 IERC721Receiver {
    /**
     * @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 `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 23 of 43 : Address.sol
// 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 Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return 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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(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);
            }
        }
    }
}

File 24 of 43 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 25 of 43 : Counters.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

File 26 of 43 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 27 of 43 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 28 of 43 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 29 of 43 : Extendable1155.sol
// SPDX-License-Identifier: MIT
// Mateline Contracts (Extendable1155.sol)

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import "../interface/ERC/IERC2981Royalties.sol";
import "../utility/TransferHelper.sol";

/**
 * @dev {ERC1155} token, including:
 *
 *  - ability for holders to burn (destroy) their tokens
 *  - a minter role that allows for token minting (creation)
 *  - a pauser role that allows to stop all token transfers
 *
 * This contract uses {AccessControl} to lock permissioned functions using the
 * different roles - head to its documentation for details.
 *
 * The account that deploys the contract will be granted the minter and pauser
 * roles, as well as the default admin role, which will let it grant both minter
 * and pauser roles to other accounts.
 */
contract ERC1155PresetMinterPauser is 
    Context, 
    AccessControl, 
    ERC1155Burnable, 
    ERC1155Pausable, 
    ERC1155Supply, 
    IERC2981Royalties 
{
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // erc2981 royalty fee, /10000
    uint256 public _royalties;

    /**
     * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE`, and `PAUSER_ROLE` to the account that
     * deploys the contract.
     */
    constructor(
        string memory name_,
        string memory symbol_,
        string memory uri
    ) ERC1155(uri) {
        _name = name_;
        _symbol = symbol_;
        _royalties = 500; // 5%

        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(MINTER_ROLE, _msgSender());
        _setupRole(PAUSER_ROLE, _msgSender());
    }

    /**
     * @dev As 1155 contract name for some dApp which read name from contract, See {IERC721Metadata-name}.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev As 1155 contract symbol for some dApp which read symbol from contract, See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev update base token uri, See {IERC1155MetadataURI-uri}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function updateURI(string calldata newuri) public virtual {
        require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role to update");
        _setURI(newuri);
    }

    /**
     * @dev Creates `amount` new tokens for `to`, of token type `id`.
     *
     * See {ERC1155-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function mint(
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) public virtual {
        require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role to mint");

        _mint(to, id, amount, data);
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] variant of {mint}.
     */
    function mintBatch(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) public virtual {
        require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role to mint");

        _mintBatch(to, ids, amounts, data);
    }

    /**
     * @dev Pauses all token transfers.
     *
     * See {ERC1155Pausable} and {Pausable-_pause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function pause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have pauser role to pause");
        _pause();
    }

    /**
     * @dev Unpauses all token transfers.
     *
     * See {ERC1155Pausable} and {Pausable-_unpause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function unpause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have pauser role to unpause");
        _unpause();
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(AccessControl, ERC1155)
        returns (bool)
    {
        return interfaceId == type(IERC2981Royalties).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    function _beforeTokenTransfer(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual override(ERC1155, ERC1155Pausable, ERC1155Supply) {
        super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
    }

    // set royalties
    function setRoyalties(uint256 royalties) external {
        require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role");
        _royalties = royalties;
    }

    /// @inheritdoc	IERC2981Royalties
    function royaltyInfo(uint256, uint256 value)
        external
        view
        override
        returns (address receiver, uint256 royaltyAmount)
    {
        receiver = address(this);
        royaltyAmount = (value * _royalties) / 10000;
    }

    // fetch royalty income
    function fetchIncome(address erc20) external {
        require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role");

        uint256 amount = IERC20(erc20).balanceOf(address(this));
        if(amount > 0) {
            TransferHelper.safeTransfer(erc20, _msgSender(), amount);
        }
    }
    function fetchIncomeEth() external {
        require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role");

        // send eth
        (bool sent, ) = _msgSender().call{value:address(this).balance}("");
        require(sent, "ERC1155PresetMinterPauser: transfer error");
    }
}

contract Extendable1155 is ERC1155PresetMinterPauser {
    
    bytes32 public constant DATA_ROLE = keccak256("DATA_ROLE");

    /**
    * @dev emit when token data section changed

    * @param id 1155 id which data has been changed
    * @param extendData data after change
    */
    event Extendable1155Modify(uint256 indexed id, bytes extendData);

    mapping(uint256=>bytes) _extendDatas;

    constructor(
        string memory name_,
        string memory symbol_,
        string memory uri) ERC1155PresetMinterPauser(name_, symbol_, uri) 
    {
    }

    /**
    * @dev modify extend 1155 data, emit {Extendable1155Modify} event
    *
    * Requirements:
    * - caller must have general `DATA_ROLE`
    *
    * @param id 1155 id to modify extend data
    * @param extendData extend data in bytes, use a codec to encode or decode the bytes data outside
    */
    function modifyExtendData(
        uint256 id,
        bytes memory extendData
    ) external whenNotPaused {
        require(
            hasRole(DATA_ROLE, _msgSender()),
            "R6"
        );

        require(
            exists(id),
            "E4"
        );

        // modify extend data
        _extendDatas[id] = extendData;

        emit Extendable1155Modify(id, extendData);
    }

    /**
    * @dev get extend 1155 data 
    *
    * @param id 1155 id to get extend data
    * @return extend data in bytes, use a codec to encode or decode the bytes data outside
    */
    function getTokenExtendNftData(uint256 id)
        external
        view
        returns (bytes memory)
    {
        require(exists(id), "E6");

        return _extendDatas[id];
    }

}

File 30 of 43 : ExtendableNFT.sol
// SPDX-License-Identifier: MIT
// Mateline Contracts (ExtendableNFT.sol)

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import "../interface/ERC/IERC2981Royalties.sol";
import "../utility/TransferHelper.sol";

/**
 * @dev {ERC721} token, including:
 *
 *  - ability for holders to burn (destroy) their tokens
 *  - a minter role that allows for token minting (creation)
 *  - a pauser role that allows to stop all token transfers
 *  - token ID and URI autogeneration
 *
 * This contract uses {AccessControl} to lock permissioned functions using the
 * different roles - head to its documentation for details.
 *
 * The account that deploys the contract will be granted the minter and pauser
 * roles, as well as the default admin role, which will let it grant both minter
 * and pauser roles to other accounts.
 */
contract ERC721PresetMinterPauserAutoId is
    Context,
    AccessControl,
    ERC721Enumerable,
    ERC721Burnable,
    ERC721Pausable, 
    IERC2981Royalties
{
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

    string internal _baseTokenURI;

    // erc2981 royalty fee, /10000
    uint256 public _royalties;

    /**
     * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
     * account that deploys the contract.
     *
     * Token URIs will be autogenerated based on `baseURI` and their token IDs.
     * See {ERC721-tokenURI}.
     */
    constructor(
        string memory name,
        string memory symbol,
        string memory baseTokenURI
    ) ERC721(name, symbol) {
        _baseTokenURI = baseTokenURI;
        _royalties = 500; // 5%

        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(MINTER_ROLE, _msgSender());
        _setupRole(PAUSER_ROLE, _msgSender());
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return _baseTokenURI;
    }

    /**
     * @dev update base token uri.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function updateURI(string calldata baseTokenURI) public virtual {
        require(hasRole(MINTER_ROLE, _msgSender()), "M1");
        _baseTokenURI = baseTokenURI;
    }

    /**
     * @dev Pauses all token transfers.
     *
     * See {ERC721Pausable} and {Pausable-_pause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function pause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "P1");
        _pause();
    }

    /**
     * @dev Unpauses all token transfers.
     *
     * See {ERC721Pausable} and {Pausable-_unpause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function unpause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "P2");
        _unpause();
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override(ERC721, ERC721Enumerable, ERC721Pausable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(AccessControl, ERC721, ERC721Enumerable)
        returns (bool)
    {
        return interfaceId == type(IERC2981Royalties).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    // set royalties
    function setRoyalties(uint256 royalties) external {
        require(hasRole(MINTER_ROLE, _msgSender()), "M1");
        _royalties = royalties;
    }

    /// @inheritdoc	IERC2981Royalties
    function royaltyInfo(uint256, uint256 value)
        external
        view
        override
        returns (address receiver, uint256 royaltyAmount)
    {
        receiver = address(this);
        royaltyAmount = (value * _royalties) / 10000;
    }

    // fetch royalty income
    function fetchIncome(address erc20) external {
        require(hasRole(MINTER_ROLE, _msgSender()), "M1");

        uint256 amount = IERC20(erc20).balanceOf(address(this));
        if(amount > 0) {
            TransferHelper.safeTransfer(erc20, _msgSender(), amount);
        }
    }
    function fetchIncomeEth() external {
        require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role");

        // send eth
        (bool sent, ) = _msgSender().call{value:address(this).balance}("");
        require(sent, "ERC1155PresetMinterPauser: transfer error");
    }
}

/**
 * @dev Extension of {ERC721PresetMinterPauserAutoId} that allows token dynamic extend data section
 */
contract ExtendableNFT is ERC721PresetMinterPauserAutoId {
    
    bytes32 public constant DATA_ROLE = keccak256("DATA_ROLE");
    bytes32 public constant FREEZE_ROLE = keccak256("FREEZE_ROLE");

    /**
    * @dev emit when token has been freezed or unfreeze

    * @param tokenId freezed token id
    * @param freeze freezed or not
    */
    event NFTFreeze(uint256 indexed tokenId, bool freeze);
    
    /**
    * @dev emit when new data section created

    * @param extendName new data section name
    * @param nameBytes data section name after keccak256
    */
    event NFTExtendName(string extendName, bytes32 nameBytes);

    /**
    * @dev emit when token data section changed

    * @param tokenId tokenid which data has been changed
    * @param nameBytes data section name after keccak256
    * @param extendData data after change
    */
    event NFTExtendModify(uint256 indexed tokenId, bytes32 nameBytes, bytes extendData);

    // record of token already extended data section
    struct NFTExtendsNames{
        bytes32[]   NFTExtendDataNames; // array of data sectioin name after keccak256
    }

    // extend data mapping
    struct NFTExtendData {
        bool _exist;
        mapping(uint256 => bytes) ExtendDatas; // tokenid => data mapping
    }

    mapping(uint256 => bool) private _nftFreezed; // tokenid => is freezed
    mapping(uint256 => NFTExtendsNames) private _nftExtendNames; // tokenid => extended data sections
    mapping(bytes32 => NFTExtendData) private _nftExtendDataMap; // extend name => extend datas mapping

    constructor(
        string memory name,
        string memory symbol,
        string memory baseTokenURI) 
        ERC721PresetMinterPauserAutoId(name, symbol, baseTokenURI) 
    {
    }

    /**
    * @dev freeze token, emit {NFTFreeze} event
    *
    * Requirements:
    * - caller must have `FREEZE_ROLE`
    *
    * @param tokenId token to freeze
    */
    function freeze(uint256 tokenId) external {
        require(hasRole(FREEZE_ROLE, _msgSender()), "R2");

        _nftFreezed[tokenId] = true;

        emit NFTFreeze(tokenId, true);
    }

    /**
    * @dev unfreeze token, emit {NFTFreeze} event
    *
    * Requirements:
    * - caller must have `FREEZE_ROLE`
    *
    * @param tokenId token to unfreeze
    */
    function unfreeze(uint256 tokenId) external {
        require(hasRole(FREEZE_ROLE, _msgSender()), "R3");

        delete _nftFreezed[tokenId];

        emit NFTFreeze(tokenId, false);
    }

    /**
    * @dev check token, return true if not freezed
    *
    * @param tokenId token to check
    * @return ture if token is not freezed
    */
    function notFreezed(uint256 tokenId) public view returns (bool) {
        return !_nftFreezed[tokenId];
    }

    /**
    * @dev check token, return true if it's freezed
    *
    * @param tokenId token to check
    * @return ture if token is freezed
    */
    function isFreezed(uint256 tokenId) public view returns (bool) {
        return _nftFreezed[tokenId];
    }

    /**
    * @dev check token, return true if it exists
    *
    * @param tokenId token to check
    * @return ture if token exists
    */
    function exists(uint256 tokenId) public view returns (bool) {
        return _exists(tokenId);
    }

    /**
    * @dev add new token data section, emit {NFTExtendName} event
    *
    * Requirements:
    * - caller must have `MINTER_ROLE`
    *
    * @param extendName string of new data section name
    */
    function extendNftData(string memory extendName) external {
        require(hasRole(MINTER_ROLE, _msgSender()), "R5");

        bytes32 nameBytes = keccak256(bytes(extendName));
        NFTExtendData storage extendData = _nftExtendDataMap[nameBytes];
        extendData._exist = true;

        emit NFTExtendName(extendName, nameBytes);
    }

    /**
    * @dev add extend token data with specify 'extendName', emit {NFTExtendModify} event
    *
    * Requirements:
    * - caller must have general `DATA_ROLE` or `DATA_ROLE` with the specify `extendName`
    *
    * @param tokenId token to add extend data
    * @param extendName data section name in string
    * @param extendData extend data in bytes, use a codec to encode or decode the bytes data outside
    */
    function addTokenExtendNftData(
        uint256 tokenId,
        string memory extendName,
        bytes memory extendData
    ) external whenNotPaused {
        require(
            hasRole(DATA_ROLE, _msgSender()) ||
                hasRole(
                    keccak256(abi.encodePacked("DATA_ROLE", extendName)),
                    _msgSender()
                ),
            "R6"
        );

        bytes32 nameBytes = keccak256(bytes(extendName));
        require(_extendNameExist(nameBytes), "E1");
        require(!_tokenExtendNameExist(tokenId, nameBytes), "E2");

        // modify extend data
        NFTExtendData storage extendDatas = _nftExtendDataMap[nameBytes];
        extendDatas.ExtendDatas[tokenId] = extendData;

        // save token extend data names
        NFTExtendsNames storage nftData = _nftExtendNames[tokenId];
        nftData.NFTExtendDataNames.push(nameBytes);

        emit NFTExtendModify(tokenId, nameBytes, extendData);
    }

    /**
    * @dev modify extend token data with specify 'extendName', emit {NFTExtendModify} event
    *
    * Requirements:
    * - caller must have general `DATA_ROLE` or `DATA_ROLE` with the specify `extendName`
    *
    * @param tokenId token to modify extend data
    * @param extendName data section name in string
    * @param extendData extend data in bytes, use a codec to encode or decode the bytes data outside
    */
    function modifyTokenExtendNftData(
        uint256 tokenId,
        string memory extendName,
        bytes memory extendData
    ) external whenNotPaused {
        require(
            hasRole(DATA_ROLE, _msgSender()) ||
                hasRole(
                    keccak256(abi.encodePacked("DATA_ROLE", extendName)),
                    _msgSender()
                ),
            "R6"
        );

        bytes32 nameBytes = keccak256(bytes(extendName));
        require(_extendNameExist(nameBytes), "E4");
        require(_tokenExtendNameExist(tokenId, nameBytes), "E5");

        // modify extend data
        NFTExtendData storage extendDatas = _nftExtendDataMap[nameBytes];
        extendDatas.ExtendDatas[tokenId] = extendData;

        emit NFTExtendModify(tokenId, nameBytes, extendData);
    }

    /**
    * @dev get extend token data with specify 'extendName'
    *
    * @param tokenId token to get extend data
    * @param extendName data section name in string
    * @return extend data in bytes, use a codec to encode or decode the bytes data outside
    */
    function getTokenExtendNftData(uint256 tokenId, string memory extendName)
        external
        view
        returns (bytes memory)
    {
        bytes32 nameBytes = keccak256(bytes(extendName));
        require(_extendNameExist(nameBytes), "E6");

        NFTExtendData storage extendDatas = _nftExtendDataMap[nameBytes];
        return extendDatas.ExtendDatas[tokenId];
    }

    function _extendNameExist(bytes32 nameBytes) internal view returns (bool) {
        return _nftExtendDataMap[nameBytes]._exist;
    }
    function _tokenExtendNameExist(uint256 tokenId, bytes32 nameBytes) internal view returns(bool) {
        NFTExtendsNames memory nftData = _nftExtendNames[tokenId];
        for(uint i=0; i<nftData.NFTExtendDataNames.length; ++i){
            if(nftData.NFTExtendDataNames[i] == nameBytes){
                return true;
            }
        }
        return false;
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        require(notFreezed(tokenId), "F1");

        super._beforeTokenTransfer(from, to, tokenId);

        if (to == address(0)) {
            // delete token extend datas;
            NFTExtendsNames memory nftData = _nftExtendNames[tokenId];
            for(uint i = 0; i< nftData.NFTExtendDataNames.length; ++i){
                NFTExtendData storage extendData = _nftExtendDataMap[nftData.NFTExtendDataNames[i]];
                delete extendData.ExtendDatas[tokenId];
            }

            // delete token datas
            delete _nftExtendNames[tokenId];
        }
    }
}

File 31 of 43 : HeroNFT.sol
// SPDX-License-Identifier: MIT
// Mateline Contracts (HeroNFT.sol)

pragma solidity ^0.8.0;

import "./utility/ResetableCounters.sol";

import "./core/ExtendableNFT.sol";
import "./HeroNFTCodec.sol";

/**
 * @dev Extension of {ExtendableNFT} that with fixed token data struct
 */
contract HeroNFT is ExtendableNFT {
    using ResetableCounters for ResetableCounters.Counter;

    /**
    * @dev emit when new token has been minted, see {HeroNFTDataBase}
    *
    * @param to owner of new token
    * @param tokenId new token id
    * @param data token data see {HeroNFTDataBase}
    */
    event HeroNFTMint(address indexed to, uint256 indexed tokenId, HeroNFTDataBase data);

    ResetableCounters.Counter internal _tokenIdTracker;

    address public _codec;
    address public _attrSource;
    
    mapping(uint256 => HeroNFTDataBase) private _nftDatas; // token id => nft data stucture

    constructor(
        uint256 idStart,
        string memory name,
        string memory symbol,
        string memory baseTokenURI) 
        ExtendableNFT(name, symbol, baseTokenURI)
    {
       _tokenIdTracker.reset(idStart);

        mint(_msgSender(), HeroNFTDataBase({
            fixedData:0,
            writeableData:0
        })); // mint first token to notify event scan
        
       _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
       _setupRole(DATA_ROLE, _msgSender());
    }

    function setAttrSource(address a) external {
        require(
            hasRole(DATA_ROLE, _msgSender()),
            "R1"
        );

        _attrSource = a;
    }
    function getAttrSource() external view returns(address a) {
        return _attrSource;
    }

    function setCodec(address c) external {
        require(
            hasRole(DATA_ROLE, _msgSender()),
            "R1"
        );

        _codec = c;
    }
    function getCodec() external view returns(address c) {
        return _codec;
    }

    /**
     * @dev Creates a new token for `to`, emit {HeroNFTMint}. Its token ID will be automatically
     * assigned (and available on the emitted {IERC721-Transfer} event), and the token
     * URI autogenerated based on the base URI passed at construction.
     *
     * See {ERC721-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     *
     * @param to new token owner address
     * @param data token data see {HeroNFTDataBase}
     * @return new token id
     */
    function mint(address to, HeroNFTDataBase memory data) public returns(uint256) {
        require(hasRole(MINTER_ROLE, _msgSender()), "R1");

        // We cannot just use balanceOf to create the new tokenId because tokens
        // can be burned (destroyed), so we need a separate counter.
        uint256 curID = _tokenIdTracker.current();

        _mint(to, curID);

        // Save token datas
        _nftDatas[curID] = data;

        emit HeroNFTMint(to, curID, data);

        // increase token id
        _tokenIdTracker.increment();

        return curID;
    }

    /**
     * @dev Creates a new token for `to`, emit {HeroNFTMint}. Its token ID give by caller
     * (and available on the emitted {IERC721-Transfer} event), and the token
     * URI autogenerated based on the base URI passed at construction.
     *
     * See {ERC721-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     *
     * @param id new token id
     * @param to new token owner address
     * @param data token data see {HeroNFTDataBase}
     * @return new token id
     */
    function mintFixedID(
        uint256 id,
        address to,
        HeroNFTDataBase memory data
    ) public returns (uint256) {
        require(hasRole(MINTER_ROLE, _msgSender()), "R1");

        require(!_exists(id), "RE");

        _mint(to, id);

        // Save token datas
        _nftDatas[id] = data;

        emit HeroNFTMint(to, id, data);

        return id;
    }

    /**
     * @dev modify token data
     *
     * @param tokenId token id
     * @param writeableData token data see {HeroNFTDataBase}
     */
    function modNftData(uint256 tokenId, uint256 writeableData) external {
        require(hasRole(DATA_ROLE, _msgSender()), "R1");

        _nftDatas[tokenId].writeableData = writeableData;
    }

    /**
     * @dev get token data
     *
     * @param tokenId token id
     * @param data token data see {HeroNFTDataBase}
     */
    function getNftData(uint256 tokenId) external view returns(HeroNFTDataBase memory data){
        require(_exists(tokenId), "T1");

        data = _nftDatas[tokenId];
    }

}

File 32 of 43 : HeroNFTCodec.sol
// SPDX-License-Identifier: MIT
// Mateline Contracts (HeroNFTCodec.sol)

pragma solidity ^0.8.0;

/**
 * @dev base struct of hero nft data
 */
struct HeroNFTDataBase
{
    uint256 fixedData;
    uint256 writeableData;
}

/**
 * @dev hero fixed nft data version 1
 */
struct HeroNFTFixedData_V1 {
    uint8 job;
    uint8 grade;

    uint16 minerAttr;
    uint16 battleAttr;
}

/**
 * @dev hero writeable nft data version 1
 */
struct HeroNFTWriteableData_V1 {
    uint8 starLevel;
    uint16 level;
    uint64 exp;
}


/**
 * @dev hero nft data codec interface
 */
interface IHeroNFTCodec_V1 {

    /**
    * @dev encode HeroNFTFixedData to HeroNFTDataBase
    * @param data input data of HeroNFTFixedData_V1
    * @return basedata output data of HeroNFTDataBase
    */
    function fromHeroNftFixedData(HeroNFTFixedData_V1 memory data) external pure returns (HeroNFTDataBase memory basedata);

    /**
    * @dev encode HeroNFTFixedData to HeroNFTDataBase
    * @param fdata input data of HeroNFTFixedData_V1
    * @param wdata input data of HeroNFTWriteableData_V1
    * @return basedata output data of HeroNFTDataBase
    */
    function fromHeroNftFixedAnWriteableData(HeroNFTFixedData_V1 memory fdata, HeroNFTWriteableData_V1 memory wdata) external pure returns (HeroNFTDataBase memory basedata);

    /**
    * @dev decode HeroNFTData from HeroNFTDataBase
    * @param data input data of HeroNFTDataBase
    * @return hndata output data of HeroNFTFixedData_V1
    */
    function getHeroNftFixedData(HeroNFTDataBase memory data) external pure returns(HeroNFTFixedData_V1 memory hndata);

    /**
    * @dev decode HeroNFTData from HeroNFTDataBase
    * @param data input data of HeroNFTDataBase
    * @return hndata output data of HeroNFTWriteableData_V1
    */
    function getHeroNftWriteableData(HeroNFTDataBase memory data) external pure returns(HeroNFTWriteableData_V1 memory hndata);

    /**
    * @dev get character id from HeroNFTDataBase
    * @param data input data of HeroNFTDataBase
    * @return characterId character id
    */
    function getCharacterId(HeroNFTDataBase memory data) external pure returns (uint16 characterId);
}

/**
 * @dev hero nft data codec v1 implement
 */
contract HeroNFTCodec_V1 is IHeroNFTCodec_V1 {

    function fromHeroNftFixedData(HeroNFTFixedData_V1 memory data)
        external
        pure
        override
        returns (HeroNFTDataBase memory basedata)
    {
        basedata.fixedData =
            uint256(data.job) |
            (uint256(data.grade) << 8) |
            (uint256(data.minerAttr) << (8 + 8)) |
            (uint256(data.battleAttr) << (8 + 8 + 16));

        basedata.writeableData = 0;
    }

    function fromHeroNftFixedAnWriteableData(HeroNFTFixedData_V1 memory fdata, HeroNFTWriteableData_V1 memory wdata) 
        external 
        pure 
        override 
        returns (HeroNFTDataBase memory basedata)
    {
        basedata.fixedData =
            uint256(fdata.job) |
            (uint256(fdata.grade) << 8) |
            (uint256(fdata.minerAttr) << (8 + 8)) |
            (uint256(fdata.battleAttr) << (8 + 8 + 16));

        basedata.writeableData = 
            (uint256(wdata.starLevel)) |
            (uint256(wdata.level << 8)) |
            (uint256(wdata.exp << (8 + 16)));
    }

    function getHeroNftFixedData(HeroNFTDataBase memory data)
        external
        pure
        override
        returns (HeroNFTFixedData_V1 memory hndata)
    {
        hndata.job = uint8(data.fixedData & 0xff);
        hndata.grade = uint8((data.fixedData >> 8) & 0xff);
        hndata.minerAttr = uint16((data.fixedData >> (8 + 8)) & 0xffff);
        hndata.battleAttr = uint16((data.fixedData >> (8 + 8 + 16)) & 0xffff);
    }

    function getHeroNftWriteableData(HeroNFTDataBase memory data) 
        external 
        pure 
        override 
        returns(HeroNFTWriteableData_V1 memory hndata)
    {
        hndata.starLevel = uint8(data.writeableData & 0xff);
        hndata.level = uint16((data.writeableData >> 8) & 0xffff);
        hndata.exp = uint64((data.writeableData >> 8 + 16) & 0xffffffffffffffff);
    }

    function getCharacterId(HeroNFTDataBase memory data) 
        external 
        pure 
        override
        returns (uint16 characterId) 
    {
        return uint16(data.fixedData & 0xffff); // job << 8 | grade;
    }
}

File 33 of 43 : HeroNFTMysteryBox.sol
// SPDX-License-Identifier: MIT
// DreamIdol Contracts (HeroNFTMysteryBox.sol)

pragma solidity ^0.8.0;

import "./HeroNFTCodec.sol";
import "./HeroNFT.sol";
import "./mysterybox/MBRandomSourceBase.sol";
import "./mysterybox/MysteryBoxBase.sol";

contract HeroNFTMysteryBoxRandSource is 
    MBRandomSourceBase
{
    using RandomPoolLib for RandomPoolLib.RandomPool;

    HeroNFT public _heroNFTContract;
    
    constructor(address heroNftAddr)
    {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
        _setupRole(MINTER_ROLE, _msgSender());

        _heroNFTContract = HeroNFT(heroNftAddr);
    }

    function randomAndMint(uint256 r, uint32 mysteryTp, address to) virtual override external 
        returns(MBContentMinter1155Info[] memory sfts, MBContentMinterNftInfo[] memory nfts)
    {
        require(hasRole(MINTER_ROLE, _msgSender()), "ownership error");

        uint32[] storage poolIDArray = _mbRandomSets[mysteryTp];

        require(poolIDArray.length == 17, "mb type config wrong");

        HeroNFTDataBase memory baseData = _getSingleRandHero(r, poolIDArray);

        // mint 
        uint256 newId = _heroNFTContract.mint(to, baseData);

        nfts = new MBContentMinterNftInfo[](1); // 1 nft
        sfts = new MBContentMinter1155Info[](0); // no sft

        nfts[0] = MBContentMinterNftInfo({
            addr : address(_heroNFTContract),
            tokenIds : new uint256[](1)
        });
        nfts[0].tokenIds[0] = newId;
    }

    function _getSingleRandHero(
        uint256 r,
        uint32[] storage poolIDArray
    ) internal view returns (HeroNFTDataBase memory baseData)
    {
        uint32 index = 0;
        
        NFTRandPool storage pool = _randPools[poolIDArray[0]]; // index 0 : job rand (1-10)
        require(pool.exist, "job pool not exist");
        uint8 job = uint8(pool.randPool.random(r));

        r = _rand.nextRand(++index, r);
        pool = _randPools[poolIDArray[1]]; // index 1 : grade rand (1-5)
        require(pool.exist, "grade pool not exist");
        uint8 grade = uint8(pool.randPool.random(r));

        if(job <= 8){
            pool = _randPools[poolIDArray[1 + grade]]; // index 2-6 : job(1-8) mineAttr rand by grade
        }
        else{
            pool = _randPools[poolIDArray[6 + grade]]; // index 7-11 : job(9-10) mineAttr rand by grade
        }
        r = _rand.nextRand(++index, r);
        require(pool.exist, "mineAttr pool not exist");
        uint16 mineAttr = uint8(pool.randPool.random(r));

        pool = _randPools[poolIDArray[11 + grade]]; // index 12-16 : battleAttr rand by grade
        r = _rand.nextRand(++index, r);
        require(pool.exist, "battleAttr pool not exist");
        uint16 battleAttr = uint8(pool.randPool.random(r));

        HeroNFTFixedData_V1 memory fdata = HeroNFTFixedData_V1({
            job : job,
            grade : grade,
            minerAttr : mineAttr,
            battleAttr : battleAttr
        });

        HeroNFTWriteableData_V1 memory wdata = HeroNFTWriteableData_V1({
            starLevel: 0,
            level : 1,
            exp : 0
        });

        IHeroNFTCodec_V1 codec = IHeroNFTCodec_V1(_heroNFTContract.getCodec());
        baseData = codec.fromHeroNftFixedAnWriteableData(fdata, wdata);
    }

    function batchRandomAndMint(uint256 r, uint32 mysteryTp, address to, uint8 batchCount) virtual override external 
        returns(MBContentMinter1155Info[] memory sfts, MBContentMinterNftInfo[] memory nfts)
    {
        require(hasRole(MINTER_ROLE, _msgSender()), "ownership error");

        uint32[] storage poolIDArray = _mbRandomSets[mysteryTp];

        require(poolIDArray.length == 17, "mb type config wrong");

        nfts = new MBContentMinterNftInfo[](1); // 1 nft
        sfts = new MBContentMinter1155Info[](0); // no sft record

        nfts[0] = MBContentMinterNftInfo({
            addr : address(_heroNFTContract),
            tokenIds : new uint256[](batchCount)
        });

        for(uint8 i=0; i< batchCount; ++i)
        {
            r = _rand.nextRand(i, r);
            HeroNFTDataBase memory baseData = _getSingleRandHero(r, poolIDArray);

            // mint 
            uint256 newId = _heroNFTContract.mint(to, baseData);

            nfts[0].tokenIds[i] = newId;
        }
    }
}

contract HeroNFTMysteryBox is MysteryBoxBase
{    
    function getName() external virtual override returns(string memory)
    {
        return "Hero NFT Mystery Box";
    }
}

File 34 of 43 : IERC2981Royalties.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @title IERC2981Royalties
/// @dev Interface for the ERC2981 - Token Royalty standard
interface IERC2981Royalties {
    /// @notice Called with the sale price to determine how much royalty
    //          is owed and to whom.
    /// @param _tokenId - the NFT asset queried for royalty information
    /// @param _value - the sale price of the NFT asset specified by _tokenId
    /// @return _receiver - address of who should be sent the royalty payment
    /// @return _royaltyAmount - the royalty payment amount for value sale price
    function royaltyInfo(uint256 _tokenId, uint256 _value)
        external
        view
        returns (address _receiver, uint256 _royaltyAmount);
}

File 35 of 43 : MBRandomSourceBase.sol
// SPDX-License-Identifier: MIT
// Mateline Contracts (MBRandomSourceBase.sol)

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/Context.sol";

import "../utility/Random.sol";
import "../utility/RandomPoolLib.sol";

struct MBContentMinter1155Info {
    address addr;
    uint256[] tokenIds;
    uint256[] tokenValues;
}
struct MBContentMinterNftInfo {
    address addr;
    uint256[] tokenIds;
}

abstract contract MBRandomSourceBase is 
    Context, 
    AccessControl
{
    using RandomPoolLib for RandomPoolLib.RandomPool;

    bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
    bytes32 public constant RANDOM_ROLE = keccak256("RANDOM_ROLE");
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

    struct NFTRandPool{
        bool exist;
        RandomPoolLib.RandomPool randPool;
    }

    Random _rand;
    mapping(uint32 => NFTRandPool)    _randPools; // poolID => nft data random pools
    mapping(uint32 => uint32[])       _mbRandomSets; // mystery type => poolID array

    constructor() {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(MANAGER_ROLE, _msgSender());
        _setupRole(RANDOM_ROLE, _msgSender());
    }

    function setRandSource(address randAddr) external {
        require(hasRole(MANAGER_ROLE, _msgSender()));

        _rand = Random(randAddr);
    }

    function getRandSource() external view returns(address) {
        // require(hasRole(MANAGER_ROLE, _msgSender()));
        return address(_rand);
    }
    function _addPool(uint32 poolID, RandomPoolLib.RandomSet[] memory randSetArray) internal {
        NFTRandPool storage rp = _randPools[poolID];

        rp.exist = true;
        for(uint i=0; i<randSetArray.length; ++i){
            rp.randPool.pool.push(randSetArray[i]);
        }

        rp.randPool.initRandomPool();
    }

    function addPool(uint32 poolID, RandomPoolLib.RandomSet[] memory randSetArray) external {
        require(hasRole(MANAGER_ROLE, _msgSender()),"not a manager");
        require(!_randPools[poolID].exist,"rand pool already exist");

        _addPool(poolID, randSetArray);
    }

    function modifyPool(uint32 poolID, RandomPoolLib.RandomSet[] memory randSetArray) external {
        require(hasRole(MANAGER_ROLE, _msgSender()),"not a manager");
        require(_randPools[poolID].exist,"rand pool not exist");

        NFTRandPool storage rp = _randPools[poolID];

        delete rp.randPool.pool;

        for(uint i=0; i<randSetArray.length; ++i){
            rp.randPool.pool.push(randSetArray[i]);
        }

        rp.randPool.initRandomPool();
    }

    function removePool(uint32 poolID) external {
        require(hasRole(MANAGER_ROLE, _msgSender()),"not a manager");
        require(_randPools[poolID].exist, "rand pool not exist");

        delete _randPools[poolID];
    }

    function getPool(uint32 poolID) public view returns(NFTRandPool memory) {
        require(_randPools[poolID].exist, "rand pool not exist");

        return _randPools[poolID];
    }

    function hasPool(uint32 poolID) external view returns(bool){
          return (_randPools[poolID].exist);
    }

    function setRandomSet(uint32 mbTypeID, uint32[] calldata poolIds) external {
        require(hasRole(MANAGER_ROLE, _msgSender()),"not a manager");
        delete _mbRandomSets[mbTypeID];
        uint32[] storage poolIDArray = _mbRandomSets[mbTypeID];
        for(uint i=0; i< poolIds.length; ++i){
            poolIDArray.push(poolIds[i]);
        }
    }
    function unsetRandomSet(uint32 mysteryTp) external {
        require(hasRole(MANAGER_ROLE, _msgSender()),"not a manager");

        delete _mbRandomSets[mysteryTp];
    }
    function getRandomSet(uint32 mysteryTp) external view returns(uint32[] memory poolIds) {
        return _mbRandomSets[mysteryTp];
    }
    
    function randomAndMint(uint256 r, uint32 mysteryTp, address to) virtual external 
        returns(MBContentMinter1155Info[] memory sfts, MBContentMinterNftInfo[] memory nfts);

    function batchRandomAndMint(uint256 r, uint32 mysteryTp, address to, uint8 batchCount) virtual external 
        returns(MBContentMinter1155Info[] memory sfts, MBContentMinterNftInfo[] memory nfts);
}

File 36 of 43 : MysteryBox1155.sol
// SPDX-License-Identifier: MIT
// Mateline Contracts (MysteryBox1155.sol)

pragma solidity ^0.8.0;

import "../core/Extendable1155.sol";

// 1155 id : combine with randomType(uint32) << 32 | mysteryType(uint32)
contract MysteryBox1155 is Extendable1155 {

    constructor(string memory uri) Extendable1155("MetaLine MysteryBox Semi-fungible Token", "MLMB", uri) {
        mint(_msgSender(), 0, 1, new bytes(0)); // mint first token to notify event scan
    }
}

File 37 of 43 : MysteryBoxBase.sol
// SPDX-License-Identifier: MIT
// Mateline Contracts (MysteryBoxBase.sol)

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/utils/Context.sol";

import "../utility/GasFeeCharger.sol";

import "./MysteryBox1155.sol";
import "./MBRandomSourceBase.sol";

abstract contract MysteryBoxBase is 
    Context, 
    Pausable, 
    AccessControl,
    IOracleRandComsumer
{
    using GasFeeCharger for GasFeeCharger.MethodExtraFees;

    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
    bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
    bytes32 public constant RAND_ROLE = keccak256("RAND_ROLE");

    event OracleOpenMysteryBox(uint256 oracleRequestId, uint256 indexed mbTokenId, address indexed owner);
    event OpenMysteryBox(address indexed owner, uint256 indexed mbTokenId, MBContentMinter1155Info[] sfts, MBContentMinterNftInfo[] nfts);

    event BatchOracleOpenMysteryBox(uint256 oracleRequestId, uint256 indexed mbTokenId, address indexed owner, uint8 batchCount);
    event BatchOpenMysteryBox(address indexed owner, uint256 indexed mbTokenId, MBContentMinter1155Info[] sfts, MBContentMinterNftInfo[] nfts);

    struct UserData{
        address owner;
        uint32 randomType;
        uint32 mysteryType;
        uint8 count;
        uint256 tokenId;
    }
    
    MysteryBox1155 public _mb1155;
    
    mapping(uint32=>address) _randomSources; // random type => random source
    mapping(uint256 => UserData) public _oracleUserData; // indexed by oracle request id

    // Method extra fee
    // For smart contract method which need extra transaction by other service, we define extra fee
    // extra fee charge by method call tx with `value` paramter, and send to target service wallet address
    GasFeeCharger.MethodExtraFees _methodExtraFees;

    constructor() {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(PAUSER_ROLE, _msgSender());
        _setupRole(MANAGER_ROLE, _msgSender());
        _setupRole(RAND_ROLE, _msgSender());
    }

    function getName() external virtual returns(string memory);

    function pause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "MysteryBox: must have pauser role to pause");
        _pause();
    }
    
    function unpause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "MysteryBox: must have pauser role to unpause");
        _unpause();
    }

    function setNftAddress(address nftAddr) external {
        require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBox: must have manager role to manage");
        _mb1155 = MysteryBox1155(nftAddr);
    }

    function getNftAddress() external view returns(address) {
        return address(_mb1155);
    }

    function setRandomSource(uint32 randomType, address randomSrc) external {
        require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBox: must have manager role to manage");
        _randomSources[randomType] = randomSrc;
    }

    function getRandomSource(uint32 randomType) external view returns(address){
        return _randomSources[randomType];
    }

    /**
    * @dev set smart contract method invoke by transaction with extra fee
    *
    * Requirements:
    * - caller must have `MANAGER_ROLE`
    *
    * @param methodKey key of which method need extra fee
    * @param value extra fee value
    * @param target target address where extra fee goes to
    */
    function setMethodExtraFee(uint8 methodKey, uint256 value, address target) external {
        require(
            hasRole(MANAGER_ROLE, _msgSender()),
            "MysteryBox: must have manager role"
        );

        _methodExtraFees.setMethodExtraFee(methodKey, value, target);
    }

    /**
    * @dev cancel smart contract method invoke by transaction with extra fee
    *
    * Requirements:
    * - caller must have `MANAGER_ROLE`
    *
    * @param methodKey key of which method need cancel extra fee
    */
    function removeMethodExtraFee(uint8 methodKey) external {
        require(
            hasRole(MANAGER_ROLE, _msgSender()),
            "MysteryBox: must have manager role"
        );

        _methodExtraFees.removeMethodExtraFee(methodKey);
    }

    /**
    * @dev open mystery box, emit {OracleOpenMysteryBox}
    * call `oracleRand` in {Random} of address from `getRandSource` in {MBRandomSource}
    * send a oracle random request and emit {OracleRandRequest}
    *
    * Extrafees:
    * - `oracleOpenMysteryBox` call need charge extra fee for `fulfillRandom` in {Random} call by oracle service
    * - methodKey = 1, extra gas fee = 0.0013 with tx.value needed
    *
    * Requirements:
    * - caller must out side contract, not from contract
    * - caller must owner of `tokenId` in {MysteryBox1155}
    * - contract not paused
    *
    * @param tokenId token id of {MysteryBox1155}, if succeed, token will be burned
    */
    function oracleOpenMysteryBox(uint256 tokenId) external payable whenNotPaused {
        require(tx.origin == _msgSender(), "MysteryBox: only for outside account");
        require(_mb1155.balanceOf(_msgSender(), tokenId) >= 1, "MysteryBox: insufficient mb");

        // check mb 1155 type
        uint32 randomType = (uint32)((tokenId >> 32) & 0xffffffff);
        address randSrcAddr = _randomSources[randomType];
        require(randSrcAddr != address(0), "MysteryBox: not a mystry box");
        
        address rndAddr = MBRandomSourceBase(randSrcAddr).getRandSource();
        require(rndAddr != address(0), "MysteryBox: rand address wrong");

        _methodExtraFees.chargeMethodExtraFee(1); // charge oracleOpenMysteryBox extra fee

        _mb1155.burn(_msgSender(), tokenId, 1);

        uint256 reqid = Random(rndAddr).oracleRand();

        UserData storage userData = _oracleUserData[reqid];
        userData.owner = _msgSender();
        userData.randomType = randomType;
        userData.mysteryType = (uint32)(tokenId & 0xffffffff);
        userData.tokenId = tokenId;
        userData.count = 1;
        
        emit OracleOpenMysteryBox(reqid, tokenId, _msgSender());
    }

    /**
    * @dev batch open mystery box, emit {BatchOracleOpenMysteryBox}
    * call `oracleRand` in {Random} of address from `getRandSource` in {MBRandomSource}
    * send a oracle random request and emit {OracleRandRequest}
    *
    * Extrafees:
    * - `batchOracleOpenMysteryBox` call need charge extra fee for `fulfillRandom` in {Random} call by oracle service
    * - methodKey = 2, extra gas fee = 0.0065 with tx.value needed
    *
    * Requirements:
    * - caller must out side contract, not from contract
    * - caller must owner of `tokenId` in {MysteryBox1155}
    * - contract not paused
    *
    * @param tokenId token id of {MysteryBox1155}, if succeed, token will be burned
    */
    function batchOracleOpenMysteryBox(uint256 tokenId, uint8 batchCount) external payable whenNotPaused {
        require(tx.origin == _msgSender(), "MysteryBox: only for outside account");
        require(batchCount <= 10, "MysteryBox: batch count overflow");
        require(_mb1155.balanceOf(_msgSender(), tokenId) >= batchCount, "MysteryBox: insufficient mb");

        // check mb 1155 type
        uint32 randomType = (uint32)((tokenId >> 32) & 0xffffffff);
        address randSrcAddr = _randomSources[randomType];
        require(randSrcAddr != address(0), "MysteryBox: not a mystry box");
        
        address rndAddr = MBRandomSourceBase(randSrcAddr).getRandSource();
        require(rndAddr != address(0), "MysteryBox: rand address wrong");

        _methodExtraFees.chargeMethodExtraFee(2); // charge batchOracleOpenMysteryBox extra fee

        _mb1155.burn(_msgSender(), tokenId, batchCount);
        
        uint256 reqid = Random(rndAddr).oracleRand();

        UserData storage userData = _oracleUserData[reqid];
        userData.owner = _msgSender();
        userData.randomType = randomType;
        userData.mysteryType = (uint32)(tokenId & 0xffffffff);
        userData.tokenId = tokenId;
        userData.count = batchCount;
        
        emit BatchOracleOpenMysteryBox(reqid, tokenId, _msgSender(), batchCount);
    }

    // call back from random contract which triger by service call {fulfillOracleRand} function
    function oracleRandResponse(uint256 reqid, uint256 randnum) override external {
        require(hasRole(RAND_ROLE, _msgSender()), "MysteryBox: must have rand role");

        UserData storage userData = _oracleUserData[reqid];

        require(userData.owner != address(0), "MysteryBox: nftdata owner not exist");

        address randSrcAddr = _randomSources[userData.randomType];
        require(randSrcAddr != address(0), "MysteryBox: not a mystry box");

        if(userData.count > 1) {

            (MBContentMinter1155Info[] memory sfts, MBContentMinterNftInfo[] memory nfts) 
                = MBRandomSourceBase(randSrcAddr).batchRandomAndMint(randnum, userData.mysteryType, userData.owner, userData.count);

            emit BatchOpenMysteryBox(userData.owner, userData.tokenId, sfts, nfts);
        }
        else {
            (MBContentMinter1155Info[] memory sfts, MBContentMinterNftInfo[] memory nfts) 
                = MBRandomSourceBase(randSrcAddr).randomAndMint(randnum, userData.mysteryType, userData.owner);

            emit OpenMysteryBox(userData.owner, userData.tokenId, sfts, nfts);
        }

        delete _oracleUserData[reqid];
    }
    
}

File 38 of 43 : MysteryBoxShop.sol
// SPDX-License-Identifier: MIT
// Mateline Contracts (MysteryBoxShop.sol)

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";

import "./MysteryBox1155.sol";

contract MysteryBoxShop is 
    Context, 
    Pausable, 
    AccessControl
{
    struct OnSaleMysterBox{
        // config data --------------------------------------------------------
        address mysteryBox1155Addr; // mystery box address
        uint256 mbTokenId; // mystery box token id

        address tokenAddr; // charge token addr, could be 20 or 1155
        uint256 tokenId; // =0 means 20 token, else 1155 token
        uint256 price; // price value

        bool isBurn; // = ture means charge token will be burned, else charge token save in this contract

        uint64 beginTime; // start sale timeStamp in seconds since unix epoch, =0 ignore this condition
        uint64 endTime; // end sale timeStamp in seconds since unix epoch, =0 ignore this condition

        uint64 renewTime; // how long in seconds for each renew
        uint256 renewCount; // how many count put on sale for each renew

        uint32 whitelistId; // = 0 means open sale, else will check if buyer address in white list
        address nftholderCheck; // = address(0) won't check, else will check if buyer hold some other nft

        uint32 perAddrLimit; // = 0 means no limit, else means each user address max buying count
    }

    struct OnSaleMysterBoxRunTime {
        // runtime data -------------------------------------------------------
        uint64 nextRenewTime; // after this timeStamp in seconds since unix epoch, will put at max [renewCount] on sale

        // config & runtime data ----------------------------------------------
        uint256 countLeft; // how many boxies left
    }

    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
    bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
    bytes32 public constant OPERATER_ROLE = keccak256("OPERATER_ROLE");

    event SetOnSaleMysterBox(string indexed pairName, OnSaleMysterBox saleConfig, OnSaleMysterBoxRunTime saleData);
    event UnsetOnSaleMysterBox(string indexed pairName, OnSaleMysterBox saleConfig, OnSaleMysterBoxRunTime saleData);
    event SetOnSaleMBCheckCondition(
        string indexed pairName, 
        uint256 price, 
        uint32 whitelistId, 
        address nftholderCheck, 
        uint32 perAddrLimit);
    event SetOnSaleMBCountleft(string indexed pairName, uint countLeft);
    event PerAddrBuyCountChange(string indexed pairName, address indexed userAddr, uint32 count);
    event BuyMysteryBox(address indexed userAddr, string indexed pairName, OnSaleMysterBox saleConfig, OnSaleMysterBoxRunTime saleData);
    event BatchBuyMysteryBox(address indexed userAddr, string indexed pairName, OnSaleMysterBox saleConfig, OnSaleMysterBoxRunTime saleData, uint256 count);

    mapping(string=>OnSaleMysterBox) public _onSaleMysterBoxes;
    mapping(string=>OnSaleMysterBoxRunTime) public _onSaleMysterBoxDatas;
    mapping(string=>mapping(address=>uint32)) public _perAddrBuyCount;
    address public _receiveIncomAddress;

    mapping(uint32=>mapping(address=>bool)) public _whitelists;

    constructor() {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(PAUSER_ROLE, _msgSender());
        _setupRole(MANAGER_ROLE, _msgSender());
        _setupRole(OPERATER_ROLE, _msgSender());
    }

    function pause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "P1");
        _pause();
    }
    function unpause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "P2");
        _unpause();
    }

    function addWitheList(uint32 wlId, address[] memory whitelist) external {
        require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage");

        mapping(address=>bool) storage wl = _whitelists[wlId];

        for(uint i=0; i< whitelist.length; ++i){
            wl[whitelist[i]] = true;
        }
    }

    function removeWhiteList(uint32 wlId, address[] memory whitelist) external {
        require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage");

        mapping(address=>bool) storage wl = _whitelists[wlId];

        for(uint i=0; i< whitelist.length; ++i){
            delete wl[whitelist[i]];
        }
    }

    function setOnSaleMysteryBox(string calldata pairName, OnSaleMysterBox memory saleConfig, OnSaleMysterBoxRunTime memory saleData) external whenNotPaused {
        require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage");

        if(saleConfig.renewTime > 0)
        {
            saleData.nextRenewTime = (uint64)(block.timestamp + saleConfig.renewTime);
        }

        _onSaleMysterBoxes[pairName] = saleConfig;
        _onSaleMysterBoxDatas[pairName] = saleData;

        emit SetOnSaleMysterBox(pairName, saleConfig, saleData);
    }

    function unsetOnSaleMysteryBox(string calldata pairName) external whenNotPaused {
        require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage");

        OnSaleMysterBox storage onSalePair = _onSaleMysterBoxes[pairName];
        OnSaleMysterBoxRunTime storage onSalePairData = _onSaleMysterBoxDatas[pairName];

        emit UnsetOnSaleMysterBox(pairName, onSalePair, onSalePairData);

        delete _onSaleMysterBoxes[pairName];
        delete _onSaleMysterBoxDatas[pairName];
    }

    function setOnSaleMBCheckCondition(
        string calldata pairName, 
        uint256 price, 
        uint32 whitelistId, 
        address nftholderCheck, 
        uint32 perAddrLimit
    ) external {
        require(hasRole(OPERATER_ROLE, _msgSender()), "MysteryBoxShop: must have operater role");

        OnSaleMysterBox storage onSalePair = _onSaleMysterBoxes[pairName];

        onSalePair.price = price;
        onSalePair.whitelistId = whitelistId;
        onSalePair.nftholderCheck = nftholderCheck;
        onSalePair.perAddrLimit = perAddrLimit;

        emit SetOnSaleMBCheckCondition(pairName, price, whitelistId, nftholderCheck, perAddrLimit);
    }

    function setOnSaleMBCountleft(string calldata pairName, uint countLeft) external {
        require(hasRole(OPERATER_ROLE, _msgSender()), "MysteryBoxShop: must have operater role");

        OnSaleMysterBoxRunTime storage onSalePairData = _onSaleMysterBoxDatas[pairName];

        onSalePairData.countLeft = countLeft;

        emit SetOnSaleMBCountleft(pairName, countLeft);
    }

    function setReceiveIncomeAddress(address incomAddr) external {
        require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage");

        _receiveIncomAddress = incomAddr;
    }

    function _checkSellCondition(OnSaleMysterBox storage onSalePair, OnSaleMysterBoxRunTime storage onSalePairData) internal {
        if(onSalePair.beginTime > 0)
        {
            require(block.timestamp >= onSalePair.beginTime, "MysteryBoxShop: sale not begin");
        }
        if(onSalePair.endTime > 0)
        {
            require(block.timestamp <= onSalePair.endTime, "MysteryBoxShop: sale finished");
        }
        if(onSalePair.whitelistId > 0)
        {
            require(_whitelists[onSalePair.whitelistId][_msgSender()], "MysteryBoxShop: not in whitelist");
        }
        if(onSalePair.nftholderCheck != address(0))
        {
            require(IERC721(onSalePair.nftholderCheck).balanceOf(_msgSender()) > 0, "MysteryBoxShop: no authority");
        }

        if(onSalePair.renewTime > 0)
        {
            if(block.timestamp > onSalePairData.nextRenewTime)
            {
                onSalePairData.nextRenewTime = (uint64)(onSalePairData.nextRenewTime + onSalePair.renewTime * (1 + ((block.timestamp - onSalePairData.nextRenewTime) / onSalePair.renewTime)));
                onSalePairData.countLeft = onSalePair.renewCount;
            }
        }
    }

    function _chargeByDesiredCount(
        string calldata pairName, OnSaleMysterBox storage onSalePair, OnSaleMysterBoxRunTime storage onSalePairData, uint256 count) 
        internal returns (uint256 realCount)
    {

        realCount = count;
        if(realCount > onSalePairData.countLeft)
        {
            realCount = onSalePairData.countLeft;
        }

        if(onSalePair.perAddrLimit > 0)
        {
            uint32 buyCount = _perAddrBuyCount[pairName][_msgSender()];
            uint32 buyCountLeft = (onSalePair.perAddrLimit > buyCount)? (onSalePair.perAddrLimit - buyCount) : 0;
            if(buyCountLeft < realCount){
                realCount = buyCountLeft;
            }

            if(realCount > 0){
                buyCount += uint32(realCount);
                _perAddrBuyCount[pairName][_msgSender()] = buyCount;

                emit PerAddrBuyCountChange(pairName, _msgSender(), buyCount);
            }
        }

        require(realCount > 0, "MysteryBoxShop: insufficient mystery box");

        onSalePairData.countLeft -= realCount;

        if(onSalePair.price > 0){
            uint256 realPrice = onSalePair.price * realCount;

            if(onSalePair.tokenAddr == address(0)){
                require(msg.value >= realPrice, "MysteryBoxShop: insufficient value");

                // receive eth
                (bool sent, ) = _receiveIncomAddress.call{value:msg.value}("");
                require(sent, "MysteryBoxShop: transfer income error");
            }
            else if(onSalePair.tokenId > 0)
            {
                // 1155
                require(IERC1155(onSalePair.tokenAddr).balanceOf( _msgSender(), onSalePair.tokenId) >= realPrice , "MysteryBoxShop: erc1155 insufficient token");

                if(onSalePair.isBurn) {
                    // burn
                    ERC1155Burnable(onSalePair.tokenAddr).burn(_msgSender(), onSalePair.tokenId, realPrice);
                }
                else {
                    // charge
                    IERC1155(onSalePair.tokenAddr).safeTransferFrom(_msgSender(), address(this), onSalePair.tokenId, realPrice, "buy mb");
                }
            }
            else{
                // 20
                require(IERC20(onSalePair.tokenAddr).balanceOf(_msgSender()) >= realPrice , "MysteryBoxShop: erc20 insufficient token");

                if(onSalePair.isBurn) {
                    // burn
                    ERC20Burnable(onSalePair.tokenAddr).burnFrom(_msgSender(), realPrice);
                }
                else {
                    // charge
                    TransferHelper.safeTransferFrom(onSalePair.tokenAddr, _msgSender(), address(this), realPrice);
                }
            }
        }

    }

    function buyMysteryBox(string calldata pairName) external payable whenNotPaused {
        OnSaleMysterBox storage onSalePair = _onSaleMysterBoxes[pairName];
        OnSaleMysterBoxRunTime storage onSalePairData = _onSaleMysterBoxDatas[pairName];
        require(address(onSalePair.mysteryBox1155Addr) != address(0), "MysteryBoxShop: mystery box not on sale");

        _checkSellCondition(onSalePair, onSalePairData);

        _chargeByDesiredCount(pairName, onSalePair, onSalePairData, 1);

        MysteryBox1155(onSalePair.mysteryBox1155Addr).mint(_msgSender(), onSalePair.mbTokenId, 1, "buy mb");

        emit BuyMysteryBox(_msgSender(), pairName, onSalePair, onSalePairData);
    }

    function batchBuyMysterBox(string calldata pairName, uint32 count) external payable whenNotPaused {

        OnSaleMysterBox storage onSalePair = _onSaleMysterBoxes[pairName];
        OnSaleMysterBoxRunTime storage onSalePairData = _onSaleMysterBoxDatas[pairName];
        require(address(onSalePair.mysteryBox1155Addr) != address(0), "MysteryBoxShop: mystery box not on sale");

        _checkSellCondition(onSalePair, onSalePairData);

        uint256 realCount = _chargeByDesiredCount(pairName, onSalePair, onSalePairData, count);

        MysteryBox1155(onSalePair.mysteryBox1155Addr).mint(_msgSender(), onSalePair.mbTokenId, realCount, "buy mb");

        emit BatchBuyMysteryBox(_msgSender(), pairName, onSalePair, onSalePairData, realCount);
    }

    function fetchIncome(address tokenAddr, uint256 value) external {
        require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage");
        IERC20 token = IERC20(tokenAddr);

        if(value <= 0){
            value = token.balanceOf(address(this));
        }

        require(value > 0, "MysteryBoxShop: zero value");

        TransferHelper.safeTransfer(tokenAddr, _receiveIncomAddress, value);
    }

    function fetchIncome1155(address tokenAddr, uint256 tokenId, uint256 value) external {
        require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage");
        IERC1155 token = IERC1155(tokenAddr);

        if(value <= 0){
            value = token.balanceOf(address(this), tokenId);
        }

        require(value > 0, "MysteryBoxShop: zero value");

        token.safeTransferFrom(address(this), _receiveIncomAddress, tokenId, value, "fetch income");
    }
}

File 39 of 43 : GasFeeCharger.sol
// SPDX-License-Identifier: MIT
// Mateline Contracts (GasFeeCharger.sol)

pragma solidity ^0.8.0;

library GasFeeCharger {

    struct MethodWithExrtraFee {
        address target;
        uint256 value;
    }

    struct MethodExtraFees {
        mapping(uint8=>MethodWithExrtraFee) extraFees;
    }

    function setMethodExtraFee(MethodExtraFees storage extraFees, uint8 methodKey, uint256 value, address target) internal {
        MethodWithExrtraFee storage fee = extraFees.extraFees[methodKey];
        fee.value = value;
        fee.target = target;
    }

    function removeMethodExtraFee(MethodExtraFees storage extraFees, uint8 methodKey) internal {
        delete extraFees.extraFees[methodKey];
    }

    function chargeMethodExtraFee(MethodExtraFees storage extraFees, uint8 methodKey)  internal returns(bool) {
        MethodWithExrtraFee storage fee = extraFees.extraFees[methodKey];
        if(fee.target == address(0)){
            return true; // no need charge fee
        }

        require(msg.value >= fee.value, "msg fee not enough");

        // Call returns a boolean value indicating success or failure.
        // This is the current recommended method to use.
        (bool sent, ) = fee.target.call{value: msg.value}("");
        require(sent, "Trans fee err");

        return sent;
    }
    
}

File 40 of 43 : Random.sol
// SPDX-License-Identifier: MIT
// Mateline Contracts (Random.sol)

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/Context.sol";

interface IOracleRandComsumer {
    function oracleRandResponse(uint256 reqid, uint256 randnum) external;
}

/**
 * @dev A random source contract provids `seedRand`, `sealedRand` and `oracleRand` methods
 */
contract Random is Context, AccessControl {
    bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
    bytes32 public constant ORACLE_ROLE = keccak256("ORACLE_ROLE");

    // an auto increased number by each _seedRand call
    uint32 _nonce;

    // an auto increased number by each setSealed call
    uint32 _sealedNonce;

    // an random seed set by manager
    uint256 _randomSeed;

    // an auto increased number by each oracleRand call
    uint256 _orcacleReqIDSeed;

    // sealed random seed data structure
    struct RandomSeed {
        uint32 sealedNonce;
        uint256 sealedNumber;
        uint256 seed;
        uint256 h1;
    }

    mapping(uint256 => RandomSeed) _sealedRandom; // _encodeSealedKey(addr) => sealed random seed data structure
    mapping(uint256 => address) _oracleRandRequests; // oracle rand request id => caller address

    /**
    * @dev emit when `oracleRand` called

    * @param reqid oracle rand request id
    * @param requestAddress caller address
    */
    event OracleRandRequest(uint256 reqid, address indexed requestAddress);

    /**
    * @dev emit when `fulfillOracleRand` called

    * @param reqid oracle rand request id
    * @param randnum random number feed to request caller
    * @param requestAddress `oracleRand` requrest caller address
    */
    event OracleRandResponse(uint256 reqid, uint256 randnum, address indexed requestAddress);

    constructor() {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(MANAGER_ROLE, _msgSender());
        _setupRole(ORACLE_ROLE, _msgSender());
    }

    /**
    * @dev check address is sealed, usually call by contract to check user seal status
    *
    * @param addr user addr
    * @return ture if user is sealed
    */
    function isSealed(address addr) external view returns (bool) {
        return _isSealedDirect(_encodeSealedKey(addr));
    }

    /**
    * @dev set random seed
    *
    * Requirements:
    * - caller must have `MANAGER_ROLE`
    *
    * @param s random seed
    */
    function setRandomSeed(uint256 s) external {
        require(hasRole(MANAGER_ROLE, _msgSender()),"not manager");

        _randomSeed = s;
    }

    /**
    * @dev set user sealed, usually call by contract to seal a user
    * this function will `_encodeSealedKey` by tx.orgin and `_msgSender`
    * if success call this function, then user can call `sealedRand`
    */
    function setSealed() external {

        require(block.number >= 100,"block is too small");
        
        uint256 sealedKey = _encodeSealedKey(tx.origin);
       
        require(!_isSealedDirect(sealedKey),"should not sealed");

        _sealedNonce++;

        RandomSeed storage rs = _sealedRandom[sealedKey];

        rs.sealedNumber = block.number + 1;
        rs.sealedNonce = _sealedNonce;
        rs.seed = _randomSeed;

        uint256 seed = uint256(
            keccak256(
                abi.encodePacked(block.number, block.timestamp, _sealedNonce)
            )
        );
        uint32 n1 = uint32(seed % 100);
        rs.h1 = uint256(blockhash(block.number - n1));
    }

    /**
    * @dev seal rand and get a random number
    *
    * Requirements:
    * - caller must call `setSealed` first
    *
    * @return ret random number
    */
    function sealedRand() external returns (uint256 ret) {
        return _sealedRand();
    }

    /**
    * @dev input a seed and get a random number depends on seed
    *
    * @param inputSeed random seed
    * @return ret random number depends on seed
    */
    function seedRand(uint256 inputSeed) external returns (uint256 ret) {
        return _seedRand(inputSeed);
    }

    /**
    * @dev start an oracle rand, emit {OracleRandRequest}, call by contract
    * oracle service wait on {OracleRandRequest} event and call `fulfillOracleRand`
    *
    * Requirements:
    * - caller must implements `oracleRandResponse` of {IOracleRandComsumer}
    *
    * @return reqid is request id of oracle rand request
    */
    function oracleRand() external returns (uint256) {
        _orcacleReqIDSeed = _orcacleReqIDSeed + 1;
        uint256 reqid = _orcacleReqIDSeed;
        //console.log("[sol]reqid=",reqid);
        _oracleRandRequests[reqid] = _msgSender();

        emit OracleRandRequest(reqid, _msgSender());

        return reqid;
    }

    /**
    * @dev fulfill an oracle rand, emit {OracleRandResponse}
    * call by oracle when it get {OracleRandRequest}, feed with an random number
    *
    * Requirements:
    * - caller must have `ORACLE_ROLE`
    *
    * @param reqid request id of oracle rand request
    * @param randnum random number feed by oracle
    * @return rand number
    */
    function fulfillOracleRand(uint256 reqid, uint256 randnum) external returns (uint256 rand) {
        require(hasRole(ORACLE_ROLE, _msgSender()),"need oracle role");
        require(_oracleRandRequests[reqid] != address(0),"reqid not exist");

        rand = _seedRand(randnum);
        IOracleRandComsumer comsumer = IOracleRandComsumer(_oracleRandRequests[reqid]);
        comsumer.oracleRandResponse(reqid, rand);

        delete _oracleRandRequests[reqid];

        emit OracleRandResponse(reqid, rand, address(comsumer));

        return rand;
    }

    /**
    * @dev input index and random number, return with new random number depends on input
    * use chain blockhash as random array, we can fetch many random number with a seed in one transaction
    *
    * @param index a number increased by caller, make sure that we don't get same outcome
    * @param randomNum random number as seed
    * @return ret is new rand number
    */
    function nextRand(uint32 index, uint256 randomNum) external view returns(uint256 ret){
        uint256 n1 = (randomNum + index) % block.number;
        uint256 h1 = uint256(blockhash(n1));

        return uint256(
            keccak256(
                abi.encodePacked(index, n1, h1)
            )
        );
    }

    function _seedRand(uint256 inputSeed) internal returns (uint256 ret) {
        require(block.number >= 1000,"block.number need >=1000");

        uint256 seed = uint256(
            keccak256(abi.encodePacked(block.number, block.timestamp, inputSeed))
        );

        uint32 n1 = uint32(seed % 100);
            
        uint32 n2 = uint32(seed % 1000);

        uint256 h1 = uint256(blockhash(block.number - n1));
  
        uint256 h2 = uint256(blockhash(block.number - n2));

        _nonce++;
        uint256 v = uint256(
            keccak256(abi.encodePacked(_randomSeed, h1, h2, _nonce))
        );

        return v;
    }

    // addr usually be tx.origin
    function _encodeSealedKey(address addr) internal view returns (uint256 key) {
        return uint256(
            keccak256(
                abi.encodePacked(addr, _msgSender())
            )
        );
    }

    function _sealedRand() internal returns (uint256 ret) {
    
        uint256 sealedKey = _encodeSealedKey(tx.origin);
        bool v = _isSealedDirect(sealedKey);
        require(v == true,"should sealed");

        RandomSeed storage rs = _sealedRandom[sealedKey];

        uint256 h2 = uint256(blockhash(rs.sealedNumber));
        ret = uint256(
            keccak256(
                abi.encodePacked(
                    rs.seed,
                    rs.h1,
                    h2,
                    block.difficulty,
                    rs.sealedNonce
                )
            )
        );

        delete _sealedRandom[sealedKey];

        return ret;
    }

    function _isSealedDirect(uint256 sealedKey) internal view returns (bool){
        return _sealedRandom[sealedKey].sealedNumber != 0;
    }

}

File 41 of 43 : RandomPoolLib.sol
// SPDX-License-Identifier: MIT
// Mateline Contracts (RandomPoolLib.sol)

pragma solidity ^0.8.0;

import "./Random.sol";

/**
 * @dev Random pool that allow user random in different rate section
 */
library RandomPoolLib {

    // random set with rate and range
    struct RandomSet {
        uint32 rate;
        uint rangMin;
        uint rangMax;
    }

    // random pool with an array of random set
    struct RandomPool {
        uint32 totalRate;
        RandomSet[] pool;
    }

    // initialize a random pool
    function initRandomPool(RandomPool storage pool) external {
        for(uint i=0; i< pool.pool.length; ++i){
            pool.totalRate += pool.pool[i].rate;
        }

        require(pool.totalRate > 0);
    }

    // use and randomNum to fetch a random result in the random set array
    function random(RandomPool storage pool, uint256 r) external view returns(uint ret) {
        require(pool.totalRate > 0);

        uint32 rate = uint32((r>>224) % pool.totalRate);
        uint32 curRate = 0;
        for(uint i=0; i<pool.pool.length; ++i){
            curRate += pool.pool[i].rate;
            if(rate > curRate){
                continue;
            }

            return randBetween(pool.pool[i].rangMin, pool.pool[i].rangMax, r);
        }
    }

    // input r and min,max, return a number between [min, max] with r
    function randBetween(
        uint256 min,
        uint256 max,
        uint256 r
    ) public pure returns (uint256 ret) {
        if(min >= max) {
            return min;
        }

        uint256 rang = (max+1) - min;
        return uint256(min + (r % rang));
    }
}

File 42 of 43 : ResetableCounters.sol
// SPDX-License-Identifier: MIT
// Override from OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title ResetableCounters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library ResetableCounters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter, uint256 v) internal {
        counter._value = v;
    }
}

File 43 of 43 : TransferHelper.sol
// contracts/TransferHelper.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library TransferHelper {
    function safeApprove(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
    }

    function safeTransfer(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
    }

    function safeTransferFrom(address token, address from, address to, uint value) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
    }

    function safeTransferETH(address to, uint value) internal {
        (bool success,) = to.call{value:value}(new bytes(0));
        require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"uri","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extendData","type":"bytes"}],"name":"Extendable1155Modify","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DATA_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_royalties","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"burnBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"erc20","type":"address"}],"name":"fetchIncome","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fetchIncomeEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getTokenExtendNftData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"extendData","type":"bytes"}],"name":"modifyExtendData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"royalties","type":"uint256"}],"name":"setRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newuri","type":"string"}],"name":"updateURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b5060405162003f0138038062003f01833981016040819052620000349162000976565b60405180606001604052806027815260200162003eda6027913960408051808201909152600481526326a626a160e11b60208201528282828280620000798162000155565b506004805460ff191690558251620000999060069060208601906200089d565b508151620000af9060079060208501906200089d565b506101f4600855620000c360003362000172565b620000ef7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a63362000172565b6200011b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a3362000172565b5050505050506200014e620001356200016e60201b60201c565b604080516000808252602082019092526001906200017e565b5062000c64565b80516200016a9060039060208401906200089d565b5050565b3390565b6200016a82826200023c565b3360009081527f0781d7cac9c378efa22a7481e4d4d29704a680ddf504b3bc50b517700ee11e6c602052604090205460ff16620002285760405162461bcd60e51b815260206004820152603860248201527f455243313135355072657365744d696e7465725061757365723a206d7573742060448201527f68617665206d696e74657220726f6c6520746f206d696e74000000000000000060648201526084015b60405180910390fd5b6200023684848484620002dc565b50505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166200016a576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620002983390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6001600160a01b0384166200033e5760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b60648201526084016200021f565b3360006200034c856200040d565b905060006200035b856200040d565b90506200036e836000898585896200045b565b60008681526001602090815260408083206001600160a01b038b16845290915281208054879290620003a290849062000aa2565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a462000404836000898989896200047e565b50505050505050565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106200044a576200044a62000b8c565b602090810291909101015292915050565b620004768686868686866200065b60201b620010da1760201c565b505050505050565b6200049d846001600160a01b03166200080960201b6200126b1760201c565b15620004765760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190620004d9908990899088908890889060040162000a46565b602060405180830381600087803b158015620004f457600080fd5b505af192505050801562000527575060408051601f3d908101601f19168201909252620005249181019062000943565b60015b620005e8576200053662000bb8565b806308c379a014156200057757506200054e62000bd5565b806200055b575062000579565b8060405162461bcd60e51b81526004016200021f919062000a8d565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560448201527f526563656976657220696d706c656d656e74657200000000000000000000000060648201526084016200021f565b6001600160e01b0319811663f23a6e6160e01b14620004045760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b60648201526084016200021f565b620006768686868686866200081860201b6200127a1760201c565b6001600160a01b0385166200070a5760005b83518110156200070857828181518110620006a757620006a762000b8c565b602002602001015160056000868481518110620006c857620006c862000b8c565b602002602001015181526020019081526020016000206000828254620006ef919062000aa2565b909155506200070090508162000b58565b905062000688565b505b6001600160a01b038416620004765760005b8351811015620004045760008482815181106200073d576200073d62000b8c565b6020026020010151905060008483815181106200075e576200075e62000b8c565b6020026020010151905060006005600084815260200190815260200160002054905081811015620007e35760405162461bcd60e51b815260206004820152602860248201527f455243313135353a206275726e20616d6f756e74206578636565647320746f74604482015267616c537570706c7960c01b60648201526084016200021f565b60009283526005602052604090922091039055620008018162000b58565b90506200071c565b6001600160a01b03163b151590565b620008338686868686866200047660201b620012631760201c565b60045460ff1615620004765760405162461bcd60e51b815260206004820152602c60248201527f455243313135355061757361626c653a20746f6b656e207472616e736665722060448201526b1dda1a5b19481c185d5cd95960a21b60648201526084016200021f565b828054620008ab9062000aec565b90600052602060002090601f016020900481019282620008cf57600085556200091a565b82601f10620008ea57805160ff19168380011785556200091a565b828001600101855582156200091a579182015b828111156200091a578251825591602001919060010190620008fd565b50620009289291506200092c565b5090565b5b808211156200092857600081556001016200092d565b6000602082840312156200095657600080fd5b81516001600160e01b0319811681146200096f57600080fd5b9392505050565b6000602082840312156200098957600080fd5b81516001600160401b0380821115620009a157600080fd5b818401915084601f830112620009b657600080fd5b815181811115620009cb57620009cb62000ba2565b6040519150620009e6601f8201601f19166020018362000b29565b808252856020828501011115620009fc57600080fd5b62000a0f81602084016020860162000abd565b50949350505050565b6000815180845262000a3281602086016020860162000abd565b601f01601f19169290920160200192915050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009062000a829083018462000a18565b979650505050505050565b6020815260006200096f602083018462000a18565b6000821982111562000ab85762000ab862000b76565b500190565b60005b8381101562000ada57818101518382015260200162000ac0565b83811115620002365750506000910152565b600181811c9082168062000b0157607f821691505b6020821081141562000b2357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f191681016001600160401b038111828210171562000b515762000b5162000ba2565b6040525050565b600060001982141562000b6f5762000b6f62000b76565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d111562000bd25760046000803e5060005160e01c5b90565b600060443d101562000be45790565b6040516003193d81016004833e81513d6001600160401b03808311602484018310171562000c1457505050505090565b828501915081518181111562000c2d5750505050505090565b843d870101602082850101111562000c485750505050505090565b62000c596020828601018762000b29565b509095945050505050565b6132668062000c746000396000f3fe608060405234801561001057600080fd5b506004361061021b5760003560e01c806366faf1f511610125578063a22cb465116100ad578063d547741f1161007c578063d547741f146104b9578063e63ab1e9146104cc578063e985e9c5146104f3578063f242432a1461052f578063f5298aca1461054257600080fd5b8063a22cb4651461045e578063bd85b03914610471578063c30f4a5a14610491578063d5391393146104a457600080fd5b806389f83e4e116100f457806389f83e4e1461042057806391d148541461043357806395d89b411461044657806399e751231461044e578063a217fddf1461045657600080fd5b806366faf1f5146103cb5780636b20c454146103f2578063731133e9146104055780638456cb591461041857600080fd5b80632eb2c2d6116101a85780633f4ba83a116101775780633f4ba83a146103635780634e1273f41461036b5780634f558e791461038b5780635c975abb146103ad5780635e03d937146103b857600080fd5b80632eb2c2d6146103175780632f2ff15d1461032a57806336568abe1461033d57806338429fde1461035057600080fd5b80630e89341c116101ef5780630e89341c146102875780631f7fdffa1461029a578063248a9ca3146102af5780632a55205a146102d25780632b80183f1461030457600080fd5b8062fdd58e1461022057806301ffc9a71461024657806306fdde03146102695780630977fd731461027e575b600080fd5b61023361022e366004612800565b610555565b6040519081526020015b60405180910390f35b6102596102543660046129da565b6105ee565b604051901515815260200161023d565b610271610619565b60405161023d9190612cd8565b61023360085481565b61027161029536600461299e565b6106ab565b6102ad6102a8366004612731565b61073f565b005b6102336102bd36600461299e565b60009081526020819052604090206001015490565b6102e56102e0366004612ada565b610785565b604080516001600160a01b03909316835260208301919091520161023d565b6102ad61031236600461299e565b6107ae565b6102ad6103253660046125b1565b6107e7565b6102ad6103383660046129b7565b61087e565b6102ad61034b3660046129b7565b6108a8565b6102ad61035e366004612a9e565b610926565b6102ad610a63565b61037e6103793660046128b1565b610af7565b60405161023d9190612c97565b61025961039936600461299e565b600090815260056020526040902054151590565b60045460ff16610259565b6102716103c636600461299e565b610c20565b6102337fa5b103c755210dd1215ce1308341380ccede082cd9202427c960290e230cba7881565b6102ad6104003660046126be565b610c7c565b6102ad61041336600461285d565b610cbf565b6102ad610cff565b6102ad61042e36600461256c565b610d91565b6102596104413660046129b7565b610e52565b610271610e7b565b6102ad610e8a565b610233600081565b6102ad61046c3660046127c9565b610f6b565b61023361047f36600461299e565b60009081526005602052604090205490565b6102ad61049f366004612a14565b610f76565b61023360008051602061321183398151915281565b6102ad6104c73660046129b7565b61102d565b6102337f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b610259610501366004612587565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205460ff1690565b6102ad61053d36600461265a565b611052565b6102ad61055036600461282a565b611097565b60006001600160a01b0383166105c65760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b60648201526084015b60405180910390fd5b5060009081526001602090815260408083206001600160a01b03949094168352929052205490565b60006001600160e01b0319821663152a902d60e11b14806106135750610613826112e2565b92915050565b60606006805461062890613063565b80601f016020809104026020016040519081016040528092919081815260200182805461065490613063565b80156106a15780601f10610676576101008083540402835291602001916106a1565b820191906000526020600020905b81548152906001019060200180831161068457829003601f168201915b5050505050905090565b6060600380546106ba90613063565b80601f01602080910402602001604051908101604052809291908181526020018280546106e690613063565b80156107335780601f1061070857610100808354040283529160200191610733565b820191906000526020600020905b81548152906001019060200180831161071657829003601f168201915b50505050509050919050565b61075760008051602061321183398151915233610e52565b6107735760405162461bcd60e51b81526004016105bd90612e86565b61077f84848484611322565b50505050565b60085430906000906127109061079b9085613001565b6107a59190612fdf565b90509250929050565b6107c660008051602061321183398151915233610e52565b6107e25760405162461bcd60e51b81526004016105bd90612d33565b600855565b6001600160a01b03851633148061080357506108038533610501565b61086a5760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b60648201526084016105bd565b610877858585858561147d565b5050505050565b60008281526020819052604090206001015461089981611622565b6108a3838361162c565b505050565b6001600160a01b03811633146109185760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084016105bd565b61092282826116b0565b5050565b60045460ff161561096c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016105bd565b6109967fa5b103c755210dd1215ce1308341380ccede082cd9202427c960290e230cba7833610e52565b6109c75760405162461bcd60e51b8152602060048201526002602482015261291b60f11b60448201526064016105bd565b600082815260056020526040902054610a075760405162461bcd60e51b8152602060048201526002602482015261114d60f21b60448201526064016105bd565b60008281526009602090815260409091208251610a26928401906123cd565b50817f01eb9f446224820ea672f6cae3910a8b4056363f1aa0ac27623d72eeb3d99d0b82604051610a579190612cd8565b60405180910390a25050565b610a8d7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33610e52565b610aed5760405162461bcd60e51b815260206004820152603b60248201526000805160206131f183398151915260448201527f686176652070617573657220726f6c6520746f20756e7061757365000000000060648201526084016105bd565b610af5611715565b565b60608151835114610b5c5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b60648201526084016105bd565b600083516001600160401b03811115610b7757610b77613111565b604051908082528060200260200182016040528015610ba0578160200160208202803683370190505b50905060005b8451811015610c1857610beb858281518110610bc457610bc46130fb565b6020026020010151858381518110610bde57610bde6130fb565b6020026020010151610555565b828281518110610bfd57610bfd6130fb565b6020908102919091010152610c11816130ca565b9050610ba6565b509392505050565b600081815260056020526040902054606090610c635760405162461bcd60e51b8152602060048201526002602482015261229b60f11b60448201526064016105bd565b600082815260096020526040902080546106ba90613063565b6001600160a01b038316331480610c985750610c988333610501565b610cb45760405162461bcd60e51b81526004016105bd90612db5565b6108a38383836117a8565b610cd760008051602061321183398151915233610e52565b610cf35760405162461bcd60e51b81526004016105bd90612e86565b61077f84848484611947565b610d297f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33610e52565b610d895760405162461bcd60e51b815260206004820152603960248201526000805160206131f183398151915260448201527f686176652070617573657220726f6c6520746f2070617573650000000000000060648201526084016105bd565b610af5611a29565b610da960008051602061321183398151915233610e52565b610dc55760405162461bcd60e51b81526004016105bd90612d33565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a082319060240160206040518083038186803b158015610e0757600080fd5b505afa158015610e1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3f9190612a85565b9050801561092257610922823383611aa4565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606007805461062890613063565b610ea260008051602061321183398151915233610e52565b610ebe5760405162461bcd60e51b81526004016105bd90612d33565b604051600090339047908381818185875af1925050503d8060008114610f00576040519150601f19603f3d011682016040523d82523d6000602084013e610f05565b606091505b5050905080610f685760405162461bcd60e51b815260206004820152602960248201527f455243313135355072657365744d696e7465725061757365723a207472616e736044820152683332b91032b93937b960b91b60648201526084016105bd565b50565b610922338383611bb8565b610f8e60008051602061321183398151915233610e52565b610fee5760405162461bcd60e51b815260206004820152603a60248201526000805160206131f183398151915260448201527f68617665206d696e74657220726f6c6520746f2075706461746500000000000060648201526084016105bd565b61092282828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c9992505050565b60008281526020819052604090206001015461104881611622565b6108a383836116b0565b6001600160a01b03851633148061106e575061106e8533610501565b61108a5760405162461bcd60e51b81526004016105bd90612db5565b6108778585858585611cac565b6001600160a01b0383163314806110b357506110b38333610501565b6110cf5760405162461bcd60e51b81526004016105bd90612db5565b6108a3838383611de8565b6110e886868686868661127a565b6001600160a01b03851661116f5760005b835181101561116d57828181518110611114576111146130fb565b602002602001015160056000868481518110611132576111326130fb565b6020026020010151815260200190815260200160002060008282546111579190612fc7565b909155506111669050816130ca565b90506110f9565b505b6001600160a01b0384166112635760005b835181101561126157600084828151811061119d5761119d6130fb565b6020026020010151905060008483815181106111bb576111bb6130fb565b602002602001015190506000600560008481526020019081526020016000205490508181101561123e5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a206275726e20616d6f756e74206578636565647320746f74604482015267616c537570706c7960c01b60648201526084016105bd565b6000928352600560205260409092209103905561125a816130ca565b9050611180565b505b505050505050565b6001600160a01b03163b151590565b60045460ff16156112635760405162461bcd60e51b815260206004820152602c60248201527f455243313135355061757361626c653a20746f6b656e207472616e736665722060448201526b1dda1a5b19481c185d5cd95960a21b60648201526084016105bd565b60006001600160e01b03198216636cdb3d1360e11b148061131357506001600160e01b031982166303a24d0760e21b145b80610613575061061382611f04565b6001600160a01b0384166113485760405162461bcd60e51b81526004016105bd90612f63565b81518351146113695760405162461bcd60e51b81526004016105bd90612f1b565b3361137981600087878787611f39565b60005b845181101561141557838181518110611397576113976130fb565b6020026020010151600160008784815181106113b5576113b56130fb565b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b0316815260200190815260200160002060008282546113fd9190612fc7565b9091555081905061140d816130ca565b91505061137c565b50846001600160a01b031660006001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051611466929190612caa565b60405180910390a461087781600087878787611f47565b815183511461149e5760405162461bcd60e51b81526004016105bd90612f1b565b6001600160a01b0384166114c45760405162461bcd60e51b81526004016105bd90612dfe565b336114d3818787878787611f39565b60005b84518110156115bc5760008582815181106114f3576114f36130fb565b602002602001015190506000858381518110611511576115116130fb565b60209081029190910181015160008481526001835260408082206001600160a01b038e1683529093529190912054909150818110156115625760405162461bcd60e51b81526004016105bd90612ed1565b60008381526001602090815260408083206001600160a01b038e8116855292528083208585039055908b168252812080548492906115a1908490612fc7565b92505081905550505050806115b5906130ca565b90506114d6565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161160c929190612caa565b60405180910390a4611263818787878787611f47565b610f6881336120b2565b6116368282610e52565b610922576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905561166c3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6116ba8282610e52565b15610922576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60045460ff1661175e5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016105bd565b6004805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0383166117ce5760405162461bcd60e51b81526004016105bd90612e43565b80518251146117ef5760405162461bcd60e51b81526004016105bd90612f1b565b600033905061181281856000868660405180602001604052806000815250611f39565b60005b83518110156118da576000848281518110611832576118326130fb565b602002602001015190506000848381518110611850576118506130fb565b60209081029190910181015160008481526001835260408082206001600160a01b038c1683529093529190912054909150818110156118a15760405162461bcd60e51b81526004016105bd90612d71565b60009283526001602090815260408085206001600160a01b038b16865290915290922091039055806118d2816130ca565b915050611815565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb868660405161192b929190612caa565b60405180910390a460408051602081019091526000905261077f565b6001600160a01b03841661196d5760405162461bcd60e51b81526004016105bd90612f63565b33600061197985612116565b9050600061198685612116565b905061199783600089858589611f39565b60008681526001602090815260408083206001600160a01b038b168452909152812080548792906119c9908490612fc7565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461126183600089898989612161565b60045460ff1615611a6f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016105bd565b6004805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861178b3390565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611b009190612b63565b6000604051808303816000865af19150503d8060008114611b3d576040519150601f19603f3d011682016040523d82523d6000602084013e611b42565b606091505b5091509150818015611b6c575080511580611b6c575080806020019051810190611b6c9190612981565b6108775760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c45440060448201526064016105bd565b816001600160a01b0316836001600160a01b03161415611c2c5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b60648201526084016105bd565b6001600160a01b03838116600081815260026020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b80516109229060039060208401906123cd565b6001600160a01b038416611cd25760405162461bcd60e51b81526004016105bd90612dfe565b336000611cde85612116565b90506000611ceb85612116565b9050611cfb838989858589611f39565b60008681526001602090815260408083206001600160a01b038c16845290915290205485811015611d3e5760405162461bcd60e51b81526004016105bd90612ed1565b60008781526001602090815260408083206001600160a01b038d8116855292528083208985039055908a16825281208054889290611d7d908490612fc7565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4611ddd848a8a8a8a8a612161565b505050505050505050565b6001600160a01b038316611e0e5760405162461bcd60e51b81526004016105bd90612e43565b336000611e1a84612116565b90506000611e2784612116565b9050611e4783876000858560405180602001604052806000815250611f39565b60008581526001602090815260408083206001600160a01b038a16845290915290205484811015611e8a5760405162461bcd60e51b81526004016105bd90612d71565b60008681526001602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a90529092908816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4604080516020810190915260009052611261565b60006001600160e01b03198216637965db0b60e01b148061061357506301ffc9a760e01b6001600160e01b0319831614610613565b6112638686868686866110da565b6001600160a01b0384163b156112635760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190611f8b9089908990889088908890600401612bf4565b602060405180830381600087803b158015611fa557600080fd5b505af1925050508015611fd5575060408051601f3d908101601f19168201909252611fd2918101906129f7565b60015b61208257611fe1613127565b806308c379a0141561201b5750611ff6613143565b80612001575061201d565b8060405162461bcd60e51b81526004016105bd9190612cd8565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e20455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b60648201526084016105bd565b6001600160e01b0319811663bc197c8160e01b146112615760405162461bcd60e51b81526004016105bd90612ceb565b6120bc8282610e52565b610922576120d4816001600160a01b0316601461222b565b6120df83602061222b565b6040516020016120f0929190612b7f565b60408051601f198184030181529082905262461bcd60e51b82526105bd91600401612cd8565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110612150576121506130fb565b602090810291909101015292915050565b6001600160a01b0384163b156112635760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906121a59089908990889088908890600401612c52565b602060405180830381600087803b1580156121bf57600080fd5b505af19250505080156121ef575060408051601f3d908101601f191682019092526121ec918101906129f7565b60015b6121fb57611fe1613127565b6001600160e01b0319811663f23a6e6160e01b146112615760405162461bcd60e51b81526004016105bd90612ceb565b6060600061223a836002613001565b612245906002612fc7565b6001600160401b0381111561225c5761225c613111565b6040519080825280601f01601f191660200182016040528015612286576020820181803683370190505b509050600360fc1b816000815181106122a1576122a16130fb565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106122d0576122d06130fb565b60200101906001600160f81b031916908160001a90535060006122f4846002613001565b6122ff906001612fc7565b90505b6001811115612377576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612333576123336130fb565b1a60f81b828281518110612349576123496130fb565b60200101906001600160f81b031916908160001a90535060049490941c936123708161304c565b9050612302565b5083156123c65760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016105bd565b9392505050565b8280546123d990613063565b90600052602060002090601f0160209004810192826123fb5760008555612441565b82601f1061241457805160ff1916838001178555612441565b82800160010185558215612441579182015b82811115612441578251825591602001919060010190612426565b5061244d929150612451565b5090565b5b8082111561244d5760008155600101612452565b80356001600160a01b038116811461247d57600080fd5b919050565b600082601f83011261249357600080fd5b813560206124a082612fa4565b6040516124ad828261309e565b8381528281019150858301600585901b870184018810156124cd57600080fd5b60005b858110156124ec578135845292840192908401906001016124d0565b5090979650505050505050565b600082601f83011261250a57600080fd5b81356001600160401b0381111561252357612523613111565b60405161253a601f8301601f19166020018261309e565b81815284602083860101111561254f57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020828403121561257e57600080fd5b6123c682612466565b6000806040838503121561259a57600080fd5b6125a383612466565b91506107a560208401612466565b600080600080600060a086880312156125c957600080fd5b6125d286612466565b94506125e060208701612466565b935060408601356001600160401b03808211156125fc57600080fd5b61260889838a01612482565b9450606088013591508082111561261e57600080fd5b61262a89838a01612482565b9350608088013591508082111561264057600080fd5b5061264d888289016124f9565b9150509295509295909350565b600080600080600060a0868803121561267257600080fd5b61267b86612466565b945061268960208701612466565b9350604086013592506060860135915060808601356001600160401b038111156126b257600080fd5b61264d888289016124f9565b6000806000606084860312156126d357600080fd5b6126dc84612466565b925060208401356001600160401b03808211156126f857600080fd5b61270487838801612482565b9350604086013591508082111561271a57600080fd5b5061272786828701612482565b9150509250925092565b6000806000806080858703121561274757600080fd5b61275085612466565b935060208501356001600160401b038082111561276c57600080fd5b61277888838901612482565b9450604087013591508082111561278e57600080fd5b61279a88838901612482565b935060608701359150808211156127b057600080fd5b506127bd878288016124f9565b91505092959194509250565b600080604083850312156127dc57600080fd5b6127e583612466565b915060208301356127f5816131cc565b809150509250929050565b6000806040838503121561281357600080fd5b61281c83612466565b946020939093013593505050565b60008060006060848603121561283f57600080fd5b61284884612466565b95602085013595506040909401359392505050565b6000806000806080858703121561287357600080fd5b61287c85612466565b9350602085013592506040850135915060608501356001600160401b038111156128a557600080fd5b6127bd878288016124f9565b600080604083850312156128c457600080fd5b82356001600160401b03808211156128db57600080fd5b818501915085601f8301126128ef57600080fd5b813560206128fc82612fa4565b604051612909828261309e565b8381528281019150858301600585901b870184018b101561292957600080fd5b600096505b848710156129535761293f81612466565b83526001969096019591830191830161292e565b509650508601359250508082111561296a57600080fd5b5061297785828601612482565b9150509250929050565b60006020828403121561299357600080fd5b81516123c6816131cc565b6000602082840312156129b057600080fd5b5035919050565b600080604083850312156129ca57600080fd5b823591506107a560208401612466565b6000602082840312156129ec57600080fd5b81356123c6816131da565b600060208284031215612a0957600080fd5b81516123c6816131da565b60008060208385031215612a2757600080fd5b82356001600160401b0380821115612a3e57600080fd5b818501915085601f830112612a5257600080fd5b813581811115612a6157600080fd5b866020828501011115612a7357600080fd5b60209290920196919550909350505050565b600060208284031215612a9757600080fd5b5051919050565b60008060408385031215612ab157600080fd5b8235915060208301356001600160401b03811115612ace57600080fd5b612977858286016124f9565b60008060408385031215612aed57600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b83811015612b2c57815187529582019590820190600101612b10565b509495945050505050565b60008151808452612b4f816020860160208601613020565b601f01601f19169290920160200192915050565b60008251612b75818460208701613020565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612bb7816017850160208801613020565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351612be8816028840160208801613020565b01602801949350505050565b6001600160a01b0386811682528516602082015260a060408201819052600090612c2090830186612afc565b8281036060840152612c328186612afc565b90508281036080840152612c468185612b37565b98975050505050505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090612c8c90830184612b37565b979650505050505050565b6020815260006123c66020830184612afc565b604081526000612cbd6040830185612afc565b8281036020840152612ccf8185612afc565b95945050505050565b6020815260006123c66020830184612b37565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b60208082526030908201526000805160206131f183398151915260408201526f68617665206d696e74657220726f6c6560801b606082015260800190565b60208082526024908201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604082015263616e636560e01b606082015260800190565b60208082526029908201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260408201526808185c1c1c9bdd995960ba1b606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526023908201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526038908201526000805160206131f183398151915260408201527f68617665206d696e74657220726f6c6520746f206d696e740000000000000000606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b60208082526021908201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60006001600160401b03821115612fbd57612fbd613111565b5060051b60200190565b60008219821115612fda57612fda6130e5565b500190565b600082612ffc57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561301b5761301b6130e5565b500290565b60005b8381101561303b578181015183820152602001613023565b8381111561077f5750506000910152565b60008161305b5761305b6130e5565b506000190190565b600181811c9082168061307757607f821691505b6020821081141561309857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f191681016001600160401b03811182821017156130c3576130c3613111565b6040525050565b60006000198214156130de576130de6130e5565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d11156131405760046000803e5060005160e01c5b90565b600060443d10156131515790565b6040516003193d81016004833e81513d6001600160401b03816024840111818411171561318057505050505090565b82850191508151818111156131985750505050505090565b843d87010160208285010111156131b25750505050505090565b6131c16020828601018761309e565b509095945050505050565b8015158114610f6857600080fd5b6001600160e01b031981168114610f6857600080fdfe455243313135355072657365744d696e7465725061757365723a206d757374209f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6a2646970667358221220a8c9bbcfb8536ce6099f41433f0f109b8b9cf62951d560c7163d5289d945210964736f6c634300080700334d6574614c696e65204d797374657279426f782053656d692d66756e6769626c6520546f6b656e0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f6d657461646174612e6d6574616c696e652e67616d65732f612f7b69647d0000000000000000000000000000000000000000000000000000

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f6d657461646174612e6d6574616c696e652e67616d65732f612f7b69647d0000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : uri (string): https://metadata.metaline.games/a/{id}

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000026
Arg [2] : 68747470733a2f2f6d657461646174612e6d6574616c696e652e67616d65732f
Arg [3] : 612f7b69647d0000000000000000000000000000000000000000000000000000


Deployed ByteCode Sourcemap

220:254:35:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2185:228:3;;;;;;:::i;:::-;;:::i;:::-;;;15474:25:43;;;15462:2;15447:18;2185:228:3;;;;;;;;4909:294:31;;;;;;:::i;:::-;;:::i;:::-;;;15301:14:43;;15294:22;15276:41;;15264:2;15249:18;4909:294:31;15136:187:43;2385:91:31;;;:::i;:::-;;;;;;;:::i;1704:25::-;;;;;;1940:103:3;;;;;;:::i;:::-;;:::i;3722:325:31:-;;;;;;:::i;:::-;;:::i;:::-;;4391:129:0;;;;;;:::i;:::-;4465:7;4491:12;;;;;;;;;;:22;;;;4391:129;5839:257:31;;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;14313:32:43;;;14295:51;;14377:2;14362:18;;14355:34;;;;14268:18;5839:257:31;14121:274:43;5595:197:31;;;;;;:::i;:::-;;:::i;4060:430:3:-;;;;;;:::i;:::-;;:::i;4770:145:0:-;;;;;;:::i;:::-;;:::i;5787:214::-;;;;;;:::i;:::-;;:::i;7704:416:31:-;;;;;;:::i;:::-;;:::i;4657:180::-;;;:::i;2570:508:3:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;901:120:8:-;;;;;;:::i;:::-;958:4;785:16;;;:12;:16;;;;;;-1:-1:-1;;;901:120:8;1098:84:2;1168:7;;;;1098:84;;8322:192:31;;;;;;:::i;:::-;;:::i;6865:58::-;;6901:22;6865:58;;709:342:6;;;;;;:::i;:::-;;:::i;3322:293:31:-;;;;;;:::i;:::-;;:::i;4263:174::-;;;:::i;6133:335::-;;;;;;:::i;:::-;;:::i;2895:145:0:-;;;;;;:::i;:::-;;:::i;2616:95:31:-;;;:::i;6474:318::-;;;:::i;2027:49:0:-;;2072:4;2027:49;;3146:153:3;;;;;;:::i;:::-;;:::i;697:111:8:-;;;;;;:::i;:::-;759:7;785:16;;;:12;:16;;;;;;;697:111;2892:208:31;;;;;;:::i;:::-;;:::i;1428:62::-;;-1:-1:-1;;;;;;;;;;;1428:62:31;;5149:147:0;;;;;;:::i;:::-;;:::i;1497:62:31:-;;1535:24;1497:62;;3366:166:3;;;;;;:::i;:::-;-1:-1:-1;;;;;3488:27:3;;;3465:4;3488:27;;;:18;:27;;;;;;;;:37;;;;;;;;;;;;;;;3366:166;3599:389;;;;;;:::i;:::-;;:::i;393:310:6:-;;;;;;:::i;:::-;;:::i;2185:228:3:-;2271:7;-1:-1:-1;;;;;2298:21:3;;2290:77;;;;-1:-1:-1;;;2290:77:3;;18475:2:43;2290:77:3;;;18457:21:43;18514:2;18494:18;;;18487:30;18553:34;18533:18;;;18526:62;-1:-1:-1;;;18604:18:43;;;18597:41;18655:19;;2290:77:3;;;;;;;;;-1:-1:-1;2384:13:3;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;2384:22:3;;;;;;;;;;;;2185:228::o;4909:294:31:-;5063:4;-1:-1:-1;;;;;;5092:50:31;;-1:-1:-1;;;5092:50:31;;:103;;;5159:36;5183:11;5159:23;:36::i;:::-;5085:110;4909:294;-1:-1:-1;;4909:294:31:o;2385:91::-;2430:13;2463:5;2456:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2385:91;:::o;1940:103:3:-;2000:13;2032:4;2025:11;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1940:103;;;:::o;3722:325:31:-;3897:34;-1:-1:-1;;;;;;;;;;;719:10:23;2895:145:0;:::i;3897:34:31:-;3889:103;;;;-1:-1:-1;;;3889:103:31;;;;;;;:::i;:::-;4005:34;4016:2;4020:3;4025:7;4034:4;4005:10;:34::i;:::-;3722:325;;;;:::o;5839:257::-;6069:10;;6028:4;;5952:16;;6083:5;;6061:18;;:5;:18;:::i;:::-;6060:28;;;;:::i;:::-;6044:44;;5839:257;;;;;:::o;5595:197::-;5664:34;-1:-1:-1;;;;;;;;;;;719:10:23;2895:145:0;:::i;5664:34:31:-;5656:95;;;;-1:-1:-1;;;5656:95:31;;;;;;;:::i;:::-;5762:10;:22;5595:197::o;4060:430:3:-;-1:-1:-1;;;;;4285:20:3;;719:10:23;4285:20:3;;:60;;-1:-1:-1;4309:36:3;4326:4;719:10:23;3366:166:3;:::i;4309:36::-;4264:157;;;;-1:-1:-1;;;4264:157:3;;21606:2:43;4264:157:3;;;21588:21:43;21645:2;21625:18;;;21618:30;21684:34;21664:18;;;21657:62;-1:-1:-1;;;21735:18:43;;;21728:48;21793:19;;4264:157:3;21404:414:43;4264:157:3;4431:52;4454:4;4460:2;4464:3;4469:7;4478:4;4431:22;:52::i;:::-;4060:430;;;;;:::o;4770:145:0:-;4465:7;4491:12;;;;;;;;;;:22;;;2505:16;2516:4;2505:10;:16::i;:::-;4883:25:::1;4894:4;4900:7;4883:10;:25::i;:::-;4770:145:::0;;;:::o;5787:214::-;-1:-1:-1;;;;;5882:23:0;;719:10:23;5882:23:0;5874:83;;;;-1:-1:-1;;;5874:83:0;;27246:2:43;5874:83:0;;;27228:21:43;27285:2;27265:18;;;27258:30;27324:34;27304:18;;;27297:62;-1:-1:-1;;;27375:18:43;;;27368:45;27430:19;;5874:83:0;27044:411:43;5874:83:0;5968:26;5980:4;5986:7;5968:11;:26::i;:::-;5787:214;;:::o;7704:416:31:-;1168:7:2;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:2;;20855:2:43;1403:38:2;;;20837:21:43;20894:2;20874:18;;;20867:30;-1:-1:-1;;;20913:18:43;;;20906:46;20969:18;;1403:38:2;20653:340:43;1403:38:2;7848:32:31::1;6901:22;719:10:23::0;2895:145:0;:::i;7848:32:31:-:1;7826:84;;;::::0;-1:-1:-1;;;7826:84:31;;26105:2:43;7826:84:31::1;::::0;::::1;26087:21:43::0;26144:1;26124:18;;;26117:29;-1:-1:-1;;;26162:18:43;;;26155:32;26204:18;;7826:84:31::1;25903:325:43::0;7826:84:31::1;958:4:8::0;785:16;;;:12;:16;;;;;;7923:62:31::1;;;::::0;-1:-1:-1;;;7923:62:31;;24529:2:43;7923:62:31::1;::::0;::::1;24511:21:43::0;24568:1;24548:18;;;24541:29;-1:-1:-1;;;24586:18:43;;;24579:32;24628:18;;7923:62:31::1;24327:325:43::0;7923:62:31::1;8029:16;::::0;;;:12:::1;:16;::::0;;;;;;;:29;;::::1;::::0;;::::1;::::0;::::1;:::i;:::-;;8097:2;8076:36;8101:10;8076:36;;;;;;:::i;:::-;;;;;;;;7704:416:::0;;:::o;4657:180::-;4710:34;1535:24;719:10:23;2895:145:0;:::i;4710:34:31:-;4702:106;;;;-1:-1:-1;;;4702:106:31;;24101:2:43;4702:106:31;;;24083:21:43;24140:2;24120:18;;;24113:30;-1:-1:-1;;;;;;;;;;;24159:18:43;;;24152:62;24250:29;24230:18;;;24223:57;24297:19;;4702:106:31;23899:423:43;4702:106:31;4819:10;:8;:10::i;:::-;4657:180::o;2570:508:3:-;2721:16;2780:3;:10;2761:8;:15;:29;2753:83;;;;-1:-1:-1;;;2753:83:3;;25695:2:43;2753:83:3;;;25677:21:43;25734:2;25714:18;;;25707:30;25773:34;25753:18;;;25746:62;-1:-1:-1;;;25824:18:43;;;25817:39;25873:19;;2753:83:3;25493:405:43;2753:83:3;2847:30;2894:8;:15;-1:-1:-1;;;;;2880:30:3;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2880:30:3;;2847:63;;2926:9;2921:120;2945:8;:15;2941:1;:19;2921:120;;;3000:30;3010:8;3019:1;3010:11;;;;;;;;:::i;:::-;;;;;;;3023:3;3027:1;3023:6;;;;;;;;:::i;:::-;;;;;;;3000:9;:30::i;:::-;2981:13;2995:1;2981:16;;;;;;;;:::i;:::-;;;;;;;;;;:49;2962:3;;;:::i;:::-;;;2921:120;;;-1:-1:-1;3058:13:3;2570:508;-1:-1:-1;;;2570:508:3:o;8322:192:31:-;958:4:8;785:16;;;:12;:16;;;;;;8415:12:31;;8445:25;;;;-1:-1:-1;;;8445:25:31;;20525:2:43;8445:25:31;;;20507:21:43;20564:1;20544:18;;;20537:29;-1:-1:-1;;;20582:18:43;;;20575:32;20624:18;;8445:25:31;20323:325:43;8445:25:31;8490:16;;;;:12;:16;;;;;8483:23;;;;;:::i;709:342:6:-;-1:-1:-1;;;;;868:23:6;;719:10:23;868:23:6;;:66;;-1:-1:-1;895:39:6;912:7;719:10:23;3366:166:3;:::i;895:39:6:-;847:154;;;;-1:-1:-1;;;847:154:6;;;;;;;:::i;:::-;1012:32;1023:7;1032:3;1037:6;1012:10;:32::i;3322:293:31:-;3472:34;-1:-1:-1;;;;;;;;;;;719:10:23;2895:145:0;:::i;3472:34:31:-;3464:103;;;;-1:-1:-1;;;3464:103:31;;;;;;;:::i;:::-;3580:27;3586:2;3590;3594:6;3602:4;3580:5;:27::i;4263:174::-;4314:34;1535:24;719:10:23;2895:145:0;:::i;4314:34:31:-;4306:104;;;;-1:-1:-1;;;4306:104:31;;24859:2:43;4306:104:31;;;24841:21:43;24898:2;24878:18;;;24871:30;-1:-1:-1;;;;;;;;;;;24917:18:43;;;24910:62;25008:27;24988:18;;;24981:55;25053:19;;4306:104:31;24657:421:43;4306:104:31;4421:8;:6;:8::i;6133:335::-;6197:34;-1:-1:-1;;;;;;;;;;;719:10:23;2895:145:0;:::i;6197:34:31:-;6189:95;;;;-1:-1:-1;;;6189:95:31;;;;;;;:::i;:::-;6314:38;;-1:-1:-1;;;6314:38:31;;6346:4;6314:38;;;12663:51:43;6297:14:31;;-1:-1:-1;;;;;6314:23:31;;;;;12636:18:43;;6314:38:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6297:55;-1:-1:-1;6366:10:31;;6363:98;;6393:56;6421:5;719:10:23;6442:6:31;6393:27;:56::i;2895:145:0:-;2981:4;3004:12;;;;;;;;;;;-1:-1:-1;;;;;3004:29:0;;;;;;;;;;;;;;;2895:145::o;2616:95:31:-;2663:13;2696:7;2689:14;;;;;:::i;6474:318::-;6528:34;-1:-1:-1;;;;;;;;;;;719:10:23;2895:145:0;:::i;6528:34:31:-;6520:95;;;;-1:-1:-1;;;6520:95:31;;;;;;;:::i;:::-;6665:50;;6650:9;;719:10:23;;6689:21:31;;6650:9;6665:50;6650:9;6665:50;6689:21;719:10:23;6665:50:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6649:66;;;6734:4;6726:58;;;;-1:-1:-1;;;6726:58:31;;20115:2:43;6726:58:31;;;20097:21:43;20154:2;20134:18;;;20127:30;20193:34;20173:18;;;20166:62;-1:-1:-1;;;20244:18:43;;;20237:39;20293:19;;6726:58:31;19913:405:43;6726:58:31;6509:283;6474:318::o;3146:153:3:-;3240:52;719:10:23;3273:8:3;3283;3240:18;:52::i;2892:208:31:-;2969:34;-1:-1:-1;;;;;;;;;;;719:10:23;2895:145:0;:::i;2969:34:31:-;2961:105;;;;-1:-1:-1;;;2961:105:31;;22025:2:43;2961:105:31;;;22007:21:43;22064:2;22044:18;;;22037:30;-1:-1:-1;;;;;;;;;;;22083:18:43;;;22076:62;22174:28;22154:18;;;22147:56;22220:19;;2961:105:31;21823:422:43;2961:105:31;3077:15;3085:6;;3077:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3077:7:31;;-1:-1:-1;;;3077:15:31:i;5149:147:0:-;4465:7;4491:12;;;;;;;;;;:22;;;2505:16;2516:4;2505:10;:16::i;:::-;5263:26:::1;5275:4;5281:7;5263:11;:26::i;3599:389:3:-:0;-1:-1:-1;;;;;3799:20:3;;719:10:23;3799:20:3;;:60;;-1:-1:-1;3823:36:3;3840:4;719:10:23;3366:166:3;:::i;3823:36::-;3778:148;;;;-1:-1:-1;;;3778:148:3;;;;;;;:::i;:::-;3936:45;3954:4;3960:2;3964;3968:6;3976:4;3936:17;:45::i;393:310:6:-;-1:-1:-1;;;;;527:23:6;;719:10:23;527:23:6;;:66;;-1:-1:-1;554:39:6;571:7;719:10:23;3366:166:3;:::i;554:39:6:-;506:154;;;;-1:-1:-1;;;506:154:6;;;;;;;:::i;:::-;671:25;677:7;686:2;690:5;671;:25::i;1091:904:8:-;1322:66;1349:8;1359:4;1365:2;1369:3;1374:7;1383:4;1322:26;:66::i;:::-;-1:-1:-1;;;;;1403:18:8;;1399:156;;1442:9;1437:108;1461:3;:10;1457:1;:14;1437:108;;;1520:7;1528:1;1520:10;;;;;;;;:::i;:::-;;;;;;;1496:12;:20;1509:3;1513:1;1509:6;;;;;;;;:::i;:::-;;;;;;;1496:20;;;;;;;;;;;;:34;;;;;;;:::i;:::-;;;;-1:-1:-1;1473:3:8;;-1:-1:-1;1473:3:8;;:::i;:::-;;;1437:108;;;;1399:156;-1:-1:-1;;;;;1569:16:8;;1565:424;;1606:9;1601:378;1625:3;:10;1621:1;:14;1601:378;;;1660:10;1673:3;1677:1;1673:6;;;;;;;;:::i;:::-;;;;;;;1660:19;;1697:14;1714:7;1722:1;1714:10;;;;;;;;:::i;:::-;;;;;;;1697:27;;1742:14;1759:12;:16;1772:2;1759:16;;;;;;;;;;;;1742:33;;1811:6;1801;:16;;1793:69;;;;-1:-1:-1;;;1793:69:8;;23692:2:43;1793:69:8;;;23674:21:43;23731:2;23711:18;;;23704:30;23770:34;23750:18;;;23743:62;-1:-1:-1;;;23821:18:43;;;23814:38;23869:19;;1793:69:8;23490:404:43;1793:69:8;1912:16;;;;:12;:16;;;;;;1931:15;;1912:34;;1637:3;;;:::i;:::-;;;1601:378;;;;1565:424;1091:904;;;;;;:::o;1175:320:22:-;-1:-1:-1;;;;;1465:19:22;;:23;;;1175:320::o;709:381:7:-;1168:7:2;;;;1025:9:7;1017:66;;;;-1:-1:-1;;;1017:66:7;;19292:2:43;1017:66:7;;;19274:21:43;19331:2;19311:18;;;19304:30;19370:34;19350:18;;;19343:62;-1:-1:-1;;;19421:18:43;;;19414:42;19473:19;;1017:66:7;19090:408:43;1236:305:3;1338:4;-1:-1:-1;;;;;;1373:41:3;;-1:-1:-1;;;1373:41:3;;:109;;-1:-1:-1;;;;;;;1430:52:3;;-1:-1:-1;;;1430:52:3;1373:109;:161;;;;1498:36;1522:11;1498:23;:36::i;9684:791::-;-1:-1:-1;;;;;9856:16:3;;9848:62;;;;-1:-1:-1;;;9848:62:3;;;;;;;:::i;:::-;9942:7;:14;9928:3;:10;:28;9920:81;;;;-1:-1:-1;;;9920:81:3;;;;;;;:::i;:::-;719:10:23;10054:66:3;719:10:23;10012:16:3;10097:2;10101:3;10106:7;10115:4;10054:20;:66::i;:::-;10136:9;10131:101;10155:3;:10;10151:1;:14;10131:101;;;10211:7;10219:1;10211:10;;;;;;;;:::i;:::-;;;;;;;10186:9;:17;10196:3;10200:1;10196:6;;;;;;;;:::i;:::-;;;;;;;10186:17;;;;;;;;;;;:21;10204:2;-1:-1:-1;;;;;10186:21:3;-1:-1:-1;;;;;10186:21:3;;;;;;;;;;;;;:35;;;;;;;:::i;:::-;;;;-1:-1:-1;10167:3:3;;-1:-1:-1;10167:3:3;;;:::i;:::-;;;;10131:101;;;;10283:2;-1:-1:-1;;;;;10247:53:3;10279:1;-1:-1:-1;;;;;10247:53:3;10261:8;-1:-1:-1;;;;;10247:53:3;;10287:3;10292:7;10247:53;;;;;;;:::i;:::-;;;;;;;;10387:81;10423:8;10441:1;10445:2;10449:3;10454:7;10463:4;10387:35;:81::i;6233:1115::-;6453:7;:14;6439:3;:10;:28;6431:81;;;;-1:-1:-1;;;6431:81:3;;;;;;;:::i;:::-;-1:-1:-1;;;;;6530:16:3;;6522:66;;;;-1:-1:-1;;;6522:66:3;;;;;;;:::i;:::-;719:10:23;6641:60:3;719:10:23;6672:4:3;6678:2;6682:3;6687:7;6696:4;6641:20;:60::i;:::-;6717:9;6712:411;6736:3;:10;6732:1;:14;6712:411;;;6767:10;6780:3;6784:1;6780:6;;;;;;;;:::i;:::-;;;;;;;6767:19;;6800:14;6817:7;6825:1;6817:10;;;;;;;;:::i;:::-;;;;;;;;;;;;6842:19;6864:13;;;:9;:13;;;;;;-1:-1:-1;;;;;6864:19:3;;;;;;;;;;;;6817:10;;-1:-1:-1;6905:21:3;;;;6897:76;;;;-1:-1:-1;;;6897:76:3;;;;;;;:::i;:::-;7015:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;7015:19:3;;;;;;;;;;7037:20;;;7015:42;;7085:17;;;;;;;:27;;7037:20;;7015:13;7085:27;;7037:20;;7085:27;:::i;:::-;;;;;;;;6753:370;;;6748:3;;;;:::i;:::-;;;6712:411;;;;7168:2;-1:-1:-1;;;;;7138:47:3;7162:4;-1:-1:-1;;;;;7138:47:3;7152:8;-1:-1:-1;;;;;7138:47:3;;7172:3;7177:7;7138:47;;;;;;;:::i;:::-;;;;;;;;7266:75;7302:8;7312:4;7318:2;7322:3;7327:7;7336:4;7266:35;:75::i;3334:103:0:-;3400:30;3411:4;719:10:23;3400::0;:30::i;7244:233::-;7327:22;7335:4;7341:7;7327;:22::i;:::-;7322:149;;7365:6;:12;;;;;;;;;;;-1:-1:-1;;;;;7365:29:0;;;;;;;;;:36;;-1:-1:-1;;7365:36:0;7397:4;7365:36;;;7447:12;719:10:23;;640:96;7447:12:0;-1:-1:-1;;;;;7420:40:0;7438:7;-1:-1:-1;;;;;7420:40:0;7432:4;7420:40;;;;;;;;;;7244:233;;:::o;7602:234::-;7685:22;7693:4;7699:7;7685;:22::i;:::-;7681:149;;;7755:5;7723:12;;;;;;;;;;;-1:-1:-1;;;;;7723:29:0;;;;;;;;;;:37;;-1:-1:-1;;7723:37:0;;;7779:40;719:10:23;;7723:12:0;;7779:40;;7755:5;7779:40;7602:234;;:::o;2110:117:2:-;1168:7;;;;1669:41;;;;-1:-1:-1;;;1669:41:2;;18126:2:43;1669:41:2;;;18108:21:43;18165:2;18145:18;;;18138:30;-1:-1:-1;;;18184:18:43;;;18177:50;18244:18;;1669:41:2;17924:344:43;1669:41:2;2168:7:::1;:15:::0;;-1:-1:-1;;2168:15:2::1;::::0;;2198:22:::1;719:10:23::0;2207:12:2::1;2198:22;::::0;-1:-1:-1;;;;;12681:32:43;;;12663:51;;12651:2;12636:18;2198:22:2::1;;;;;;;2110:117::o:0;11695:943:3:-;-1:-1:-1;;;;;11842:18:3;;11834:66;;;;-1:-1:-1;;;11834:66:3;;;;;;;:::i;:::-;11932:7;:14;11918:3;:10;:28;11910:81;;;;-1:-1:-1;;;11910:81:3;;;;;;;:::i;:::-;12002:16;719:10:23;12002:31:3;;12044:66;12065:8;12075:4;12089:1;12093:3;12098:7;12044:66;;;;;;;;;;;;:20;:66::i;:::-;12126:9;12121:364;12145:3;:10;12141:1;:14;12121:364;;;12176:10;12189:3;12193:1;12189:6;;;;;;;;:::i;:::-;;;;;;;12176:19;;12209:14;12226:7;12234:1;12226:10;;;;;;;;:::i;:::-;;;;;;;;;;;;12251:19;12273:13;;;:9;:13;;;;;;-1:-1:-1;;;;;12273:19:3;;;;;;;;;;;;12226:10;;-1:-1:-1;12314:21:3;;;;12306:70;;;;-1:-1:-1;;;12306:70:3;;;;;;;:::i;:::-;12418:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;12418:19:3;;;;;;;;;;12440:20;;12418:42;;12157:3;;;;:::i;:::-;;;;12121:364;;;;12538:1;-1:-1:-1;;;;;12500:55:3;12524:4;-1:-1:-1;;;;;12500:55:3;12514:8;-1:-1:-1;;;;;12500:55:3;;12542:3;12547:7;12500:55;;;;;;;:::i;:::-;;;;;;;;12566:65;;;;;;;;;12610:1;12566:65;;;1091:904:8;8630:709:3;-1:-1:-1;;;;;8777:16:3;;8769:62;;;;-1:-1:-1;;;8769:62:3;;;;;;;:::i;:::-;719:10:23;8842:16:3;8906:21;8924:2;8906:17;:21::i;:::-;8883:44;;8937:24;8964:25;8982:6;8964:17;:25::i;:::-;8937:52;;9000:66;9021:8;9039:1;9043:2;9047:3;9052:7;9061:4;9000:20;:66::i;:::-;9077:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;9077:17:3;;;;;;;;;:27;;9098:6;;9077:13;:27;;9098:6;;9077:27;:::i;:::-;;;;-1:-1:-1;;9119:52:3;;;27816:25:43;;;27872:2;27857:18;;27850:34;;;-1:-1:-1;;;;;9119:52:3;;;;9152:1;;9119:52;;;;;;27789:18:43;9119:52:3;;;;;;;9258:74;9289:8;9307:1;9311:2;9315;9319:6;9327:4;9258:30;:74::i;1863:115:2:-;1168:7;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:2;;20855:2:43;1403:38:2;;;20837:21:43;20894:2;20874:18;;;20867:30;-1:-1:-1;;;20913:18:43;;;20906:46;20969:18;;1403:38:2;20653:340:43;1403:38:2;1922:7:::1;:14:::0;;-1:-1:-1;;1922:14:2::1;1932:4;1922:14;::::0;;1951:20:::1;1958:12;719:10:23::0;;640:96;489:361:42;684:45;;;-1:-1:-1;;;;;14313:32:43;;;684:45:42;;;14295:51:43;14362:18;;;;14355:34;;;684:45:42;;;;;;;;;;14268:18:43;;;;684:45:42;;;;;;;-1:-1:-1;;;;;684:45:42;-1:-1:-1;;;684:45:42;;;673:57;;-1:-1:-1;;;;673:10:42;;;;:57;;684:45;673:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;637:93;;;;749:7;:57;;;;-1:-1:-1;761:11:42;;:16;;:44;;;792:4;781:24;;;;;;;;;;;;:::i;:::-;741:101;;;;-1:-1:-1;;;741:101:42;;17349:2:43;741:101:42;;;17331:21:43;17388:2;17368:18;;;17361:30;17427:33;17407:18;;;17400:61;17478:18;;741:101:42;17147:355:43;12773:323:3;12923:8;-1:-1:-1;;;;;12914:17:3;:5;-1:-1:-1;;;;;12914:17:3;;;12906:71;;;;-1:-1:-1;;;12906:71:3;;25285:2:43;12906:71:3;;;25267:21:43;25324:2;25304:18;;;25297:30;25363:34;25343:18;;;25336:62;-1:-1:-1;;;25414:18:43;;;25407:39;25463:19;;12906:71:3;25083:405:43;12906:71:3;-1:-1:-1;;;;;12987:25:3;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;12987:46:3;;;;;;;;;;13048:41;;15276::43;;;13048::3;;15249:18:43;13048:41:3;;;;;;;12773:323;;;:::o;8171:86::-;8237:13;;;;:4;;:13;;;;;:::i;4940:947::-;-1:-1:-1;;;;;5121:16:3;;5113:66;;;;-1:-1:-1;;;5113:66:3;;;;;;;:::i;:::-;719:10:23;5190:16:3;5254:21;5272:2;5254:17;:21::i;:::-;5231:44;;5285:24;5312:25;5330:6;5312:17;:25::i;:::-;5285:52;;5348:60;5369:8;5379:4;5385:2;5389:3;5394:7;5403:4;5348:20;:60::i;:::-;5419:19;5441:13;;;:9;:13;;;;;;;;-1:-1:-1;;;;;5441:19:3;;;;;;;;;;5478:21;;;;5470:76;;;;-1:-1:-1;;;5470:76:3;;;;;;;:::i;:::-;5580:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;5580:19:3;;;;;;;;;;5602:20;;;5580:42;;5642:17;;;;;;;:27;;5602:20;;5580:13;5642:27;;5602:20;;5642:27;:::i;:::-;;;;-1:-1:-1;;5685:46:3;;;27816:25:43;;;27872:2;27857:18;;27850:34;;;-1:-1:-1;;;;;5685:46:3;;;;;;;;;;;;;;27789:18:43;5685:46:3;;;;;;;5812:68;5843:8;5853:4;5859:2;5863;5867:6;5875:4;5812:30;:68::i;:::-;5103:784;;;;4940:947;;;;;:::o;10715:786::-;-1:-1:-1;;;;;10837:18:3;;10829:66;;;;-1:-1:-1;;;10829:66:3;;;;;;;:::i;:::-;719:10:23;10906:16:3;10970:21;10988:2;10970:17;:21::i;:::-;10947:44;;11001:24;11028:25;11046:6;11028:17;:25::i;:::-;11001:52;;11064:66;11085:8;11095:4;11109:1;11113:3;11118:7;11064:66;;;;;;;;;;;;:20;:66::i;:::-;11141:19;11163:13;;;:9;:13;;;;;;;;-1:-1:-1;;;;;11163:19:3;;;;;;;;;;11200:21;;;;11192:70;;;;-1:-1:-1;;;11192:70:3;;;;;;;:::i;:::-;11296:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;11296:19:3;;;;;;;;;;;;11318:20;;;11296:42;;11364:54;;27816:25:43;;;27857:18;;;27850:34;;;11296:19:3;;11364:54;;;;;;27789:18:43;11364:54:3;;;;;;;11429:65;;;;;;;;;11473:1;11429:65;;;1091:904:8;2606:202:0;2691:4;-1:-1:-1;;;;;;2714:47:0;;-1:-1:-1;;;2714:47:0;;:87;;-1:-1:-1;;;;;;;;;;937:40:26;;;2765:36:0;829:155:26;5211:354:31;5491:66;5518:8;5528:4;5534:2;5538:3;5543:7;5552:4;5491:26;:66::i;16127:792:3:-;-1:-1:-1;;;;;16359:13:3;;1465:19:22;:23;16355:558:3;;16394:79;;-1:-1:-1;;;16394:79:3;;-1:-1:-1;;;;;16394:43:3;;;;;:79;;16438:8;;16448:4;;16454:3;;16459:7;;16468:4;;16394:79;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16394:79:3;;;;;;;;-1:-1:-1;;16394:79:3;;;;;;;;;;;;:::i;:::-;;;16390:513;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;16779:6;16772:14;;-1:-1:-1;;;16772:14:3;;;;;;;;:::i;16390:513::-;;;16826:62;;-1:-1:-1;;;16826:62:3;;16158:2:43;16826:62:3;;;16140:21:43;16197:2;16177:18;;;16170:30;16236:34;16216:18;;;16209:62;-1:-1:-1;;;16287:18:43;;;16280:50;16347:19;;16826:62:3;15956:416:43;16390:513:3;-1:-1:-1;;;;;;16552:60:3;;-1:-1:-1;;;16552:60:3;16548:157;;16636:50;;-1:-1:-1;;;16636:50:3;;;;;;;:::i;3718:492:0:-;3806:22;3814:4;3820:7;3806;:22::i;:::-;3801:403;;3989:41;4017:7;-1:-1:-1;;;;;3989:41:0;4027:2;3989:19;:41::i;:::-;4101:38;4129:4;4136:2;4101:19;:38::i;:::-;3896:265;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;3896:265:0;;;;;;;;;;-1:-1:-1;;;3844:349:0;;;;;;;:::i;16925:193:3:-;17044:16;;;17058:1;17044:16;;;;;;;;;16991;;17019:22;;17044:16;;;;;;;;;;;;-1:-1:-1;17044:16:3;17019:41;;17081:7;17070:5;17076:1;17070:8;;;;;;;;:::i;:::-;;;;;;;;;;:18;17106:5;16925:193;-1:-1:-1;;16925:193:3:o;15396:725::-;-1:-1:-1;;;;;15603:13:3;;1465:19:22;:23;15599:516:3;;15638:72;;-1:-1:-1;;;15638:72:3;;-1:-1:-1;;;;;15638:38:3;;;;;:72;;15677:8;;15687:4;;15693:2;;15697:6;;15705:4;;15638:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;15638:72:3;;;;;;;;-1:-1:-1;;15638:72:3;;;;;;;;;;;;:::i;:::-;;;15634:471;;;;:::i;:::-;-1:-1:-1;;;;;;15759:55:3;;-1:-1:-1;;;15759:55:3;15755:152;;15838:50;;-1:-1:-1;;;15838:50:3;;;;;;;:::i;1588:441:25:-;1663:13;1688:19;1720:10;1724:6;1720:1;:10;:::i;:::-;:14;;1733:1;1720:14;:::i;:::-;-1:-1:-1;;;;;1710:25:25;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1710:25:25;;1688:47;;-1:-1:-1;;;1745:6:25;1752:1;1745:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;1745:15:25;;;;;;;;;-1:-1:-1;;;1770:6:25;1777:1;1770:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;1770:15:25;;;;;;;;-1:-1:-1;1800:9:25;1812:10;1816:6;1812:1;:10;:::i;:::-;:14;;1825:1;1812:14;:::i;:::-;1800:26;;1795:132;1832:1;1828;:5;1795:132;;;-1:-1:-1;;;1879:5:25;1887:3;1879:11;1866:25;;;;;;;:::i;:::-;;;;1854:6;1861:1;1854:9;;;;;;;;:::i;:::-;;;;:37;-1:-1:-1;;;;;1854:37:25;;;;;;;;-1:-1:-1;1915:1:25;1905:11;;;;;1835:3;;;:::i;:::-;;;1795:132;;;-1:-1:-1;1944:10:25;;1936:55;;;;-1:-1:-1;;;1936:55:25;;16579:2:43;1936:55:25;;;16561:21:43;;;16598:18;;;16591:30;16657:34;16637:18;;;16630:62;16709:18;;1936:55:25;16377:356:43;1936:55:25;2015:6;1588:441;-1:-1:-1;;;1588:441:25:o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:173:43;82:20;;-1:-1:-1;;;;;131:31:43;;121:42;;111:70;;177:1;174;167:12;111:70;14:173;;;:::o;192:735::-;246:5;299:3;292:4;284:6;280:17;276:27;266:55;;317:1;314;307:12;266:55;353:6;340:20;379:4;402:43;442:2;402:43;:::i;:::-;474:2;468:9;486:31;514:2;506:6;486:31;:::i;:::-;552:18;;;586:15;;;;-1:-1:-1;621:15:43;;;671:1;667:10;;;655:23;;651:32;;648:41;-1:-1:-1;645:61:43;;;702:1;699;692:12;645:61;724:1;734:163;748:2;745:1;742:9;734:163;;;805:17;;793:30;;843:12;;;;875;;;;766:1;759:9;734:163;;;-1:-1:-1;915:6:43;;192:735;-1:-1:-1;;;;;;;192:735:43:o;932:555::-;974:5;1027:3;1020:4;1012:6;1008:17;1004:27;994:55;;1045:1;1042;1035:12;994:55;1081:6;1068:20;-1:-1:-1;;;;;1103:2:43;1100:26;1097:52;;;1129:18;;:::i;:::-;1178:2;1172:9;1190:67;1245:2;1226:13;;-1:-1:-1;;1222:27:43;1251:4;1218:38;1172:9;1190:67;:::i;:::-;1281:2;1273:6;1266:18;1327:3;1320:4;1315:2;1307:6;1303:15;1299:26;1296:35;1293:55;;;1344:1;1341;1334:12;1293:55;1408:2;1401:4;1393:6;1389:17;1382:4;1374:6;1370:17;1357:54;1455:1;1431:15;;;1448:4;1427:26;1420:37;;;;1435:6;932:555;-1:-1:-1;;;932:555:43:o;1492:186::-;1551:6;1604:2;1592:9;1583:7;1579:23;1575:32;1572:52;;;1620:1;1617;1610:12;1572:52;1643:29;1662:9;1643:29;:::i;1683:260::-;1751:6;1759;1812:2;1800:9;1791:7;1787:23;1783:32;1780:52;;;1828:1;1825;1818:12;1780:52;1851:29;1870:9;1851:29;:::i;:::-;1841:39;;1899:38;1933:2;1922:9;1918:18;1899:38;:::i;1948:943::-;2102:6;2110;2118;2126;2134;2187:3;2175:9;2166:7;2162:23;2158:33;2155:53;;;2204:1;2201;2194:12;2155:53;2227:29;2246:9;2227:29;:::i;:::-;2217:39;;2275:38;2309:2;2298:9;2294:18;2275:38;:::i;:::-;2265:48;;2364:2;2353:9;2349:18;2336:32;-1:-1:-1;;;;;2428:2:43;2420:6;2417:14;2414:34;;;2444:1;2441;2434:12;2414:34;2467:61;2520:7;2511:6;2500:9;2496:22;2467:61;:::i;:::-;2457:71;;2581:2;2570:9;2566:18;2553:32;2537:48;;2610:2;2600:8;2597:16;2594:36;;;2626:1;2623;2616:12;2594:36;2649:63;2704:7;2693:8;2682:9;2678:24;2649:63;:::i;:::-;2639:73;;2765:3;2754:9;2750:19;2737:33;2721:49;;2795:2;2785:8;2782:16;2779:36;;;2811:1;2808;2801:12;2779:36;;2834:51;2877:7;2866:8;2855:9;2851:24;2834:51;:::i;:::-;2824:61;;;1948:943;;;;;;;;:::o;2896:606::-;3000:6;3008;3016;3024;3032;3085:3;3073:9;3064:7;3060:23;3056:33;3053:53;;;3102:1;3099;3092:12;3053:53;3125:29;3144:9;3125:29;:::i;:::-;3115:39;;3173:38;3207:2;3196:9;3192:18;3173:38;:::i;:::-;3163:48;;3258:2;3247:9;3243:18;3230:32;3220:42;;3309:2;3298:9;3294:18;3281:32;3271:42;;3364:3;3353:9;3349:19;3336:33;-1:-1:-1;;;;;3384:6:43;3381:30;3378:50;;;3424:1;3421;3414:12;3378:50;3447:49;3488:7;3479:6;3468:9;3464:22;3447:49;:::i;3507:669::-;3634:6;3642;3650;3703:2;3691:9;3682:7;3678:23;3674:32;3671:52;;;3719:1;3716;3709:12;3671:52;3742:29;3761:9;3742:29;:::i;:::-;3732:39;;3822:2;3811:9;3807:18;3794:32;-1:-1:-1;;;;;3886:2:43;3878:6;3875:14;3872:34;;;3902:1;3899;3892:12;3872:34;3925:61;3978:7;3969:6;3958:9;3954:22;3925:61;:::i;:::-;3915:71;;4039:2;4028:9;4024:18;4011:32;3995:48;;4068:2;4058:8;4055:16;4052:36;;;4084:1;4081;4074:12;4052:36;;4107:63;4162:7;4151:8;4140:9;4136:24;4107:63;:::i;:::-;4097:73;;;3507:669;;;;;:::o;4181:868::-;4326:6;4334;4342;4350;4403:3;4391:9;4382:7;4378:23;4374:33;4371:53;;;4420:1;4417;4410:12;4371:53;4443:29;4462:9;4443:29;:::i;:::-;4433:39;;4523:2;4512:9;4508:18;4495:32;-1:-1:-1;;;;;4587:2:43;4579:6;4576:14;4573:34;;;4603:1;4600;4593:12;4573:34;4626:61;4679:7;4670:6;4659:9;4655:22;4626:61;:::i;:::-;4616:71;;4740:2;4729:9;4725:18;4712:32;4696:48;;4769:2;4759:8;4756:16;4753:36;;;4785:1;4782;4775:12;4753:36;4808:63;4863:7;4852:8;4841:9;4837:24;4808:63;:::i;:::-;4798:73;;4924:2;4913:9;4909:18;4896:32;4880:48;;4953:2;4943:8;4940:16;4937:36;;;4969:1;4966;4959:12;4937:36;;4992:51;5035:7;5024:8;5013:9;5009:24;4992:51;:::i;:::-;4982:61;;;4181:868;;;;;;;:::o;5054:315::-;5119:6;5127;5180:2;5168:9;5159:7;5155:23;5151:32;5148:52;;;5196:1;5193;5186:12;5148:52;5219:29;5238:9;5219:29;:::i;:::-;5209:39;;5298:2;5287:9;5283:18;5270:32;5311:28;5333:5;5311:28;:::i;:::-;5358:5;5348:15;;;5054:315;;;;;:::o;5374:254::-;5442:6;5450;5503:2;5491:9;5482:7;5478:23;5474:32;5471:52;;;5519:1;5516;5509:12;5471:52;5542:29;5561:9;5542:29;:::i;:::-;5532:39;5618:2;5603:18;;;;5590:32;;-1:-1:-1;;;5374:254:43:o;5633:322::-;5710:6;5718;5726;5779:2;5767:9;5758:7;5754:23;5750:32;5747:52;;;5795:1;5792;5785:12;5747:52;5818:29;5837:9;5818:29;:::i;:::-;5808:39;5894:2;5879:18;;5866:32;;-1:-1:-1;5945:2:43;5930:18;;;5917:32;;5633:322;-1:-1:-1;;;5633:322:43:o;5960:531::-;6055:6;6063;6071;6079;6132:3;6120:9;6111:7;6107:23;6103:33;6100:53;;;6149:1;6146;6139:12;6100:53;6172:29;6191:9;6172:29;:::i;:::-;6162:39;;6248:2;6237:9;6233:18;6220:32;6210:42;;6299:2;6288:9;6284:18;6271:32;6261:42;;6354:2;6343:9;6339:18;6326:32;-1:-1:-1;;;;;6373:6:43;6370:30;6367:50;;;6413:1;6410;6403:12;6367:50;6436:49;6477:7;6468:6;6457:9;6453:22;6436:49;:::i;6496:1219::-;6614:6;6622;6675:2;6663:9;6654:7;6650:23;6646:32;6643:52;;;6691:1;6688;6681:12;6643:52;6731:9;6718:23;-1:-1:-1;;;;;6801:2:43;6793:6;6790:14;6787:34;;;6817:1;6814;6807:12;6787:34;6855:6;6844:9;6840:22;6830:32;;6900:7;6893:4;6889:2;6885:13;6881:27;6871:55;;6922:1;6919;6912:12;6871:55;6958:2;6945:16;6980:4;7003:43;7043:2;7003:43;:::i;:::-;7075:2;7069:9;7087:31;7115:2;7107:6;7087:31;:::i;:::-;7153:18;;;7187:15;;;;-1:-1:-1;7222:11:43;;;7264:1;7260:10;;;7252:19;;7248:28;;7245:41;-1:-1:-1;7242:61:43;;;7299:1;7296;7289:12;7242:61;7321:1;7312:10;;7331:169;7345:2;7342:1;7339:9;7331:169;;;7402:23;7421:3;7402:23;:::i;:::-;7390:36;;7363:1;7356:9;;;;;7446:12;;;;7478;;7331:169;;;-1:-1:-1;7519:6:43;-1:-1:-1;;7563:18:43;;7550:32;;-1:-1:-1;;7594:16:43;;;7591:36;;;7623:1;7620;7613:12;7591:36;;7646:63;7701:7;7690:8;7679:9;7675:24;7646:63;:::i;:::-;7636:73;;;6496:1219;;;;;:::o;7720:245::-;7787:6;7840:2;7828:9;7819:7;7815:23;7811:32;7808:52;;;7856:1;7853;7846:12;7808:52;7888:9;7882:16;7907:28;7929:5;7907:28;:::i;7970:180::-;8029:6;8082:2;8070:9;8061:7;8057:23;8053:32;8050:52;;;8098:1;8095;8088:12;8050:52;-1:-1:-1;8121:23:43;;7970:180;-1:-1:-1;7970:180:43:o;8155:254::-;8223:6;8231;8284:2;8272:9;8263:7;8259:23;8255:32;8252:52;;;8300:1;8297;8290:12;8252:52;8336:9;8323:23;8313:33;;8365:38;8399:2;8388:9;8384:18;8365:38;:::i;8414:245::-;8472:6;8525:2;8513:9;8504:7;8500:23;8496:32;8493:52;;;8541:1;8538;8531:12;8493:52;8580:9;8567:23;8599:30;8623:5;8599:30;:::i;8664:249::-;8733:6;8786:2;8774:9;8765:7;8761:23;8757:32;8754:52;;;8802:1;8799;8792:12;8754:52;8834:9;8828:16;8853:30;8877:5;8853:30;:::i;8918:592::-;8989:6;8997;9050:2;9038:9;9029:7;9025:23;9021:32;9018:52;;;9066:1;9063;9056:12;9018:52;9106:9;9093:23;-1:-1:-1;;;;;9176:2:43;9168:6;9165:14;9162:34;;;9192:1;9189;9182:12;9162:34;9230:6;9219:9;9215:22;9205:32;;9275:7;9268:4;9264:2;9260:13;9256:27;9246:55;;9297:1;9294;9287:12;9246:55;9337:2;9324:16;9363:2;9355:6;9352:14;9349:34;;;9379:1;9376;9369:12;9349:34;9424:7;9419:2;9410:6;9406:2;9402:15;9398:24;9395:37;9392:57;;;9445:1;9442;9435:12;9392:57;9476:2;9468:11;;;;;9498:6;;-1:-1:-1;8918:592:43;;-1:-1:-1;;;;8918:592:43:o;9700:184::-;9770:6;9823:2;9811:9;9802:7;9798:23;9794:32;9791:52;;;9839:1;9836;9829:12;9791:52;-1:-1:-1;9862:16:43;;9700:184;-1:-1:-1;9700:184:43:o;9889:388::-;9966:6;9974;10027:2;10015:9;10006:7;10002:23;9998:32;9995:52;;;10043:1;10040;10033:12;9995:52;10079:9;10066:23;10056:33;;10140:2;10129:9;10125:18;10112:32;-1:-1:-1;;;;;10159:6:43;10156:30;10153:50;;;10199:1;10196;10189:12;10153:50;10222:49;10263:7;10254:6;10243:9;10239:22;10222:49;:::i;10282:248::-;10350:6;10358;10411:2;10399:9;10390:7;10386:23;10382:32;10379:52;;;10427:1;10424;10417:12;10379:52;-1:-1:-1;;10450:23:43;;;10520:2;10505:18;;;10492:32;;-1:-1:-1;10282:248:43:o;10535:435::-;10588:3;10626:5;10620:12;10653:6;10648:3;10641:19;10679:4;10708:2;10703:3;10699:12;10692:19;;10745:2;10738:5;10734:14;10766:1;10776:169;10790:6;10787:1;10784:13;10776:169;;;10851:13;;10839:26;;10885:12;;;;10920:15;;;;10812:1;10805:9;10776:169;;;-1:-1:-1;10961:3:43;;10535:435;-1:-1:-1;;;;;10535:435:43:o;10975:257::-;11016:3;11054:5;11048:12;11081:6;11076:3;11069:19;11097:63;11153:6;11146:4;11141:3;11137:14;11130:4;11123:5;11119:16;11097:63;:::i;:::-;11214:2;11193:15;-1:-1:-1;;11189:29:43;11180:39;;;;11221:4;11176:50;;10975:257;-1:-1:-1;;10975:257:43:o;11237:274::-;11366:3;11404:6;11398:13;11420:53;11466:6;11461:3;11454:4;11446:6;11442:17;11420:53;:::i;:::-;11489:16;;;;;11237:274;-1:-1:-1;;11237:274:43:o;11726:786::-;12137:25;12132:3;12125:38;12107:3;12192:6;12186:13;12208:62;12263:6;12258:2;12253:3;12249:12;12242:4;12234:6;12230:17;12208:62;:::i;:::-;-1:-1:-1;;;12329:2:43;12289:16;;;12321:11;;;12314:40;12379:13;;12401:63;12379:13;12450:2;12442:11;;12435:4;12423:17;;12401:63;:::i;:::-;12484:17;12503:2;12480:26;;11726:786;-1:-1:-1;;;;11726:786:43:o;12725:826::-;-1:-1:-1;;;;;13122:15:43;;;13104:34;;13174:15;;13169:2;13154:18;;13147:43;13084:3;13221:2;13206:18;;13199:31;;;13047:4;;13253:57;;13290:19;;13282:6;13253:57;:::i;:::-;13358:9;13350:6;13346:22;13341:2;13330:9;13326:18;13319:50;13392:44;13429:6;13421;13392:44;:::i;:::-;13378:58;;13485:9;13477:6;13473:22;13467:3;13456:9;13452:19;13445:51;13513:32;13538:6;13530;13513:32;:::i;:::-;13505:40;12725:826;-1:-1:-1;;;;;;;;12725:826:43:o;13556:560::-;-1:-1:-1;;;;;13853:15:43;;;13835:34;;13905:15;;13900:2;13885:18;;13878:43;13952:2;13937:18;;13930:34;;;13995:2;13980:18;;13973:34;;;13815:3;14038;14023:19;;14016:32;;;13778:4;;14065:45;;14090:19;;14082:6;14065:45;:::i;:::-;14057:53;13556:560;-1:-1:-1;;;;;;;13556:560:43:o;14400:261::-;14579:2;14568:9;14561:21;14542:4;14599:56;14651:2;14640:9;14636:18;14628:6;14599:56;:::i;14666:465::-;14923:2;14912:9;14905:21;14886:4;14949:56;15001:2;14990:9;14986:18;14978:6;14949:56;:::i;:::-;15053:9;15045:6;15041:22;15036:2;15025:9;15021:18;15014:50;15081:44;15118:6;15110;15081:44;:::i;:::-;15073:52;14666:465;-1:-1:-1;;;;;14666:465:43:o;15510:217::-;15657:2;15646:9;15639:21;15620:4;15677:44;15717:2;15706:9;15702:18;15694:6;15677:44;:::i;16738:404::-;16940:2;16922:21;;;16979:2;16959:18;;;16952:30;17018:34;17013:2;16998:18;;16991:62;-1:-1:-1;;;17084:2:43;17069:18;;17062:38;17132:3;17117:19;;16738:404::o;17507:412::-;17709:2;17691:21;;;17748:2;17728:18;;;17721:30;-1:-1:-1;;;;;;;;;;;17782:2:43;17767:18;;17760:62;-1:-1:-1;;;17853:2:43;17838:18;;17831:46;17909:3;17894:19;;17507:412::o;18685:400::-;18887:2;18869:21;;;18926:2;18906:18;;;18899:30;18965:34;18960:2;18945:18;;18938:62;-1:-1:-1;;;19031:2:43;19016:18;;19009:34;19075:3;19060:19;;18685:400::o;19503:405::-;19705:2;19687:21;;;19744:2;19724:18;;;19717:30;19783:34;19778:2;19763:18;;19756:62;-1:-1:-1;;;19849:2:43;19834:18;;19827:39;19898:3;19883:19;;19503:405::o;20998:401::-;21200:2;21182:21;;;21239:2;21219:18;;;21212:30;21278:34;21273:2;21258:18;;21251:62;-1:-1:-1;;;21344:2:43;21329:18;;21322:35;21389:3;21374:19;;20998:401::o;22250:399::-;22452:2;22434:21;;;22491:2;22471:18;;;22464:30;22530:34;22525:2;22510:18;;22503:62;-1:-1:-1;;;22596:2:43;22581:18;;22574:33;22639:3;22624:19;;22250:399::o;22654:420::-;22856:2;22838:21;;;22895:2;22875:18;;;22868:30;-1:-1:-1;;;;;;;;;;;22929:2:43;22914:18;;22907:62;23005:26;23000:2;22985:18;;22978:54;23064:3;23049:19;;22654:420::o;23079:406::-;23281:2;23263:21;;;23320:2;23300:18;;;23293:30;23359:34;23354:2;23339:18;;23332:62;-1:-1:-1;;;23425:2:43;23410:18;;23403:40;23475:3;23460:19;;23079:406::o;26233:404::-;26435:2;26417:21;;;26474:2;26454:18;;;26447:30;26513:34;26508:2;26493:18;;26486:62;-1:-1:-1;;;26579:2:43;26564:18;;26557:38;26627:3;26612:19;;26233:404::o;26642:397::-;26844:2;26826:21;;;26883:2;26863:18;;;26856:30;26922:34;26917:2;26902:18;;26895:62;-1:-1:-1;;;26988:2:43;26973:18;;26966:31;27029:3;27014:19;;26642:397::o;27895:183::-;27955:4;-1:-1:-1;;;;;27980:6:43;27977:30;27974:56;;;28010:18;;:::i;:::-;-1:-1:-1;28055:1:43;28051:14;28067:4;28047:25;;27895:183::o;28083:128::-;28123:3;28154:1;28150:6;28147:1;28144:13;28141:39;;;28160:18;;:::i;:::-;-1:-1:-1;28196:9:43;;28083:128::o;28216:217::-;28256:1;28282;28272:132;;28326:10;28321:3;28317:20;28314:1;28307:31;28361:4;28358:1;28351:15;28389:4;28386:1;28379:15;28272:132;-1:-1:-1;28418:9:43;;28216:217::o;28438:168::-;28478:7;28544:1;28540;28536:6;28532:14;28529:1;28526:21;28521:1;28514:9;28507:17;28503:45;28500:71;;;28551:18;;:::i;:::-;-1:-1:-1;28591:9:43;;28438:168::o;28611:258::-;28683:1;28693:113;28707:6;28704:1;28701:13;28693:113;;;28783:11;;;28777:18;28764:11;;;28757:39;28729:2;28722:10;28693:113;;;28824:6;28821:1;28818:13;28815:48;;;-1:-1:-1;;28859:1:43;28841:16;;28834:27;28611:258::o;28874:136::-;28913:3;28941:5;28931:39;;28950:18;;:::i;:::-;-1:-1:-1;;;28986:18:43;;28874:136::o;29015:380::-;29094:1;29090:12;;;;29137;;;29158:61;;29212:4;29204:6;29200:17;29190:27;;29158:61;29265:2;29257:6;29254:14;29234:18;29231:38;29228:161;;;29311:10;29306:3;29302:20;29299:1;29292:31;29346:4;29343:1;29336:15;29374:4;29371:1;29364:15;29228:161;;29015:380;;;:::o;29400:249::-;29510:2;29491:13;;-1:-1:-1;;29487:27:43;29475:40;;-1:-1:-1;;;;;29530:34:43;;29566:22;;;29527:62;29524:88;;;29592:18;;:::i;:::-;29628:2;29621:22;-1:-1:-1;;29400:249:43:o;29654:135::-;29693:3;-1:-1:-1;;29714:17:43;;29711:43;;;29734:18;;:::i;:::-;-1:-1:-1;29781:1:43;29770:13;;29654:135::o;29794:127::-;29855:10;29850:3;29846:20;29843:1;29836:31;29886:4;29883:1;29876:15;29910:4;29907:1;29900:15;29926:127;29987:10;29982:3;29978:20;29975:1;29968:31;30018:4;30015:1;30008:15;30042:4;30039:1;30032:15;30058:127;30119:10;30114:3;30110:20;30107:1;30100:31;30150:4;30147:1;30140:15;30174:4;30171:1;30164:15;30190:179;30225:3;30267:1;30249:16;30246:23;30243:120;;;30313:1;30310;30307;30292:23;-1:-1:-1;30350:1:43;30344:8;30339:3;30335:18;30243:120;30190:179;:::o;30374:671::-;30413:3;30455:4;30437:16;30434:26;30431:39;;;30374:671;:::o;30431:39::-;30497:2;30491:9;-1:-1:-1;;30562:16:43;30558:25;;30555:1;30491:9;30534:50;30613:4;30607:11;30637:16;-1:-1:-1;;;;;30743:2:43;30736:4;30728:6;30724:17;30721:25;30716:2;30708:6;30705:14;30702:45;30699:58;;;30750:5;;;;;30374:671;:::o;30699:58::-;30787:6;30781:4;30777:17;30766:28;;30823:3;30817:10;30850:2;30842:6;30839:14;30836:27;;;30856:5;;;;;;30374:671;:::o;30836:27::-;30940:2;30921:16;30915:4;30911:27;30907:36;30900:4;30891:6;30886:3;30882:16;30878:27;30875:69;30872:82;;;30947:5;;;;;;30374:671;:::o;30872:82::-;30963:57;31014:4;31005:6;30997;30993:19;30989:30;30983:4;30963:57;:::i;:::-;-1:-1:-1;31036:3:43;;30374:671;-1:-1:-1;;;;;30374:671:43:o;31050:118::-;31136:5;31129:13;31122:21;31115:5;31112:32;31102:60;;31158:1;31155;31148:12;31173:131;-1:-1:-1;;;;;;31247:32:43;;31237:43;;31227:71;;31294:1;31291;31284:12

Metadata Hash

ipfs://a8c9bbcfb8536ce6099f41433f0f109b8b9cf62951d560c7163d5289d9452109
Loading