Token Planck

Overview ERC-721

Total Supply:
90,000 PLK

Holders:
130 addresses

Transfers:
-

Profile Summary

 
Contract:
0x7edbb61ccea2f29e31525d33f310a9ea943c7a890x7EdbB61CcEA2F29e31525d33f310A9ea943C7A89

Loading
[ Download CSV Export  ] 
Loading
[ Download CSV Export  ] 
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
TheSpaceRegistry

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, Apache-2.0 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-05-12
*/

//SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.11;

// OpenZeppelin Contracts v4.4.1 (token/ERC20/ERC20.sol)

// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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 `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, 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 `sender` to `recipient` 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 sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

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

// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.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);
}

// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

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

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

/**
 * @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:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, 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) {
        _approve(_msgSender(), 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:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        uint256 currentAllowance = _allowances[sender][_msgSender()];
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
            unchecked {
                _approve(sender, _msgSender(), currentAllowance - amount);
            }
        }

        _transfer(sender, recipient, 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) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][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) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(_msgSender(), 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:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, 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 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 {}
}

// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)

// OpenZeppelin Contracts v4.4.1 (token/ERC721/ERC721.sol)

// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

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

/**
 * @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`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)

/**
 * @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 `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.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);
}

// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)

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

// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

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

// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.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;
    }
}

/**
 * @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 overriden 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 || getApproved(tokenId) == spender || isApprovedForAll(owner, 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 {}
}

// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Enumerable.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);
}

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

// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

/**
 * @title The interface for `TheSpaceRegistry` contract.
 * @notice Storage contract for `TheSpace` contract.
 * @dev It stores all states related to the market, and is owned by the TheSpace contract.
 * @dev The market contract can be upgraded by changing the owner of this contract to the new implementation contract.
 */
interface ITheSpaceRegistry is IERC721Enumerable {
    //////////////////////////////
    /// Error types
    //////////////////////////////

    /**
     * @notice Token id is out of range.
     * @param min Lower range of possible token id.
     * @param max Higher range of possible token id.
     */
    error InvalidTokenId(uint256 min, uint256 max);

    //////////////////////////////
    /// Event types
    //////////////////////////////

    /**
     * @notice A token updated price.
     * @param tokenId Id of token that updated price.
     * @param price New price after update.
     * @param owner Token owner during price update.
     */
    event Price(uint256 indexed tokenId, uint256 price, address indexed owner);

    /**
     * @notice Global configuration is updated.
     * @param option Field of config been updated.
     * @param value New value after update.
     */
    event Config(ConfigOptions indexed option, uint256 value);

    /**
     * @notice Total is updated.
     * @param previousSupply Total supply amount before update.
     * @param newSupply New supply amount after update.
     */
    event TotalSupply(uint256 previousSupply, uint256 newSupply);

    /**
     * @notice Tax is collected for a token.
     * @param tokenId Id of token that has been taxed.
     * @param taxpayer user address who has paid the tax.
     * @param amount Amount of tax been collected.
     */
    event Tax(uint256 indexed tokenId, address indexed taxpayer, uint256 amount);

    /**
     * @notice UBI (universal basic income) is withdrawn for a token.
     * @param tokenId Id of token that UBI has been withdrawn for.
     * @param recipient user address who got this withdrawn UBI.
     * @param amount Amount of UBI withdrawn.
     */
    event UBI(uint256 indexed tokenId, address indexed recipient, uint256 amount);

    /**
     * @notice Treasury is withdrawn.
     * @param recipient address who got this withdrawn treasury.
     * @param amount Amount of withdrawn.
     */
    event Treasury(address indexed recipient, uint256 amount);

    /**
     * @notice A token has been succefully bid.
     * @param tokenId Id of token that has been bid.
     * @param from Original owner before bid.
     * @param to New owner after bid.
     * @param amount Amount of currency used for bidding.
     */
    event Bid(uint256 indexed tokenId, address indexed from, address indexed to, uint256 amount);

    /**
     * @notice Emitted when the color of a pixel is updated.
     * @param tokenId Id of token that has been bid.
     * @param color Color index defined by client.
     * @param owner Token owner.
     */
    event Color(uint256 indexed tokenId, uint256 indexed color, address indexed owner);

    //////////////////////////////
    /// Data structure
    //////////////////////////////

    /**
     * @notice Options for global tax configuration.
     * @param taxRate: Tax rate in bps every 1000 blocks
     * @param treasuryShare: Share to treasury in bps.
     * @param mintTax: Tax to mint a token. It should be non-zero to prevent attacker constantly mint, default and mint token again.
     */
    enum ConfigOptions {
        taxRate,
        treasuryShare,
        mintTax
    }

    /**
     * @notice Record of each token.
     * @param price Current price.
     * @param lastTaxCollection Block number of last tax collection.
     * @param ubiWithdrawn Amount of UBI been withdrawn.
     */
    struct TokenRecord {
        uint256 price;
        uint256 lastTaxCollection;
        uint256 ubiWithdrawn;
    }

    /**
     * @notice Global state of tax and treasury.
     * @param accumulatedUBI Total amount of currency allocated for UBI.
     * @param accumulatedTreasury Total amount of currency allocated for treasury.
     * @param treasuryWithdrawn Total amount of treasury been withdrawn.
     */
    struct TreasuryRecord {
        uint256 accumulatedUBI;
        uint256 accumulatedTreasury;
        uint256 treasuryWithdrawn;
    }

    /**
     * @dev Packed pixel info.
     */
    struct Pixel {
        uint256 tokenId;
        uint256 price;
        uint256 lastTaxCollection;
        uint256 ubi;
        address owner;
        uint256 color;
    }

    //////////////////////////////
    /// Getters & Setters
    //////////////////////////////

    /**
     * @notice Update total supply of ERC721 token.
     * @param totalSupply_ New amount of total supply.
     */
    function setTotalSupply(uint256 totalSupply_) external;

    /**
     * @notice Update global tax settings.
     * @param option_ Tax config options, see {ConfigOptions} for detail.
     * @param value_ New value for tax setting.
     */
    function setTaxConfig(ConfigOptions option_, uint256 value_) external;

    /**
     * @notice Update UBI and treasury.
     * @param accumulatedUBI_ Total amount of currency allocated for UBI.
     * @param accumulatedTreasury_ Total amount of currency allocated for treasury.
     * @param treasuryWithdrawn_ Total amount of treasury been withdrawn.
     */
    function setTreasuryRecord(
        uint256 accumulatedUBI_,
        uint256 accumulatedTreasury_,
        uint256 treasuryWithdrawn_
    ) external;

    /**
     * @notice Set record for a given token.
     * @param tokenId_ Id of token to be set.
     * @param price_ Current price.
     * @param lastTaxCollection_ Block number of last tax collection.
     * @param ubiWithdrawn_ Amount of UBI been withdrawn.
     */
    function setTokenRecord(
        uint256 tokenId_,
        uint256 price_,
        uint256 lastTaxCollection_,
        uint256 ubiWithdrawn_
    ) external;

    /**
     * @notice Set color for a given token.
     * @param tokenId_ Token id to be set.
     * @param color_ Color Id.
     * @param owner_ Token owner.
     */
    function setColor(
        uint256 tokenId_,
        uint256 color_,
        address owner_
    ) external;

    //////////////////////////////
    /// Event emission
    //////////////////////////////

    /**
     * @dev Emit {Tax} event
     */
    function emitTax(
        uint256 tokenId_,
        address taxpayer_,
        uint256 amount_
    ) external;

    /**
     * @dev Emit {Price} event
     */
    function emitPrice(
        uint256 tokenId_,
        uint256 price_,
        address operator_
    ) external;

    /**
     * @dev Emit {UBI} event
     */
    function emitUBI(
        uint256 tokenId_,
        address recipient_,
        uint256 amount_
    ) external;

    /**
     * @dev Emit {Treasury} event
     */
    function emitTreasury(address recipient_, uint256 amount_) external;

    /**
     * @dev Emit {Bid} event
     */
    function emitBid(
        uint256 tokenId_,
        address from_,
        address to_,
        uint256 amount_
    ) external;

    //////////////////////////////
    /// ERC721 property related
    //////////////////////////////

    /**
     * @dev Mint an ERC721 token.
     */
    function mint(address to_, uint256 tokenId_) external;

    /**
     * @dev Burn an ERC721 token.
     */
    function burn(uint256 tokenId_) external;

    /**
     * @dev Perform ERC721 token transfer by market contract.
     */
    function safeTransferByMarket(
        address from_,
        address to_,
        uint256 tokenId_
    ) external;

    /**
     * @dev If an ERC721 token has been minted.
     */
    function exists(uint256 tokenId_) external view returns (bool);

    /**
     * @dev If an address is allowed to transfer an ERC721 token.
     */
    function isApprovedOrOwner(address spender_, uint256 tokenId_) external view returns (bool);

    //////////////////////////////
    /// ERC20 currency related
    //////////////////////////////

    /**
     * @dev Perform ERC20 token transfer by market contract.
     */
    function transferCurrency(address to_, uint256 amount_) external;

    /**
     * @dev Perform ERC20 token transferFrom by market contract.
     */
    function transferCurrencyFrom(
        address from_,
        address to_,
        uint256 amount_
    ) external;
}

/**
 * @title The interface for `TheSpace` contract
 * @notice _The Space_ is a pixel space owned by a decentralized autonomous organization (DAO), where members can tokenize, own, trade and color pixels.
 *
 * Pixels are tokenized as ERC721 tokens and traded under Harberger tax, while members receive dividend based on the share of pixels they own.
 *
 * #### Trading
 * - User needs to call `approve` on currency contract before starting. If there is not sufficient allowance for taxing, the corresponding assets are defaulted.
 * - User buy pixel: call [`bid` function](./ITheSpace.md).
 * - User set pixel price: call [`setPrice` function](./ITheSpace.md).
 *
 * @dev This contract holds the logic of market place, while read from and write into {TheSpaceRegistry}, which is the storage contact.
 * @dev This contract owns a {TheSpaceRegistry} contract for storage, and can be updated by transfering ownership to a new implementation contract.
 */

interface ITheSpace {
    //////////////////////////////
    /// Error types
    //////////////////////////////

    /**
     * @dev Price too low to bid the given token.
     */
    error PriceTooLow();

    /**
     * @dev Price too high to set.
     */
    error PriceTooHigh(uint256 maxPrice);

    /**
     * @dev Sender is not authorized for given operation.
     */
    error Unauthorized();

    /**
     * @dev The give token does not exist and needs to be minted first via bidding.
     */
    error TokenNotExists();

    //////////////////////////////
    /// Upgradability
    //////////////////////////////

    /**
     * @notice Switch logic contract to another one.
     *
     * @dev Access: only `Role.aclManager`.
     * @dev Throws: `RoleRequired` error.
     *
     * @param newImplementation address of new logic contract.
     */
    function upgradeTo(address newImplementation) external;

    //////////////////////////////
    /// Configuration / Admin
    //////////////////////////////

    /**
     * @notice Update total supply of ERC721 token.
     *
     * @dev Access: only `Role.marketAdmin`.
     * @dev Throws: `RoleRequired` error.
     *
     * @param totalSupply_ New amount of total supply.
     */
    function setTotalSupply(uint256 totalSupply_) external;

    /**
     * @notice Update current tax configuration.
     *
     * @dev Access: only `Role.marketAdmin`.
     * @dev Emits: `Config` event.
     * @dev Throws: `RoleRequired` error.
     *
     * @param option_ Field of config been updated.
     * @param value_ New value after update.
     */
    function setTaxConfig(ITheSpaceRegistry.ConfigOptions option_, uint256 value_) external;

    /**
     * @notice Withdraw all available treasury.
     *
     * @dev Access: only `Role.treasuryAdmin`.
     * @dev Throws: `RoleRequired` error.
     *
     * @param to address of DAO treasury.
     */
    function withdrawTreasury(address to) external;

    //////////////////////////////
    /// Pixel
    //////////////////////////////

    /**
     * @notice Get pixel info.
     * @param tokenId_ Token id to be queried.
     * @return pixel Packed pixel info.
     */
    function getPixel(uint256 tokenId_) external view returns (ITheSpaceRegistry.Pixel memory pixel);

    /**
     * @notice Bid pixel, then set price and color.
     *
     * @dev Throws: inherits from `bid` and `setPrice`.
     *
     * @param tokenId_ Token id to be bid and set.
     * @param bidPrice_ Bid price.
     * @param newPrice_ New price to be set.
     * @param color_ Color to be set.
     */
    function setPixel(
        uint256 tokenId_,
        uint256 bidPrice_,
        uint256 newPrice_,
        uint256 color_
    ) external;

    /**
     * @notice Set color for a pixel.
     *
     * @dev Access: only token owner or approved operator.
     * @dev Throws: `Unauthorized` or `ERC721: operator query for nonexistent token` error.
     * @dev Emits: `Color` event.
     *
     * @param tokenId_ Token id to be set.
     * @param color_ Color to be set.
     */
    function setColor(uint256 tokenId_, uint256 color_) external;

    /**
     * @notice Get color for a pixel.
     * @param tokenId_ Token id to be queried.
     * @return color Color.
     */
    function getColor(uint256 tokenId_) external view returns (uint256 color);

    /**
     * @notice Get pixels owned by a given address.
     * @param owner_ Owner address.
     * @param limit_ Limit of returned pixels.
     * @param offset_ Offset of returned pixels.
     * @return total Total number of pixels.
     * @return limit Limit of returned pixels.
     * @return offset Offset of returned pixels.
     * @return pixels Packed pixels.
     * @dev offset-based pagination
     */
    function getPixelsByOwner(
        address owner_,
        uint256 limit_,
        uint256 offset_
    )
        external
        view
        returns (
            uint256 total,
            uint256 limit,
            uint256 offset,
            ITheSpaceRegistry.Pixel[] memory pixels
        );

    //////////////////////////////
    /// Trading
    //////////////////////////////

    /**
     * @notice Returns the current price of a token by id.
     * @param tokenId_ Token id to be queried.
     * @return price Current price.
     */
    function getPrice(uint256 tokenId_) external view returns (uint256 price);

    /**
     * @notice Set the current price of a token with id. Triggers tax settle first, price is succefully updated after tax is successfully collected.
     *
     * @dev Access: only token owner or approved operator.
     * @dev Throws: `Unauthorized` or `ERC721: operator query for nonexistent token` error.
     * @dev Emits: `Price` event.
     *
     * @param tokenId_ Id of token been updated.
     * @param price_ New price to be updated.
     */
    function setPrice(uint256 tokenId_, uint256 price_) external;

    /**
     * @notice Returns the current owner of an Harberger property with token id.
     * @dev If token does not exisit, return zero address and user can bid the token as usual.
     * @param tokenId_ Token id to be queried.
     * @return owner Current owner address.
     */
    function getOwner(uint256 tokenId_) external view returns (address owner);

    /**
     * @notice Purchase property with bid higher than current price.
     * If bid price is higher than ask price, only ask price will be deducted.
     * @dev Clear tax for owner before transfer.
     *
     * @dev Throws: `PriceTooLow` or `InvalidTokenId` error.
     * @dev Emits: `Bid`, `Tax` events.
     *
     * @param tokenId_ Id of token been bid.
     * @param price_ Bid price.
     */
    function bid(uint256 tokenId_, uint256 price_) external;

    //////////////////////////////
    /// Tax & UBI
    //////////////////////////////

    /**
     * @notice Calculate outstanding tax for a token.
     * @param tokenId_ Token id to be queried.
     * @return amount Current amount of tax that needs to be paid.
     */
    function getTax(uint256 tokenId_) external view returns (uint256 amount);

    /**
     * @notice Calculate amount of tax that can be collected, and determine if token should be defaulted.
     * @param tokenId_ Token id to be queried.
     * @return collectable Amount of currency that can be collected, considering balance and allowance.
     * @return shouldDefault Whether current token should be defaulted.
     */
    function evaluateOwnership(uint256 tokenId_) external view returns (uint256 collectable, bool shouldDefault);

    /**
     * @notice Collect outstanding tax of a token and default it if needed.
     * @dev Anyone can trigger this function. It could be desirable for the developer team to trigger it once a while to make sure all tokens meet their tax obligation.
     *
     * @dev Throws: `PriceTooLow` or `InvalidTokenId` error.
     * @dev Emits: `Bid`, `Tax` events.
     *
     * @param tokenId_ Id of token been settled.
     * @return success Whether tax is fully collected without token been defaulted.
     */
    function settleTax(uint256 tokenId_) external returns (bool success);

    /**
     * @notice Amount of UBI available for withdraw on given token.
     * @param tokenId_ Token id to be queried.
     * @param amount Amount of UBI available to be collected
     */
    function ubiAvailable(uint256 tokenId_) external view returns (uint256 amount);

    /**
     * @notice Withdraw all UBI on given token.
     *
     * @dev Emits: `UBI` event.
     *
     * @param tokenId_ Id of token been withdrawn.
     */
    function withdrawUbi(uint256 tokenId_) external;

    //////////////////////////////
    /// Registry backcall
    //////////////////////////////

    /**
     * @notice Perform before `safeTransfer` and `safeTransferFrom` by registry contract.
     * @dev Collect tax and set price.
     *
     * @dev Access: only registry.
     * @dev Throws: `Unauthorized` error.
     *
     * @param tokenId_ Token id to be transferred.
     * @return success Whether tax is fully collected without token been defaulted.
     */
    function beforeTransferByRegistry(uint256 tokenId_) external returns (bool success);
}

contract TheSpaceRegistry is ITheSpaceRegistry, ERC721Enumerable, Ownable {
    /**
     * @dev Total possible number of ERC721 token
     */
    uint256 private _totalSupply;

    /**
     * @dev ERC20 token used as currency
     */
    ERC20 public immutable currency;

    /**
     * @dev Record for all tokens (tokenId => TokenRecord).
     */
    mapping(uint256 => TokenRecord) public tokenRecord;

    /**
     * @dev Color of each token.
     */
    mapping(uint256 => uint256) public pixelColor;

    /**
     * @dev Tax configuration of market.
     */
    mapping(ConfigOptions => uint256) public taxConfig;

    /**
     * @dev Global state of tax and treasury.
     */
    TreasuryRecord public treasuryRecord;

    /**
     * @dev Create Property contract, setup attached currency contract, setup tax rate.
     */
    constructor(
        string memory propertyName_,
        string memory propertySymbol_,
        uint256 totalSupply_,
        uint256 taxRate_,
        uint256 treasuryShare_,
        uint256 mintTax_,
        address currencyAddress_
    ) ERC721(propertyName_, propertySymbol_) {
        // initialize total supply
        _totalSupply = totalSupply_;

        // initialize currency contract
        currency = ERC20(currencyAddress_);

        // initialize tax config
        taxConfig[ConfigOptions.taxRate] = taxRate_;
        emit Config(ConfigOptions.taxRate, taxRate_);
        taxConfig[ConfigOptions.treasuryShare] = treasuryShare_;
        emit Config(ConfigOptions.treasuryShare, treasuryShare_);
        taxConfig[ConfigOptions.mintTax] = mintTax_;
        emit Config(ConfigOptions.mintTax, mintTax_);
    }

    //////////////////////////////
    /// Getters & Setters
    //////////////////////////////

    /**
     * @notice See {IERC20-totalSupply}.
     * @dev Always return total possible amount of supply, instead of current token in circulation.
     */
    function totalSupply() public view override(ERC721Enumerable, IERC721Enumerable) returns (uint256) {
        return _totalSupply;
    }

    //////////////////////////////
    /// Setters for global variables
    //////////////////////////////

    /// @inheritdoc ITheSpaceRegistry
    function setTotalSupply(uint256 totalSupply_) external onlyOwner {
        emit TotalSupply(_totalSupply, totalSupply_);

        _totalSupply = totalSupply_;
    }

    /// @inheritdoc ITheSpaceRegistry
    function setTaxConfig(ConfigOptions option_, uint256 value_) external onlyOwner {
        taxConfig[option_] = value_;

        emit Config(option_, value_);
    }

    /// @inheritdoc ITheSpaceRegistry
    function setTreasuryRecord(
        uint256 accumulatedUBI_,
        uint256 accumulatedTreasury_,
        uint256 treasuryWithdrawn_
    ) external onlyOwner {
        treasuryRecord = TreasuryRecord(accumulatedUBI_, accumulatedTreasury_, treasuryWithdrawn_);
    }

    /// @inheritdoc ITheSpaceRegistry
    function setTokenRecord(
        uint256 tokenId_,
        uint256 price_,
        uint256 lastTaxCollection_,
        uint256 ubiWithdrawn_
    ) external onlyOwner {
        tokenRecord[tokenId_] = TokenRecord(price_, lastTaxCollection_, ubiWithdrawn_);
    }

    /// @inheritdoc ITheSpaceRegistry
    function setColor(
        uint256 tokenId_,
        uint256 color_,
        address owner_
    ) external onlyOwner {
        pixelColor[tokenId_] = color_;
        emit Color(tokenId_, color_, owner_);
    }

    //////////////////////////////
    /// Event emission
    //////////////////////////////

    /// @inheritdoc ITheSpaceRegistry
    function emitTax(
        uint256 tokenId_,
        address taxpayer_,
        uint256 amount_
    ) external onlyOwner {
        emit Tax(tokenId_, taxpayer_, amount_);
    }

    /// @inheritdoc ITheSpaceRegistry
    function emitPrice(
        uint256 tokenId_,
        uint256 price_,
        address operator_
    ) external onlyOwner {
        emit Price(tokenId_, price_, operator_);
    }

    /// @inheritdoc ITheSpaceRegistry
    function emitUBI(
        uint256 tokenId_,
        address recipient_,
        uint256 amount_
    ) external onlyOwner {
        emit UBI(tokenId_, recipient_, amount_);
    }

    /// @inheritdoc ITheSpaceRegistry
    function emitTreasury(address recipient_, uint256 amount_) external onlyOwner {
        emit Treasury(recipient_, amount_);
    }

    /// @inheritdoc ITheSpaceRegistry
    function emitBid(
        uint256 tokenId_,
        address from_,
        address to_,
        uint256 amount_
    ) external onlyOwner {
        emit Bid(tokenId_, from_, to_, amount_);
    }

    //////////////////////////////
    /// ERC721 property related
    //////////////////////////////

    /// @inheritdoc ITheSpaceRegistry
    function mint(address to_, uint256 tokenId_) external onlyOwner {
        if (tokenId_ > _totalSupply || tokenId_ < 1) revert InvalidTokenId(1, _totalSupply);
        _safeMint(to_, tokenId_);
    }

    /// @inheritdoc ITheSpaceRegistry
    function burn(uint256 tokenId_) external onlyOwner {
        _burn(tokenId_);
    }

    /// @inheritdoc ITheSpaceRegistry
    function safeTransferByMarket(
        address from_,
        address to_,
        uint256 tokenId_
    ) external onlyOwner {
        _safeTransfer(from_, to_, tokenId_, "");
    }

    /// @inheritdoc ITheSpaceRegistry
    function exists(uint256 tokenId_) external view returns (bool) {
        return _exists(tokenId_);
    }

    /// @inheritdoc ITheSpaceRegistry
    function isApprovedOrOwner(address spender_, uint256 tokenId_) external view returns (bool) {
        return _isApprovedOrOwner(spender_, tokenId_);
    }

    /**
     * @notice See {IERC721-transferFrom}.
     * @dev Override to collect tax and set price before transfer.
     */
    function transferFrom(
        address from_,
        address to_,
        uint256 tokenId_
    ) public override(ERC721, IERC721) {
        safeTransferFrom(from_, to_, tokenId_, "");
    }

    /**
     * @notice See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from_,
        address to_,
        uint256 tokenId_,
        bytes memory data_
    ) public override(ERC721, IERC721) {
        // solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(msg.sender, tokenId_), "ERC721: transfer caller is not owner nor approved");

        ITheSpace market = ITheSpace(owner());

        bool success = market.beforeTransferByRegistry(tokenId_);

        if (success) {
            _safeTransfer(from_, to_, tokenId_, data_);
        }
    }

    //////////////////////////////
    /// ERC20 currency related
    //////////////////////////////

    /// @inheritdoc ITheSpaceRegistry
    function transferCurrency(address to_, uint256 amount_) external onlyOwner {
        currency.transfer(to_, amount_);
    }

    /// @inheritdoc ITheSpaceRegistry
    function transferCurrencyFrom(
        address from_,
        address to_,
        uint256 amount_
    ) external onlyOwner {
        currency.transferFrom(from_, to_, amount_);
    }
}

Contract ABI

[{"inputs":[{"internalType":"string","name":"propertyName_","type":"string"},{"internalType":"string","name":"propertySymbol_","type":"string"},{"internalType":"uint256","name":"totalSupply_","type":"uint256"},{"internalType":"uint256","name":"taxRate_","type":"uint256"},{"internalType":"uint256","name":"treasuryShare_","type":"uint256"},{"internalType":"uint256","name":"mintTax_","type":"uint256"},{"internalType":"address","name":"currencyAddress_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"InvalidTokenId","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","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":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Bid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"color","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"Color","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum ITheSpaceRegistry.ConfigOptions","name":"option","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Config","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"Price","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"taxpayer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Tax","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previousSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSupply","type":"uint256"}],"name":"TotalSupply","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Treasury","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UBI","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currency","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"emitBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"price_","type":"uint256"},{"internalType":"address","name":"operator_","type":"address"}],"name":"emitPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"taxpayer_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"emitTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"emitTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"emitUBI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"isApprovedOrOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pixelColor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"safeTransferByMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","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":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"color_","type":"uint256"},{"internalType":"address","name":"owner_","type":"address"}],"name":"setColor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ITheSpaceRegistry.ConfigOptions","name":"option_","type":"uint8"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"setTaxConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"price_","type":"uint256"},{"internalType":"uint256","name":"lastTaxCollection_","type":"uint256"},{"internalType":"uint256","name":"ubiWithdrawn_","type":"uint256"}],"name":"setTokenRecord","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"totalSupply_","type":"uint256"}],"name":"setTotalSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"accumulatedUBI_","type":"uint256"},{"internalType":"uint256","name":"accumulatedTreasury_","type":"uint256"},{"internalType":"uint256","name":"treasuryWithdrawn_","type":"uint256"}],"name":"setTreasuryRecord","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":"enum ITheSpaceRegistry.ConfigOptions","name":"","type":"uint8"}],"name":"taxConfig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenRecord","outputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"lastTaxCollection","type":"uint256"},{"internalType":"uint256","name":"ubiWithdrawn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"transferCurrency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"transferCurrencyFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasuryRecord","outputs":[{"internalType":"uint256","name":"accumulatedUBI","type":"uint256"},{"internalType":"uint256","name":"accumulatedTreasury","type":"uint256"},{"internalType":"uint256","name":"treasuryWithdrawn","type":"uint256"}],"stateMutability":"view","type":"function"}]

60a06040523480156200001157600080fd5b5060405162002ae038038062002ae0833981016040819052620000349162000365565b8651879087906200004d906000906020850190620001f2565b50805162000063906001906020840190620001f2565b505050620000806200007a6200019c60201b60201c565b620001a0565b600b8590556001600160a01b0381166080526000808052600e60209081527fe710864318d4a32f37d6ce54cb3fadbef648dd12d8dbdf53973564d56b7f881c86905560408051878152905160008051602062002ac0833981519152929181900390910190a260016000819052600e60209081527fa7c5ba7114a813b50159add3a36832908dc83db71d0b9a24c2ad0f83be95820785905560408051868152905160008051602062002ac0833981519152929181900390910190a260026000819052600e60209081527f9adb202b1492743bc00c81d33cdc6423fa8c79109027eb6a845391e8fc1f048184905560408051858152905160008051602062002ac0833981519152929181900390910190a25050505050505062000452565b3390565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b828054620002009062000416565b90600052602060002090601f0160209004810192826200022457600085556200026f565b82601f106200023f57805160ff19168380011785556200026f565b828001600101855582156200026f579182015b828111156200026f57825182559160200191906001019062000252565b506200027d92915062000281565b5090565b5b808211156200027d576000815560010162000282565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620002c057600080fd5b81516001600160401b0380821115620002dd57620002dd62000298565b604051601f8301601f19908116603f0116810190828211818310171562000308576200030862000298565b816040528381526020925086838588010111156200032557600080fd5b600091505b838210156200034957858201830151818301840152908201906200032a565b838211156200035b5760008385830101525b9695505050505050565b600080600080600080600060e0888a0312156200038157600080fd5b87516001600160401b03808211156200039957600080fd5b620003a78b838c01620002ae565b985060208a0151915080821115620003be57600080fd5b50620003cd8a828b01620002ae565b96505060408801519450606088015193506080880151925060a0880151915060c088015160018060a01b03811681146200040657600080fd5b8091505092959891949750929550565b600181811c908216806200042b57607f821691505b6020821081036200044c57634e487b7160e01b600052602260045260246000fd5b50919050565b6080516126446200047c6000396000818161053d01528181610e6d015261128101526126446000f3fe608060405234801561001057600080fd5b50600436106102525760003560e01c80635850088411610146578063b3e4ee22116100c3578063e5a6b10f11610087578063e5a6b10f14610538578063e7d6fbbf1461055f578063e985e9c51461057f578063ecaf822a146105bb578063f2fde38b146105ce578063f7ea7a3d146105e157600080fd5b8063b3e4ee22146104d9578063b88d4fde146104ec578063c87b56dd146104ff578063d17d14c514610512578063e3759abd1461052557600080fd5b806376a91e6c1161010a57806376a91e6c146104875780638da5cb5b1461049a57806395d89b41146104ab578063a22cb465146104b3578063a5e59fb2146104c657600080fd5b806358500884146104175780635d4744041461042a5780636352211e1461045957806370a082311461046c578063715018a61461047f57600080fd5b80632f745c59116101d45780634d7c7dc7116101985780634d7c7dc71461039e5780634f558e79146103cb5780634f6ccce7146103de5780635701e25d146103f1578063583d42481461040457600080fd5b80632f745c591461035257806340c10f191461036557806342842e0e1461032c57806342966c6814610378578063430c20811461038b57600080fd5b80631164da761161021b5780631164da76146102e757806318160ddd146102fa5780631d8d0f481461030c57806323b872dd1461032c5780632b2163b31461033f57600080fd5b80627f57501461025757806301ffc9a71461026c57806306fdde0314610294578063081812fc146102a9578063095ea7b3146102d4575b600080fd5b61026a610265366004611fe5565b6105f4565b005b61027f61027a36600461203f565b61067b565b60405190151581526020015b60405180910390f35b61029c6106a6565b60405161028b91906120b4565b6102bc6102b73660046120c7565b610738565b6040516001600160a01b03909116815260200161028b565b61026a6102e23660046120e0565b6107cd565b61026a6102f536600461210a565b6108e2565b600b545b60405190815260200161028b565b6102fe61031a3660046120c7565b600d6020526000908152604090205481565b61026a61033a36600461213f565b610955565b61026a61034d36600461210a565b610970565b6102fe6103603660046120e0565b6109d6565b61026a6103733660046120e0565b610a6c565b61026a6103863660046120c7565b610ae0565b61027f6103993660046120e0565b610b16565b600f546010546011546103b092919083565b6040805193845260208401929092529082015260600161028b565b61027f6103d93660046120c7565b610b29565b6102fe6103ec3660046120c7565b610b48565b61026a6103ff3660046120e0565b610bdb565b61026a61041236600461216b565b610c4c565b61026a61042536600461213f565b610c9c565b6103b06104383660046120c7565b600c6020526000908152604090208054600182015460029092015490919083565b6102bc6104673660046120c7565b610ce1565b6102fe61047a366004612197565b610d58565b61026a610ddf565b61026a61049536600461213f565b610e15565b600a546001600160a01b03166102bc565b61029c610ee0565b61026a6104c13660046121c0565b610eef565b61026a6104d43660046121f7565b610efa565b61026a6104e736600461222c565b610f6e565b61026a6104fa366004612274565b610fd3565b61029c61050d3660046120c7565b6110e4565b61026a6105203660046121f7565b6111cb565b61026a6105333660046120e0565b611231565b6102bc7f000000000000000000000000000000000000000000000000000000000000000081565b6102fe61056d36600461235f565b600e6020526000908152604090205481565b61027f61058d36600461237a565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61026a6105c93660046123ad565b6112ee565b61026a6105dc366004612197565b611393565b61026a6105ef3660046120c7565b61142b565b600a546001600160a01b031633146106275760405162461bcd60e51b815260040161061e906123c9565b60405180910390fd5b816001600160a01b0316836001600160a01b0316857ff828f9266a867e728bd505090b4db2d33e1935c90d43a9fe0a6906eaf30bc48b8460405161066d91815260200190565b60405180910390a450505050565b60006001600160e01b0319821663780e9d6360e01b14806106a057506106a082611496565b92915050565b6060600080546106b5906123fe565b80601f01602080910402602001604051908101604052809291908181526020018280546106e1906123fe565b801561072e5780601f106107035761010080835404028352916020019161072e565b820191906000526020600020905b81548152906001019060200180831161071157829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166107b15760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b606482015260840161061e565b506000908152600460205260409020546001600160a01b031690565b60006107d882610ce1565b9050806001600160a01b0316836001600160a01b0316036108455760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b606482015260840161061e565b336001600160a01b03821614806108615750610861813361058d565b6108d35760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606482015260840161061e565b6108dd83836114e6565b505050565b600a546001600160a01b0316331461090c5760405162461bcd60e51b815260040161061e906123c9565b816001600160a01b0316837fa760fe80056c46d089c37a35d9dbe762141a463ae0eb8235522d27ab9595286d8360405161094891815260200190565b60405180910390a3505050565b6108dd83838360405180602001604052806000815250610fd3565b600a546001600160a01b0316331461099a5760405162461bcd60e51b815260040161061e906123c9565b816001600160a01b0316837fc5790222911f43ca7d78c4f5ef5cb5a21d7fda4d923d433b80e7db9c295de88a8360405161094891815260200190565b60006109e183610d58565b8210610a435760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b606482015260840161061e565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b600a546001600160a01b03163314610a965760405162461bcd60e51b815260040161061e906123c9565b600b54811180610aa65750600181105b15610ad257600b5460405163168a450960e21b815260016004820152602481019190915260440161061e565b610adc8282611554565b5050565b600a546001600160a01b03163314610b0a5760405162461bcd60e51b815260040161061e906123c9565b610b138161156e565b50565b6000610b228383611615565b9392505050565b6000818152600260205260408120546001600160a01b031615156106a0565b6000610b5360085490565b8210610bb65760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b606482015260840161061e565b60088281548110610bc957610bc9612438565b90600052602060002001549050919050565b600a546001600160a01b03163314610c055760405162461bcd60e51b815260040161061e906123c9565b816001600160a01b03167f782743bed566521eb169ba5186430a0e29079bfd1bdf4fc061bd63b48729846682604051610c4091815260200190565b60405180910390a25050565b600a546001600160a01b03163314610c765760405162461bcd60e51b815260040161061e906123c9565b604080516060810182528481526020810184905201819052600f92909255601055601155565b600a546001600160a01b03163314610cc65760405162461bcd60e51b815260040161061e906123c9565b6108dd8383836040518060200160405280600081525061170c565b6000818152600260205260408120546001600160a01b0316806106a05760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b606482015260840161061e565b60006001600160a01b038216610dc35760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b606482015260840161061e565b506001600160a01b031660009081526003602052604090205490565b600a546001600160a01b03163314610e095760405162461bcd60e51b815260040161061e906123c9565b610e13600061173f565b565b600a546001600160a01b03163314610e3f5760405162461bcd60e51b815260040161061e906123c9565b6040516323b872dd60e01b81526001600160a01b0384811660048301528381166024830152604482018390527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af1158015610eb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eda919061244e565b50505050565b6060600180546106b5906123fe565b610adc338383611791565b600a546001600160a01b03163314610f245760405162461bcd60e51b815260040161061e906123c9565b6000838152600d6020526040808220849055516001600160a01b03831691849186917f8da7074ffa2c919782faaf9705c7edfe7f814551a91b91aed83ee2ef5ac6af2791a4505050565b600a546001600160a01b03163314610f985760405162461bcd60e51b815260040161061e906123c9565b6040805160608101825293845260208085019384528482019283526000958652600c9052909320915182555160018201559051600290910155565b610fdd3383611615565b6110435760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6044820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606482015260840161061e565b6000611057600a546001600160a01b031690565b60405163700bee4360e11b8152600481018590529091506000906001600160a01b0383169063e017dc86906024016020604051808303816000875af11580156110a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c8919061244e565b905080156110dc576110dc8686868661170c565b505050505050565b6000818152600260205260409020546060906001600160a01b03166111635760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b606482015260840161061e565b600061117a60408051602081019091526000815290565b9050600081511161119a5760405180602001604052806000815250610b22565b806111a484611857565b6040516020016111b592919061246b565b6040516020818303038152906040529392505050565b600a546001600160a01b031633146111f55760405162461bcd60e51b815260040161061e906123c9565b806001600160a01b0316837f75a0543aefc16d03b25751bdf0b5a2fbbec05c6436fd60b038d40f5b7d1def838460405161094891815260200190565b600a546001600160a01b0316331461125b5760405162461bcd60e51b815260040161061e906123c9565b60405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156112ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108dd919061244e565b600a546001600160a01b031633146113185760405162461bcd60e51b815260040161061e906123c9565b80600e600084600281111561132f5761132f61249a565b60028111156113405761134061249a565b81526020810191909152604001600020558160028111156113635761136361249a565b6040518281527f90e64b63a2c952a97e60fcb9bdb464e5e76d2920683504331028687f0cd6643b90602001610c40565b600a546001600160a01b031633146113bd5760405162461bcd60e51b815260040161061e906123c9565b6001600160a01b0381166114225760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161061e565b610b138161173f565b600a546001600160a01b031633146114555760405162461bcd60e51b815260040161061e906123c9565b600b5460408051918252602082018390527fce065be89501ad8aef77e0eb0160264c2d1eb1732a004bcb98735bb0b8102205910160405180910390a1600b55565b60006001600160e01b031982166380ac58cd60e01b14806114c757506001600160e01b03198216635b5e139f60e01b145b806106a057506301ffc9a760e01b6001600160e01b03198316146106a0565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061151b82610ce1565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b610adc828260405180602001604052806000815250611958565b600061157982610ce1565b90506115878160008461198b565b6115926000836114e6565b6001600160a01b03811660009081526003602052604081208054600192906115bb9084906124c6565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000818152600260205260408120546001600160a01b031661168e5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b606482015260840161061e565b600061169983610ce1565b9050806001600160a01b0316846001600160a01b031614806116d45750836001600160a01b03166116c984610738565b6001600160a01b0316145b8061170457506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b611717848484611a43565b61172384848484611bea565b610eda5760405162461bcd60e51b815260040161061e906124dd565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316036117f25760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161061e565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101610948565b60608160000361187e5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156118a857806118928161252f565b91506118a19050600a8361255e565b9150611882565b60008167ffffffffffffffff8111156118c3576118c361225e565b6040519080825280601f01601f1916602001820160405280156118ed576020820181803683370190505b5090505b8415611704576119026001836124c6565b915061190f600a86612572565b61191a906030612586565b60f81b81838151811061192f5761192f612438565b60200101906001600160f81b031916908160001a905350611951600a8661255e565b94506118f1565b6119628383611ceb565b61196f6000848484611bea565b6108dd5760405162461bcd60e51b815260040161061e906124dd565b6001600160a01b0383166119e6576119e181600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b611a09565b816001600160a01b0316836001600160a01b031614611a0957611a098382611e39565b6001600160a01b038216611a20576108dd81611ed6565b826001600160a01b0316826001600160a01b0316146108dd576108dd8282611f85565b826001600160a01b0316611a5682610ce1565b6001600160a01b031614611aba5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b606482015260840161061e565b6001600160a01b038216611b1c5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161061e565b611b2783838361198b565b611b326000826114e6565b6001600160a01b0383166000908152600360205260408120805460019290611b5b9084906124c6565b90915550506001600160a01b0382166000908152600360205260408120805460019290611b89908490612586565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60006001600160a01b0384163b15611ce057604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290611c2e90339089908890889060040161259e565b6020604051808303816000875af1925050508015611c69575060408051601f3d908101601f19168201909252611c66918101906125db565b60015b611cc6573d808015611c97576040519150601f19603f3d011682016040523d82523d6000602084013e611c9c565b606091505b508051600003611cbe5760405162461bcd60e51b815260040161061e906124dd565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611704565b506001949350505050565b6001600160a01b038216611d415760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161061e565b6000818152600260205260409020546001600160a01b031615611da65760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161061e565b611db26000838361198b565b6001600160a01b0382166000908152600360205260408120805460019290611ddb908490612586565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001611e4684610d58565b611e5091906124c6565b600083815260076020526040902054909150808214611ea3576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611ee8906001906124c6565b60008381526009602052604081205460088054939450909284908110611f1057611f10612438565b906000526020600020015490508060088381548110611f3157611f31612438565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611f6957611f696125f8565b6001900381819060005260206000200160009055905550505050565b6000611f9083610d58565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b80356001600160a01b0381168114611fe057600080fd5b919050565b60008060008060808587031215611ffb57600080fd5b8435935061200b60208601611fc9565b925061201960408601611fc9565b9396929550929360600135925050565b6001600160e01b031981168114610b1357600080fd5b60006020828403121561205157600080fd5b8135610b2281612029565b60005b8381101561207757818101518382015260200161205f565b83811115610eda5750506000910152565b600081518084526120a081602086016020860161205c565b601f01601f19169290920160200192915050565b602081526000610b226020830184612088565b6000602082840312156120d957600080fd5b5035919050565b600080604083850312156120f357600080fd5b6120fc83611fc9565b946020939093013593505050565b60008060006060848603121561211f57600080fd5b8335925061212f60208501611fc9565b9150604084013590509250925092565b60008060006060848603121561215457600080fd5b61215d84611fc9565b925061212f60208501611fc9565b60008060006060848603121561218057600080fd5b505081359360208301359350604090920135919050565b6000602082840312156121a957600080fd5b610b2282611fc9565b8015158114610b1357600080fd5b600080604083850312156121d357600080fd5b6121dc83611fc9565b915060208301356121ec816121b2565b809150509250929050565b60008060006060848603121561220c57600080fd5b833592506020840135915061222360408501611fc9565b90509250925092565b6000806000806080858703121561224257600080fd5b5050823594602084013594506040840135936060013592509050565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561228a57600080fd5b61229385611fc9565b93506122a160208601611fc9565b925060408501359150606085013567ffffffffffffffff808211156122c557600080fd5b818701915087601f8301126122d957600080fd5b8135818111156122eb576122eb61225e565b604051601f8201601f19908116603f011681019083821181831017156123135761231361225e565b816040528281528a602084870101111561232c57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b803560038110611fe057600080fd5b60006020828403121561237157600080fd5b610b2282612350565b6000806040838503121561238d57600080fd5b61239683611fc9565b91506123a460208401611fc9565b90509250929050565b600080604083850312156123c057600080fd5b6120fc83612350565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600181811c9082168061241257607f821691505b60208210810361243257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561246057600080fd5b8151610b22816121b2565b6000835161247d81846020880161205c565b83519083019061249181836020880161205c565b01949350505050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000828210156124d8576124d86124b0565b500390565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b600060018201612541576125416124b0565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261256d5761256d612548565b500490565b60008261258157612581612548565b500690565b60008219821115612599576125996124b0565b500190565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906125d190830184612088565b9695505050505050565b6000602082840312156125ed57600080fd5b8151610b2281612029565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220e3cc4adf28603d304dd258ff9cb919e7f7ee0564a5ffd84872be969455e9a15864736f6c634300080d003390e64b63a2c952a97e60fcb9bdb464e5e76d2920683504331028687f0cd6643b00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000000000000000000000000000000000000000004b00000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000eb6814043dc2184b0b321f6de995bf11bdbcc5b80000000000000000000000000000000000000000000000000000000000000006506c616e636b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003504c4b0000000000000000000000000000000000000000000000000000000000

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

00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000000000000000000000000000000000000000004b00000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000eb6814043dc2184b0b321f6de995bf11bdbcc5b80000000000000000000000000000000000000000000000000000000000000006506c616e636b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003504c4b0000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : propertyName_ (string): Planck
Arg [1] : propertySymbol_ (string): PLK
Arg [2] : totalSupply_ (uint256): 1000000
Arg [3] : taxRate_ (uint256): 75
Arg [4] : treasuryShare_ (uint256): 500
Arg [5] : mintTax_ (uint256): 1000000000000000000
Arg [6] : currencyAddress_ (address): 0xeb6814043dc2184b0b321f6de995bf11bdbcc5b8

-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [2] : 00000000000000000000000000000000000000000000000000000000000f4240
Arg [3] : 000000000000000000000000000000000000000000000000000000000000004b
Arg [4] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [5] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [6] : 000000000000000000000000eb6814043dc2184b0b321f6de995bf11bdbcc5b8
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [8] : 506c616e636b0000000000000000000000000000000000000000000000000000
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [10] : 504c4b0000000000000000000000000000000000000000000000000000000000


Deployed ByteCode Sourcemap

78219:7327:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82788:200;;;;;;:::i;:::-;;:::i;:::-;;51529:224;;;;;;:::i;:::-;;:::i;:::-;;;1145:14:1;;1138:22;1120:41;;1108:2;1093:18;51529:224:0;;;;;;;;37594:100;;;:::i;:::-;;;;;;;:::i;39153:221::-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;2272:32:1;;;2254:51;;2242:2;2227:18;39153:221:0;2108:203:1;38676:411:0;;;;;;:::i;:::-;;:::i;82380:183::-;;;;;;:::i;:::-;;:::i;80202:137::-;80319:12;;80202:137;;;3048:25:1;;;3036:2;3021:18;80202:137:0;2902:177:1;78696:45:0;;;;;;:::i;:::-;;;;;;;;;;;;;;84203:196;;;;;;:::i;:::-;;:::i;81922:181::-;;;;;;:::i;:::-;;:::i;51837:256::-;;;;;;:::i;:::-;;:::i;83142:201::-;;;;;;:::i;:::-;;:::i;83390:85::-;;;;;;:::i;:::-;;:::i;83909:156::-;;;;;;:::i;:::-;;:::i;78934:36::-;;;;;;;;;;;;;;;;;3619:25:1;;;3675:2;3660:18;;3653:34;;;;3703:18;;;3696:34;3607:2;3592:18;78934:36:0;3417:319:1;83756:106:0;;;;;;:::i;:::-;;:::i;52359:233::-;;;;;;:::i;:::-;;:::i;82610:131::-;;;;;;:::i;:::-;;:::i;80927:272::-;;;;;;:::i;:::-;;:::i;83522:187::-;;;;;;:::i;:::-;;:::i;78585:50::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;37288:239;;;;;;:::i;:::-;;:::i;37018:208::-;;;;;;:::i;:::-;;:::i;59304:103::-;;;:::i;85354:189::-;;;;;;:::i;:::-;;:::i;58653:87::-;58726:6;;-1:-1:-1;;;;;58726:6:0;58653:87;;37763:104;;;:::i;39446:155::-;;;;;;:::i;:::-;;:::i;81561:216::-;;;;;;:::i;:::-;;:::i;81246:268::-;;;;;;:::i;:::-;;:::i;84473:556::-;;;;;;:::i;:::-;;:::i;37938:334::-;;;;;;:::i;:::-;;:::i;82150:183::-;;;;;;:::i;:::-;;:::i;85182:125::-;;;;;;:::i;:::-;;:::i;78466:31::-;;;;;78810:50;;;;;;:::i;:::-;;;;;;;;;;;;;;39672:164;;;;;;:::i;:::-;-1:-1:-1;;;;;39793:25:0;;;39769:4;39793:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;39672:164;80713:167;;;;;;:::i;:::-;;:::i;59562:201::-;;;;;;:::i;:::-;;:::i;80498:168::-;;;;;;:::i;:::-;;:::i;82788:200::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;;;;;;;;;82967:3:::1;-1:-1:-1::0;;;;;82946:34:0::1;82960:5;-1:-1:-1::0;;;;;82946:34:0::1;82950:8;82946:34;82972:7;82946:34;;;;3048:25:1::0;;3036:2;3021:18;;2902:177;82946:34:0::1;;;;;;;;82788:200:::0;;;;:::o;51529:224::-;51631:4;-1:-1:-1;;;;;;51655:50:0;;-1:-1:-1;;;51655:50:0;;:90;;;51709:36;51733:11;51709:23;:36::i;:::-;51648:97;51529:224;-1:-1:-1;;51529:224:0:o;37594:100::-;37648:13;37681:5;37674:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37594:100;:::o;39153:221::-;39229:7;42496:16;;;:7;:16;;;;;;-1:-1:-1;;;;;42496:16:0;39249:73;;;;-1:-1:-1;;;39249:73:0;;8789:2:1;39249:73:0;;;8771:21:1;8828:2;8808:18;;;8801:30;8867:34;8847:18;;;8840:62;-1:-1:-1;;;8918:18:1;;;8911:42;8970:19;;39249:73:0;8587:408:1;39249:73:0;-1:-1:-1;39342:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;39342:24:0;;39153:221::o;38676:411::-;38757:13;38773:23;38788:7;38773:14;:23::i;:::-;38757:39;;38821:5;-1:-1:-1;;;;;38815:11:0;:2;-1:-1:-1;;;;;38815:11:0;;38807:57;;;;-1:-1:-1;;;38807:57:0;;9202:2:1;38807:57:0;;;9184:21:1;9241:2;9221:18;;;9214:30;9280:34;9260:18;;;9253:62;-1:-1:-1;;;9331:18:1;;;9324:31;9372:19;;38807:57:0;9000:397:1;38807:57:0;4237:10;-1:-1:-1;;;;;38899:21:0;;;;:62;;-1:-1:-1;38924:37:0;38941:5;4237:10;39672:164;:::i;38924:37::-;38877:168;;;;-1:-1:-1;;;38877:168:0;;9604:2:1;38877:168:0;;;9586:21:1;9643:2;9623:18;;;9616:30;9682:34;9662:18;;;9655:62;9753:26;9733:18;;;9726:54;9797:19;;38877:168:0;9402:420:1;38877:168:0;39058:21;39067:2;39071:7;39058:8;:21::i;:::-;38746:341;38676:411;;:::o;82380:183::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;82535:10:::1;-1:-1:-1::0;;;;;82521:34:0::1;82525:8;82521:34;82547:7;82521:34;;;;3048:25:1::0;;3036:2;3021:18;;2902:177;82521:34:0::1;;;;;;;;82380:183:::0;;;:::o;84203:196::-;84349:42;84366:5;84373:3;84378:8;84349:42;;;;;;;;;;;;:16;:42::i;81922:181::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;82076:9:::1;-1:-1:-1::0;;;;;82062:33:0::1;82066:8;82062:33;82087:7;82062:33;;;;3048:25:1::0;;3036:2;3021:18;;2902:177;51837:256:0;51934:7;51970:23;51987:5;51970:16;:23::i;:::-;51962:5;:31;51954:87;;;;-1:-1:-1;;;51954:87:0;;10029:2:1;51954:87:0;;;10011:21:1;10068:2;10048:18;;;10041:30;10107:34;10087:18;;;10080:62;-1:-1:-1;;;10158:18:1;;;10151:41;10209:19;;51954:87:0;9827:407:1;51954:87:0;-1:-1:-1;;;;;;52059:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;51837:256::o;83142:201::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;83232:12:::1;;83221:8;:23;:39;;;;83259:1;83248:8;:12;83221:39;83217:83;;;83287:12;::::0;83269:31:::1;::::0;-1:-1:-1;;;83269:31:0;;83284:1:::1;83269:31;::::0;::::1;10421:25:1::0;10462:18;;;10455:34;;;;10394:18;;83269:31:0::1;10239:256:1::0;83217:83:0::1;83311:24;83321:3;83326:8;83311:9;:24::i;:::-;83142:201:::0;;:::o;83390:85::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;83452:15:::1;83458:8;83452:5;:15::i;:::-;83390:85:::0;:::o;83909:156::-;83995:4;84019:38;84038:8;84048;84019:18;:38::i;:::-;84012:45;83909:156;-1:-1:-1;;;83909:156:0:o;83756:106::-;83813:4;42496:16;;;:7;:16;;;;;;-1:-1:-1;;;;;42496:16:0;:30;;83837:17;42407:127;52359:233;52434:7;52470:30;52257:10;:17;;52169:113;52470:30;52462:5;:38;52454:95;;;;-1:-1:-1;;;52454:95:0;;10702:2:1;52454:95:0;;;10684:21:1;10741:2;10721:18;;;10714:30;10780:34;10760:18;;;10753:62;-1:-1:-1;;;10831:18:1;;;10824:42;10883:19;;52454:95:0;10500:408:1;52454:95:0;52567:10;52578:5;52567:17;;;;;;;;:::i;:::-;;;;;;;;;52560:24;;52359:233;;;:::o;82610:131::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;82713:10:::1;-1:-1:-1::0;;;;;82704:29:0::1;;82725:7;82704:29;;;;3048:25:1::0;;3036:2;3021:18;;2902:177;82704:29:0::1;;;;;;;;82610:131:::0;;:::o;80927:272::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;81118:73:::1;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;;;81101:14:::1;:90:::0;;;;;;;;80927:272::o;83522:187::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;83662:39:::1;83676:5;83683:3;83688:8;83662:39;;;;;;;;;;;::::0;:13:::1;:39::i;37288:239::-:0;37360:7;37396:16;;;:7;:16;;;;;;-1:-1:-1;;;;;37396:16:0;;37423:73;;;;-1:-1:-1;;;37423:73:0;;11247:2:1;37423:73:0;;;11229:21:1;11286:2;11266:18;;;11259:30;11325:34;11305:18;;;11298:62;-1:-1:-1;;;11376:18:1;;;11369:39;11425:19;;37423:73:0;11045:405:1;37018:208:0;37090:7;-1:-1:-1;;;;;37118:19:0;;37110:74;;;;-1:-1:-1;;;37110:74:0;;11657:2:1;37110:74:0;;;11639:21:1;11696:2;11676:18;;;11669:30;11735:34;11715:18;;;11708:62;-1:-1:-1;;;11786:18:1;;;11779:40;11836:19;;37110:74:0;11455:406:1;37110:74:0;-1:-1:-1;;;;;;37202:16:0;;;;;:9;:16;;;;;;;37018:208::o;59304:103::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;59369:30:::1;59396:1;59369:18;:30::i;:::-;59304:103::o:0;85354:189::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;85493:42:::1;::::0;-1:-1:-1;;;85493:42:0;;-1:-1:-1;;;;;12124:15:1;;;85493:42:0::1;::::0;::::1;12106:34:1::0;12176:15;;;12156:18;;;12149:43;12208:18;;;12201:34;;;85493:8:0::1;:21;::::0;::::1;::::0;12041:18:1;;85493:42:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;85354:189:::0;;;:::o;37763:104::-;37819:13;37852:7;37845:14;;;;;:::i;39446:155::-;39541:52;4237:10;39574:8;39584;39541:18;:52::i;81561:216::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;81693:20:::1;::::0;;;:10:::1;:20;::::0;;;;;:29;;;81738:31;-1:-1:-1;;;;;81738:31:0;::::1;::::0;81716:6;;81704:8;;81738:31:::1;::::0;::::1;81561:216:::0;;;:::o;81246:268::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;81452:54:::1;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;;;;;;;;;-1:-1:-1;81428:21:0;;;:11:::1;:21:::0;;;;;:78;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;81246:268::o;84473:556::-;84714:40;84733:10;84745:8;84714:18;:40::i;:::-;84706:102;;;;-1:-1:-1;;;84706:102:0;;12698:2:1;84706:102:0;;;12680:21:1;12737:2;12717:18;;;12710:30;12776:34;12756:18;;;12749:62;-1:-1:-1;;;12827:18:1;;;12820:47;12884:19;;84706:102:0;12496:413:1;84706:102:0;84821:16;84850:7;58726:6;;-1:-1:-1;;;;;58726:6:0;;58653:87;84850:7;84886:41;;-1:-1:-1;;;84886:41:0;;;;;3048:25:1;;;84821:37:0;;-1:-1:-1;84871:12:0;;-1:-1:-1;;;;;84886:31:0;;;;;3021:18:1;;84886:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;84871:56;;84944:7;84940:82;;;84968:42;84982:5;84989:3;84994:8;85004:5;84968:13;:42::i;:::-;84641:388;;84473:556;;;;:::o;37938:334::-;42472:4;42496:16;;;:7;:16;;;;;;38011:13;;-1:-1:-1;;;;;42496:16:0;38037:76;;;;-1:-1:-1;;;38037:76:0;;13116:2:1;38037:76:0;;;13098:21:1;13155:2;13135:18;;;13128:30;13194:34;13174:18;;;13167:62;-1:-1:-1;;;13245:18:1;;;13238:45;13300:19;;38037:76:0;12914:411:1;38037:76:0;38126:21;38150:10;38597:9;;;;;;;;;-1:-1:-1;38597:9:0;;;38520:94;38150:10;38126:34;;38202:1;38184:7;38178:21;:25;:86;;;;;;;;;;;;;;;;;38230:7;38239:18;:7;:16;:18::i;:::-;38213:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;38171:93;37938:334;-1:-1:-1;;;37938:334:0:o;82150:183::-;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;82315:9:::1;-1:-1:-1::0;;;;;82291:34:0::1;82297:8;82291:34;82307:6;82291:34;;;;3048:25:1::0;;3036:2;3021:18;;2902:177;85182:125:0;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;85268:31:::1;::::0;-1:-1:-1;;;85268:31:0;;-1:-1:-1;;;;;13997:32:1;;;85268:31:0::1;::::0;::::1;13979:51:1::0;14046:18;;;14039:34;;;85268:8:0::1;:17;::::0;::::1;::::0;13952:18:1;;85268:31:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;80713:167::-:0;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;80825:6:::1;80804:9;:18;80814:7;80804:18;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;80804:18:0;:27;80856:7;80849:23:::1;::::0;::::1;;;;;;:::i;:::-;;::::0;3048:25:1;;;80849:23:0::1;::::0;3036:2:1;3021:18;80849:23:0::1;2902:177:1::0;59562:201:0;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;59651:22:0;::::1;59643:73;;;::::0;-1:-1:-1;;;59643:73:0;;14418:2:1;59643:73:0::1;::::0;::::1;14400:21:1::0;14457:2;14437:18;;;14430:30;14496:34;14476:18;;;14469:62;-1:-1:-1;;;14547:18:1;;;14540:36;14593:19;;59643:73:0::1;14216:402:1::0;59643:73:0::1;59727:28;59746:8;59727:18;:28::i;80498:168::-:0;58726:6;;-1:-1:-1;;;;;58726:6:0;4237:10;58873:23;58865:68;;;;-1:-1:-1;;;58865:68:0;;;;;;;:::i;:::-;80591:12:::1;::::0;80579:39:::1;::::0;;10421:25:1;;;10477:2;10462:18;;10455:34;;;80579:39:0::1;::::0;10394:18:1;80579:39:0::1;;;;;;;80631:12;:27:::0;80498:168::o;36649:305::-;36751:4;-1:-1:-1;;;;;;36788:40:0;;-1:-1:-1;;;36788:40:0;;:105;;-1:-1:-1;;;;;;;36845:48:0;;-1:-1:-1;;;36845:48:0;36788:105;:158;;;-1:-1:-1;;;;;;;;;;35367:40:0;;;36910:36;35258:157;46553:174;46628:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;46628:29:0;-1:-1:-1;;;;;46628:29:0;;;;;;;;:24;;46682:23;46628:24;46682:14;:23::i;:::-;-1:-1:-1;;;;;46673:46:0;;;;;;;;;;;46553:174;;:::o;43391:110::-;43467:26;43477:2;43481:7;43467:26;;;;;;;;;;;;:9;:26::i;45053:420::-;45113:13;45129:23;45144:7;45129:14;:23::i;:::-;45113:39;;45165:48;45186:5;45201:1;45205:7;45165:20;:48::i;:::-;45254:29;45271:1;45275:7;45254:8;:29::i;:::-;-1:-1:-1;;;;;45296:16:0;;;;;;:9;:16;;;;;:21;;45316:1;;45296:16;:21;;45316:1;;45296:21;:::i;:::-;;;;-1:-1:-1;;45335:16:0;;;;:7;:16;;;;;;45328:23;;-1:-1:-1;;;;;;45328:23:0;;;45369:36;45343:7;;45335:16;-1:-1:-1;;;;;45369:36:0;;;;;45335:16;;45369:36;83142:201;;:::o;42701:348::-;42794:4;42496:16;;;:7;:16;;;;;;-1:-1:-1;;;;;42496:16:0;42811:73;;;;-1:-1:-1;;;42811:73:0;;15340:2:1;42811:73:0;;;15322:21:1;15379:2;15359:18;;;15352:30;15418:34;15398:18;;;15391:62;-1:-1:-1;;;15469:18:1;;;15462:42;15521:19;;42811:73:0;15138:408:1;42811:73:0;42895:13;42911:23;42926:7;42911:14;:23::i;:::-;42895:39;;42964:5;-1:-1:-1;;;;;42953:16:0;:7;-1:-1:-1;;;;;42953:16:0;;:51;;;;42997:7;-1:-1:-1;;;;;42973:31:0;:20;42985:7;42973:11;:20::i;:::-;-1:-1:-1;;;;;42973:31:0;;42953:51;:87;;;-1:-1:-1;;;;;;39793:25:0;;;39769:4;39793:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;43008:32;42945:96;42701:348;-1:-1:-1;;;;42701:348:0:o;41779:315::-;41936:28;41946:4;41952:2;41956:7;41936:9;:28::i;:::-;41983:48;42006:4;42012:2;42016:7;42025:5;41983:22;:48::i;:::-;41975:111;;;;-1:-1:-1;;;41975:111:0;;;;;;;:::i;59923:191::-;60016:6;;;-1:-1:-1;;;;;60033:17:0;;;-1:-1:-1;;;;;;60033:17:0;;;;;;;60066:40;;60016:6;;;60033:17;60016:6;;60066:40;;59997:16;;60066:40;59986:128;59923:191;:::o;46869:315::-;47024:8;-1:-1:-1;;;;;47015:17:0;:5;-1:-1:-1;;;;;47015:17:0;;47007:55;;;;-1:-1:-1;;;47007:55:0;;16172:2:1;47007:55:0;;;16154:21:1;16211:2;16191:18;;;16184:30;16250:27;16230:18;;;16223:55;16295:18;;47007:55:0;15970:349:1;47007:55:0;-1:-1:-1;;;;;47073:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;47073:46:0;;;;;;;;;;47135:41;;1120::1;;;47135::0;;1093:18:1;47135:41:0;980:187:1;32732:723:0;32788:13;33009:5;33018:1;33009:10;33005:53;;-1:-1:-1;;33036:10:0;;;;;;;;;;;;-1:-1:-1;;;33036:10:0;;;;;32732:723::o;33005:53::-;33083:5;33068:12;33124:78;33131:9;;33124:78;;33157:8;;;;:::i;:::-;;-1:-1:-1;33180:10:0;;-1:-1:-1;33188:2:0;33180:10;;:::i;:::-;;;33124:78;;;33212:19;33244:6;33234:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33234:17:0;;33212:39;;33262:154;33269:10;;33262:154;;33296:11;33306:1;33296:11;;:::i;:::-;;-1:-1:-1;33365:10:0;33373:2;33365:5;:10;:::i;:::-;33352:24;;:2;:24;:::i;:::-;33339:39;;33322:6;33329;33322:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;33322:56:0;;;;;;;;-1:-1:-1;33393:11:0;33402:2;33393:11;;:::i;:::-;;;33262:154;;43728:321;43858:18;43864:2;43868:7;43858:5;:18::i;:::-;43909:54;43940:1;43944:2;43948:7;43957:5;43909:22;:54::i;:::-;43887:154;;;;-1:-1:-1;;;43887:154:0;;;;;;;:::i;53205:589::-;-1:-1:-1;;;;;53411:18:0;;53407:187;;53446:40;53478:7;54621:10;:17;;54594:24;;;;:15;:24;;;;;:44;;;54649:24;;;;;;;;;;;;54517:164;53446:40;53407:187;;;53516:2;-1:-1:-1;;;;;53508:10:0;:4;-1:-1:-1;;;;;53508:10:0;;53504:90;;53535:47;53568:4;53574:7;53535:32;:47::i;:::-;-1:-1:-1;;;;;53608:16:0;;53604:183;;53641:45;53678:7;53641:36;:45::i;53604:183::-;53714:4;-1:-1:-1;;;;;53708:10:0;:2;-1:-1:-1;;;;;53708:10:0;;53704:83;;53735:40;53763:2;53767:7;53735:27;:40::i;45810:625::-;45969:4;-1:-1:-1;;;;;45942:31:0;:23;45957:7;45942:14;:23::i;:::-;-1:-1:-1;;;;;45942:31:0;;45934:81;;;;-1:-1:-1;;;45934:81:0;;17173:2:1;45934:81:0;;;17155:21:1;17212:2;17192:18;;;17185:30;17251:34;17231:18;;;17224:62;-1:-1:-1;;;17302:18:1;;;17295:35;17347:19;;45934:81:0;16971:401:1;45934:81:0;-1:-1:-1;;;;;46034:16:0;;46026:65;;;;-1:-1:-1;;;46026:65:0;;17579:2:1;46026:65:0;;;17561:21:1;17618:2;17598:18;;;17591:30;17657:34;17637:18;;;17630:62;-1:-1:-1;;;17708:18:1;;;17701:34;17752:19;;46026:65:0;17377:400:1;46026:65:0;46104:39;46125:4;46131:2;46135:7;46104:20;:39::i;:::-;46208:29;46225:1;46229:7;46208:8;:29::i;:::-;-1:-1:-1;;;;;46250:15:0;;;;;;:9;:15;;;;;:20;;46269:1;;46250:15;:20;;46269:1;;46250:20;:::i;:::-;;;;-1:-1:-1;;;;;;;46281:13:0;;;;;;:9;:13;;;;;:18;;46298:1;;46281:13;:18;;46298:1;;46281:18;:::i;:::-;;;;-1:-1:-1;;46310:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;46310:21:0;-1:-1:-1;;;;;46310:21:0;;;;;;;;;46349:27;;46310:16;;46349:27;;;;;;;38746:341;38676:411;;:::o;47749:799::-;47904:4;-1:-1:-1;;;;;47925:13:0;;25475:19;:23;47921:620;;47961:72;;-1:-1:-1;;;47961:72:0;;-1:-1:-1;;;;;47961:36:0;;;;;:72;;4237:10;;48012:4;;48018:7;;48027:5;;47961:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;47961:72:0;;;;;;;;-1:-1:-1;;47961:72:0;;;;;;;;;;;;:::i;:::-;;;47957:529;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48203:6;:13;48220:1;48203:18;48199:272;;48246:60;;-1:-1:-1;;;48246:60:0;;;;;;;:::i;48199:272::-;48421:6;48415:13;48406:6;48402:2;48398:15;48391:38;47957:529;-1:-1:-1;;;;;;48084:51:0;-1:-1:-1;;;48084:51:0;;-1:-1:-1;48077:58:0;;47921:620;-1:-1:-1;48525:4:0;47749:799;;;;;;:::o;44385:439::-;-1:-1:-1;;;;;44465:16:0;;44457:61;;;;-1:-1:-1;;;44457:61:0;;18732:2:1;44457:61:0;;;18714:21:1;;;18751:18;;;18744:30;18810:34;18790:18;;;18783:62;18862:18;;44457:61:0;18530:356:1;44457:61:0;42472:4;42496:16;;;:7;:16;;;;;;-1:-1:-1;;;;;42496:16:0;:30;44529:58;;;;-1:-1:-1;;;44529:58:0;;19093:2:1;44529:58:0;;;19075:21:1;19132:2;19112:18;;;19105:30;19171;19151:18;;;19144:58;19219:18;;44529:58:0;18891:352:1;44529:58:0;44600:45;44629:1;44633:2;44637:7;44600:20;:45::i;:::-;-1:-1:-1;;;;;44658:13:0;;;;;;:9;:13;;;;;:18;;44675:1;;44658:13;:18;;44675:1;;44658:18;:::i;:::-;;;;-1:-1:-1;;44687:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;44687:21:0;-1:-1:-1;;;;;44687:21:0;;;;;;;;44726:33;;44687:16;;;44726:33;;44687:16;;44726:33;83142:201;;:::o;55308:988::-;55574:22;55624:1;55599:22;55616:4;55599:16;:22::i;:::-;:26;;;;:::i;:::-;55636:18;55657:26;;;:17;:26;;;;;;55574:51;;-1:-1:-1;55790:28:0;;;55786:328;;-1:-1:-1;;;;;55857:18:0;;55835:19;55857:18;;;:12;:18;;;;;;;;:34;;;;;;;;;55908:30;;;;;;:44;;;56025:30;;:17;:30;;;;;:43;;;55786:328;-1:-1:-1;56210:26:0;;;;:17;:26;;;;;;;;56203:33;;;-1:-1:-1;;;;;56254:18:0;;;;;:12;:18;;;;;:34;;;;;;;56247:41;55308:988::o;56591:1079::-;56869:10;:17;56844:22;;56869:21;;56889:1;;56869:21;:::i;:::-;56901:18;56922:24;;;:15;:24;;;;;;57295:10;:26;;56844:46;;-1:-1:-1;56922:24:0;;56844:46;;57295:26;;;;;;:::i;:::-;;;;;;;;;57273:48;;57359:11;57334:10;57345;57334:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;57439:28;;;:15;:28;;;;;;;:41;;;57611:24;;;;;57604:31;57646:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;56662:1008;;;56591:1079;:::o;54095:221::-;54180:14;54197:20;54214:2;54197:16;:20::i;:::-;-1:-1:-1;;;;;54228:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;54273:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;54095:221:0:o;14:173:1:-;82:20;;-1:-1:-1;;;;;131:31:1;;121:42;;111:70;;177:1;174;167:12;111:70;14:173;;;:::o;192:397::-;278:6;286;294;302;355:3;343:9;334:7;330:23;326:33;323:53;;;372:1;369;362:12;323:53;408:9;395:23;385:33;;437:38;471:2;460:9;456:18;437:38;:::i;:::-;427:48;;494:38;528:2;517:9;513:18;494:38;:::i;:::-;192:397;;;;-1:-1:-1;484:48:1;;579:2;564:18;551:32;;-1:-1:-1;;192:397:1:o;594:131::-;-1:-1:-1;;;;;;668:32:1;;658:43;;648:71;;715:1;712;705:12;730:245;788:6;841:2;829:9;820:7;816:23;812:32;809:52;;;857:1;854;847:12;809:52;896:9;883:23;915:30;939:5;915:30;:::i;1172:258::-;1244:1;1254:113;1268:6;1265:1;1262:13;1254:113;;;1344:11;;;1338:18;1325:11;;;1318:39;1290:2;1283:10;1254:113;;;1385:6;1382:1;1379:13;1376:48;;;-1:-1:-1;;1420:1:1;1402:16;;1395:27;1172:258::o;1435:::-;1477:3;1515:5;1509:12;1542:6;1537:3;1530:19;1558:63;1614:6;1607:4;1602:3;1598:14;1591:4;1584:5;1580:16;1558:63;:::i;:::-;1675:2;1654:15;-1:-1:-1;;1650:29:1;1641:39;;;;1682:4;1637:50;;1435:258;-1:-1:-1;;1435:258:1:o;1698:220::-;1847:2;1836:9;1829:21;1810:4;1867:45;1908:2;1897:9;1893:18;1885:6;1867:45;:::i;1923:180::-;1982:6;2035:2;2023:9;2014:7;2010:23;2006:32;2003:52;;;2051:1;2048;2041:12;2003:52;-1:-1:-1;2074:23:1;;1923:180;-1:-1:-1;1923:180:1:o;2316:254::-;2384:6;2392;2445:2;2433:9;2424:7;2420:23;2416:32;2413:52;;;2461:1;2458;2451:12;2413:52;2484:29;2503:9;2484:29;:::i;:::-;2474:39;2560:2;2545:18;;;;2532:32;;-1:-1:-1;;;2316:254:1:o;2575:322::-;2652:6;2660;2668;2721:2;2709:9;2700:7;2696:23;2692:32;2689:52;;;2737:1;2734;2727:12;2689:52;2773:9;2760:23;2750:33;;2802:38;2836:2;2825:9;2821:18;2802:38;:::i;:::-;2792:48;;2887:2;2876:9;2872:18;2859:32;2849:42;;2575:322;;;;;:::o;3084:328::-;3161:6;3169;3177;3230:2;3218:9;3209:7;3205:23;3201:32;3198:52;;;3246:1;3243;3236:12;3198:52;3269:29;3288:9;3269:29;:::i;:::-;3259:39;;3317:38;3351:2;3340:9;3336:18;3317:38;:::i;3741:316::-;3818:6;3826;3834;3887:2;3875:9;3866:7;3862:23;3858:32;3855:52;;;3903:1;3900;3893:12;3855:52;-1:-1:-1;;3926:23:1;;;3996:2;3981:18;;3968:32;;-1:-1:-1;4047:2:1;4032:18;;;4019:32;;3741:316;-1:-1:-1;3741:316:1:o;4062:186::-;4121:6;4174:2;4162:9;4153:7;4149:23;4145:32;4142:52;;;4190:1;4187;4180:12;4142:52;4213:29;4232:9;4213:29;:::i;4253:118::-;4339:5;4332:13;4325:21;4318:5;4315:32;4305:60;;4361:1;4358;4351:12;4376:315;4441:6;4449;4502:2;4490:9;4481:7;4477:23;4473:32;4470:52;;;4518:1;4515;4508:12;4470:52;4541:29;4560:9;4541:29;:::i;:::-;4531:39;;4620:2;4609:9;4605:18;4592:32;4633:28;4655:5;4633:28;:::i;:::-;4680:5;4670:15;;;4376:315;;;;;:::o;4696:322::-;4773:6;4781;4789;4842:2;4830:9;4821:7;4817:23;4813:32;4810:52;;;4858:1;4855;4848:12;4810:52;4894:9;4881:23;4871:33;;4951:2;4940:9;4936:18;4923:32;4913:42;;4974:38;5008:2;4997:9;4993:18;4974:38;:::i;:::-;4964:48;;4696:322;;;;;:::o;5023:385::-;5109:6;5117;5125;5133;5186:3;5174:9;5165:7;5161:23;5157:33;5154:53;;;5203:1;5200;5193:12;5154:53;-1:-1:-1;;5226:23:1;;;5296:2;5281:18;;5268:32;;-1:-1:-1;5347:2:1;5332:18;;5319:32;;5398:2;5383:18;5370:32;;-1:-1:-1;5023:385:1;-1:-1:-1;5023:385:1:o;5413:127::-;5474:10;5469:3;5465:20;5462:1;5455:31;5505:4;5502:1;5495:15;5529:4;5526:1;5519:15;5545:1138;5640:6;5648;5656;5664;5717:3;5705:9;5696:7;5692:23;5688:33;5685:53;;;5734:1;5731;5724:12;5685:53;5757:29;5776:9;5757:29;:::i;:::-;5747:39;;5805:38;5839:2;5828:9;5824:18;5805:38;:::i;:::-;5795:48;;5890:2;5879:9;5875:18;5862:32;5852:42;;5945:2;5934:9;5930:18;5917:32;5968:18;6009:2;6001:6;5998:14;5995:34;;;6025:1;6022;6015:12;5995:34;6063:6;6052:9;6048:22;6038:32;;6108:7;6101:4;6097:2;6093:13;6089:27;6079:55;;6130:1;6127;6120:12;6079:55;6166:2;6153:16;6188:2;6184;6181:10;6178:36;;;6194:18;;:::i;:::-;6269:2;6263:9;6237:2;6323:13;;-1:-1:-1;;6319:22:1;;;6343:2;6315:31;6311:40;6299:53;;;6367:18;;;6387:22;;;6364:46;6361:72;;;6413:18;;:::i;:::-;6453:10;6449:2;6442:22;6488:2;6480:6;6473:18;6528:7;6523:2;6518;6514;6510:11;6506:20;6503:33;6500:53;;;6549:1;6546;6539:12;6500:53;6605:2;6600;6596;6592:11;6587:2;6579:6;6575:15;6562:46;6650:1;6645:2;6640;6632:6;6628:15;6624:24;6617:35;6671:6;6661:16;;;;;;;5545:1138;;;;;;;:::o;6909:154::-;6988:20;;7037:1;7027:12;;7017:40;;7053:1;7050;7043:12;7068:215;7145:6;7198:2;7186:9;7177:7;7173:23;7169:32;7166:52;;;7214:1;7211;7204:12;7166:52;7237:40;7267:9;7237:40;:::i;7288:260::-;7356:6;7364;7417:2;7405:9;7396:7;7392:23;7388:32;7385:52;;;7433:1;7430;7423:12;7385:52;7456:29;7475:9;7456:29;:::i;:::-;7446:39;;7504:38;7538:2;7527:9;7523:18;7504:38;:::i;:::-;7494:48;;7288:260;;;;;:::o;7553:283::-;7639:6;7647;7700:2;7688:9;7679:7;7675:23;7671:32;7668:52;;;7716:1;7713;7706:12;7668:52;7739:40;7769:9;7739:40;:::i;7841:356::-;8043:2;8025:21;;;8062:18;;;8055:30;8121:34;8116:2;8101:18;;8094:62;8188:2;8173:18;;7841:356::o;8202:380::-;8281:1;8277:12;;;;8324;;;8345:61;;8399:4;8391:6;8387:17;8377:27;;8345:61;8452:2;8444:6;8441:14;8421:18;8418:38;8415:161;;8498:10;8493:3;8489:20;8486:1;8479:31;8533:4;8530:1;8523:15;8561:4;8558:1;8551:15;8415:161;;8202:380;;;:::o;10913:127::-;10974:10;10969:3;10965:20;10962:1;10955:31;11005:4;11002:1;10995:15;11029:4;11026:1;11019:15;12246:245;12313:6;12366:2;12354:9;12345:7;12341:23;12337:32;12334:52;;;12382:1;12379;12372:12;12334:52;12414:9;12408:16;12433:28;12455:5;12433:28;:::i;13330:470::-;13509:3;13547:6;13541:13;13563:53;13609:6;13604:3;13597:4;13589:6;13585:17;13563:53;:::i;:::-;13679:13;;13638:16;;;;13701:57;13679:13;13638:16;13735:4;13723:17;;13701:57;:::i;:::-;13774:20;;13330:470;-1:-1:-1;;;;13330:470:1:o;14084:127::-;14145:10;14140:3;14136:20;14133:1;14126:31;14176:4;14173:1;14166:15;14200:4;14197:1;14190:15;14876:127;14937:10;14932:3;14928:20;14925:1;14918:31;14968:4;14965:1;14958:15;14992:4;14989:1;14982:15;15008:125;15048:4;15076:1;15073;15070:8;15067:34;;;15081:18;;:::i;:::-;-1:-1:-1;15118:9:1;;15008:125::o;15551:414::-;15753:2;15735:21;;;15792:2;15772:18;;;15765:30;15831:34;15826:2;15811:18;;15804:62;-1:-1:-1;;;15897:2:1;15882:18;;15875:48;15955:3;15940:19;;15551:414::o;16324:135::-;16363:3;16384:17;;;16381:43;;16404:18;;:::i;:::-;-1:-1:-1;16451:1:1;16440:13;;16324:135::o;16464:127::-;16525:10;16520:3;16516:20;16513:1;16506:31;16556:4;16553:1;16546:15;16580:4;16577:1;16570:15;16596:120;16636:1;16662;16652:35;;16667:18;;:::i;:::-;-1:-1:-1;16701:9:1;;16596:120::o;16721:112::-;16753:1;16779;16769:35;;16784:18;;:::i;:::-;-1:-1:-1;16818:9:1;;16721:112::o;16838:128::-;16878:3;16909:1;16905:6;16902:1;16899:13;16896:39;;;16915:18;;:::i;:::-;-1:-1:-1;16951:9:1;;16838:128::o;17782:489::-;-1:-1:-1;;;;;18051:15:1;;;18033:34;;18103:15;;18098:2;18083:18;;18076:43;18150:2;18135:18;;18128:34;;;18198:3;18193:2;18178:18;;18171:31;;;17976:4;;18219:46;;18245:19;;18237:6;18219:46;:::i;:::-;18211:54;17782:489;-1:-1:-1;;;;;;17782:489:1:o;18276:249::-;18345:6;18398:2;18386:9;18377:7;18373:23;18369:32;18366:52;;;18414:1;18411;18404:12;18366:52;18446:9;18440:16;18465:30;18489:5;18465:30;:::i;19248:127::-;19309:10;19304:3;19300:20;19297:1;19290:31;19340:4;19337:1;19330:15;19364:4;19361:1;19354:15

Swarm Source

ipfs://e3cc4adf28603d304dd258ff9cb919e7f7ee0564a5ffd84872be969455e9a158
Loading