ETH Price: $3,005.61 (+2.43%)

Contract

0x26fFb53E87EC52f02EE3AAFB57126cBB623C59e9

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Cancel371702452026-01-28 13:35:552 hrs ago1769607355IN
0x26fFb53E...B623C59e9
0 ETH0.000006690.04525
Match Orders371572292026-01-28 12:18:513 hrs ago1769602731IN
0x26fFb53E...B623C59e9
0.00185 ETH0.000019230.04525
Match Orders371571312026-01-28 12:18:193 hrs ago1769602699IN
0x26fFb53E...B623C59e9
0.00185 ETH0.000025940.04525
Match Orders371570372026-01-28 12:17:373 hrs ago1769602657IN
0x26fFb53E...B623C59e9
0.00175 ETH0.000026230.04525
Match Orders371173472026-01-28 8:22:087 hrs ago1769588528IN
0x26fFb53E...B623C59e9
0.00185 ETH0.000019220.04525
Match Orders371171992026-01-28 8:21:157 hrs ago1769588475IN
0x26fFb53E...B623C59e9
0.00185 ETH0.000025410.04525
Match Orders371082812026-01-28 7:23:078 hrs ago1769584987IN
0x26fFb53E...B623C59e9
0 ETH0.000023490.04525
Match Orders370868222026-01-28 4:54:2811 hrs ago1769576068IN
0x26fFb53E...B623C59e9
0.00175 ETH0.00002550.04525
Match Orders370817352026-01-28 4:16:4911 hrs ago1769573809IN
0x26fFb53E...B623C59e9
0.00185 ETH0.0000250.04525
Match Orders370788132026-01-28 3:54:2412 hrs ago1769572464IN
0x26fFb53E...B623C59e9
0.00185 ETH0.000024980.04525
Cancel370754072026-01-28 3:30:1512 hrs ago1769571015IN
0x26fFb53E...B623C59e9
0 ETH0.000006340.04525
Match Orders370709472026-01-28 3:00:4912 hrs ago1769569249IN
0x26fFb53E...B623C59e9
0.0019 ETH0.000026510.04525
Match Orders370707162026-01-28 2:58:5912 hrs ago1769569139IN
0x26fFb53E...B623C59e9
0.0034 ETH0.00002550.04525
Match Orders370683612026-01-28 2:42:1413 hrs ago1769568134IN
0x26fFb53E...B623C59e9
0.0035 ETH0.00002550.04525
Cancel370539232026-01-28 0:52:2415 hrs ago1769561544IN
0x26fFb53E...B623C59e9
0 ETH0.000004570.04525
Cancel370537272026-01-28 0:50:3715 hrs ago1769561437IN
0x26fFb53E...B623C59e9
0 ETH0.000006690.04525
Match Orders370468632026-01-27 23:55:5015 hrs ago1769558150IN
0x26fFb53E...B623C59e9
0.0035 ETH0.000018890.04525
Match Orders370468192026-01-27 23:55:2715 hrs ago1769558127IN
0x26fFb53E...B623C59e9
0.0035 ETH0.000018890.04525
Match Orders370467752026-01-27 23:55:0216 hrs ago1769558102IN
0x26fFb53E...B623C59e9
0.0035 ETH0.000018890.04525
Match Orders370459992026-01-27 23:48:0716 hrs ago1769557687IN
0x26fFb53E...B623C59e9
0.0035 ETH0.00002550.04525
Match Orders370450012026-01-27 23:39:0216 hrs ago1769557142IN
0x26fFb53E...B623C59e9
0.019 ETH0.000023320.04525
Match Orders370429362026-01-27 23:21:2216 hrs ago1769556082IN
0x26fFb53E...B623C59e9
0.00185 ETH0.00002550.04525
Match Orders370096932026-01-27 19:27:5720 hrs ago1769542077IN
0x26fFb53E...B623C59e9
0 ETH0.000018250.04525
Match Orders370096192026-01-27 19:27:2920 hrs ago1769542049IN
0x26fFb53E...B623C59e9
0 ETH0.000018250.04525
Match Orders370095462026-01-27 19:27:0220 hrs ago1769542022IN
0x26fFb53E...B623C59e9
0 ETH0.000020180.04525
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
371572292026-01-28 12:18:513 hrs ago1769602731
0x26fFb53E...B623C59e9
0.00169275 ETH
371572292026-01-28 12:18:513 hrs ago1769602731
0x26fFb53E...B623C59e9
0.000037 ETH
371572292026-01-28 12:18:513 hrs ago1769602731
0x26fFb53E...B623C59e9
0.00012025 ETH
371572292026-01-28 12:18:513 hrs ago1769602731
0x26fFb53E...B623C59e9
0.00185 ETH
371571312026-01-28 12:18:193 hrs ago1769602699
0x26fFb53E...B623C59e9
0.00169275 ETH
371571312026-01-28 12:18:193 hrs ago1769602699
0x26fFb53E...B623C59e9
0.000037 ETH
371571312026-01-28 12:18:193 hrs ago1769602699
0x26fFb53E...B623C59e9
0.00012025 ETH
371571312026-01-28 12:18:193 hrs ago1769602699
0x26fFb53E...B623C59e9
0.00185 ETH
371570372026-01-28 12:17:373 hrs ago1769602657
0x26fFb53E...B623C59e9
0.00160125 ETH
371570372026-01-28 12:17:373 hrs ago1769602657
0x26fFb53E...B623C59e9
0.000035 ETH
371570372026-01-28 12:17:373 hrs ago1769602657
0x26fFb53E...B623C59e9
0.00011375 ETH
371570372026-01-28 12:17:373 hrs ago1769602657
0x26fFb53E...B623C59e9
0.00175 ETH
371173472026-01-28 8:22:087 hrs ago1769588528
0x26fFb53E...B623C59e9
0.00169275 ETH
371173472026-01-28 8:22:087 hrs ago1769588528
0x26fFb53E...B623C59e9
0.000037 ETH
371173472026-01-28 8:22:087 hrs ago1769588528
0x26fFb53E...B623C59e9
0.00012025 ETH
371173472026-01-28 8:22:087 hrs ago1769588528
0x26fFb53E...B623C59e9
0.00185 ETH
371171992026-01-28 8:21:157 hrs ago1769588475
0x26fFb53E...B623C59e9
0.00169275 ETH
371171992026-01-28 8:21:157 hrs ago1769588475
0x26fFb53E...B623C59e9
0.000037 ETH
371171992026-01-28 8:21:157 hrs ago1769588475
0x26fFb53E...B623C59e9
0.00012025 ETH
371171992026-01-28 8:21:157 hrs ago1769588475
0x26fFb53E...B623C59e9
0.00185 ETH
370868222026-01-28 4:54:2811 hrs ago1769576068
0x26fFb53E...B623C59e9
0.00160125 ETH
370868222026-01-28 4:54:2811 hrs ago1769576068
0x26fFb53E...B623C59e9
0.000035 ETH
370868222026-01-28 4:54:2811 hrs ago1769576068
0x26fFb53E...B623C59e9
0.00011375 ETH
370868222026-01-28 4:54:2811 hrs ago1769576068
0x26fFb53E...B623C59e9
0.00175 ETH
370817352026-01-28 4:16:4911 hrs ago1769573809
0x26fFb53E...B623C59e9
0.00169275 ETH
View All Internal Transactions
Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ExchangeMetaV2

Compiler Version
v0.7.6+commit.7338295f

ZkSolc Version
v1.3.18

Optimization Enabled:
Yes with Mode z

Other Settings:
default evmVersion
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "./ExchangeV2Core.sol";
import "@rarible/meta-tx/contracts/EIP712MetaTransaction.sol";
import "@rarible/transfer-manager/contracts/RaribleTransferManager.sol";

contract ExchangeMetaV2 is ExchangeV2Core, RaribleTransferManager, EIP712MetaTransaction {
    function __ExchangeV2_init(
        address _transferProxy,
        address _erc20TransferProxy,
        uint newProtocolFee,
        address newDefaultFeeReceiver,
        IRoyaltiesProvider newRoyaltiesProvider
    ) external initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
        __OrderValidator_init_unchained();
        __MetaTransaction_init_unchained("ExchangeMetaV2", "1");
        __TransferExecutor_init_unchained(_transferProxy, _erc20TransferProxy);
        __RaribleTransferManager_init_unchained(newProtocolFee, newDefaultFeeReceiver, newRoyaltiesProvider);
    }

    function _msgSender() internal view virtual override(ContextUpgradeable, EIP712MetaTransaction) returns (address payable) {
        return super._msgSender();
    }

}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal initializer {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), 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 {
        emit OwnershipTransferred(_owner, address(0));
        _owner = 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");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
    uint256[49] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;
import "../proxy/Initializable.sol";

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * _Available since v3.4._
 */
abstract contract EIP712Upgradeable is Initializable {
    /* solhint-disable var-name-mixedcase */
    bytes32 private _HASHED_NAME;
    bytes32 private _HASHED_VERSION;
    bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
    /* solhint-enable var-name-mixedcase */

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    function __EIP712_init(string memory name, string memory version) internal initializer {
        __EIP712_init_unchained(name, version);
    }

    function __EIP712_init_unchained(string memory name, string memory version) internal initializer {
        bytes32 hashedName = keccak256(bytes(name));
        bytes32 hashedVersion = keccak256(bytes(version));
        _HASHED_NAME = hashedName;
        _HASHED_VERSION = hashedVersion;
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());
    }

    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {
        return keccak256(
            abi.encode(
                typeHash,
                name,
                version,
                _getChainId(),
                address(this)
            )
        );
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", _domainSeparatorV4(), structHash));
    }

    function _getChainId() private view returns (uint256 chainId) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        // solhint-disable-next-line no-inline-assembly
        assembly {
            chainId := chainid()
        }
    }

    /**
     * @dev The hash of the name parameter for the EIP712 domain.
     *
     * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
     * are a concern.
     */
    function _EIP712NameHash() internal virtual view returns (bytes32) {
        return _HASHED_NAME;
    }

    /**
     * @dev The hash of the version parameter for the EIP712 domain.
     *
     * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
     * are a concern.
     */
    function _EIP712VersionHash() internal virtual view returns (bytes32) {
        return _HASHED_VERSION;
    }
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC165Upgradeable.sol";
import "../proxy/Initializable.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    function __ERC165_init() internal initializer {
        __ERC165_init_unchained();
    }

    function __ERC165_init_unchained() internal initializer {
        // Derived contracts need only register support for their own interfaces,
        // we register support for ERC165 itself here
        _registerInterface(_INTERFACE_ID_ERC165);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     *
     * Time complexity O(1), guaranteed to always use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return _supportedInterfaces[interfaceId];
    }

    /**
     * @dev Registers the contract as an implementer of the interface defined by
     * `interfaceId`. Support of the actual ERC165 interface is automatic and
     * registering its interface id is not required.
     *
     * See {IERC165-supportsInterface}.
     *
     * Requirements:
     *
     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
     */
    function _registerInterface(bytes4 interfaceId) internal virtual {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
    uint256[49] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMathUpgradeable {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}

File 7 of 182 : Initializable.sol
// SPDX-License-Identifier: MIT

// solhint-disable-next-line compiler-version
pragma solidity >=0.4.24 <0.8.0;

import "../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {

    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /// @dev Returns true if and only if the function is running in the constructor
    function _isConstructor() private view returns (bool) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC1155ReceiverUpgradeable.sol";
import "../../introspection/ERC165Upgradeable.sol";
import "../../proxy/Initializable.sol";

/**
 * @dev _Available since v3.1._
 */
abstract contract ERC1155ReceiverUpgradeable is Initializable, ERC165Upgradeable, IERC1155ReceiverUpgradeable {
    function __ERC1155Receiver_init() internal initializer {
        __ERC165_init_unchained();
        __ERC1155Receiver_init_unchained();
    }

    function __ERC1155Receiver_init_unchained() internal initializer {
        _registerInterface(
            ERC1155ReceiverUpgradeable(address(0)).onERC1155Received.selector ^
            ERC1155ReceiverUpgradeable(address(0)).onERC1155BatchReceived.selector
        );
    }
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC1155Upgradeable.sol";
import "./IERC1155MetadataURIUpgradeable.sol";
import "./IERC1155ReceiverUpgradeable.sol";
import "../../utils/ContextUpgradeable.sol";
import "../../introspection/ERC165Upgradeable.sol";
import "../../math/SafeMathUpgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../proxy/Initializable.sol";

/**
 *
 * @dev Implementation of the basic standard multi-token.
 * See https://eips.ethereum.org/EIPS/eip-1155
 * Originally based on code by Enjin: https://github.com/enjin/erc-1155
 *
 * _Available since v3.1._
 */
contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155Upgradeable, IERC1155MetadataURIUpgradeable {
    using SafeMathUpgradeable for uint256;
    using AddressUpgradeable for address;

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

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

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

    /*
     *     bytes4(keccak256('balanceOf(address,uint256)')) == 0x00fdd58e
     *     bytes4(keccak256('balanceOfBatch(address[],uint256[])')) == 0x4e1273f4
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,uint256,bytes)')) == 0xf242432a
     *     bytes4(keccak256('safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)')) == 0x2eb2c2d6
     *
     *     => 0x00fdd58e ^ 0x4e1273f4 ^ 0xa22cb465 ^
     *        0xe985e9c5 ^ 0xf242432a ^ 0x2eb2c2d6 == 0xd9b67a26
     */
    bytes4 private constant _INTERFACE_ID_ERC1155 = 0xd9b67a26;

    /*
     *     bytes4(keccak256('uri(uint256)')) == 0x0e89341c
     */
    bytes4 private constant _INTERFACE_ID_ERC1155_METADATA_URI = 0x0e89341c;

    /**
     * @dev See {_setURI}.
     */
    function __ERC1155_init(string memory uri_) internal initializer {
        __Context_init_unchained();
        __ERC165_init_unchained();
        __ERC1155_init_unchained(uri_);
    }

    function __ERC1155_init_unchained(string memory uri_) internal initializer {
        _setURI(uri_);

        // register the supported interfaces to conform to ERC1155 via ERC165
        _registerInterface(_INTERFACE_ID_ERC1155);

        // register the supported interfaces to conform to ERC1155MetadataURI via ERC165
        _registerInterface(_INTERFACE_ID_ERC1155_METADATA_URI);
    }

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

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

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

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

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

        return batchBalances;
    }

    /**
     * @dev See {IERC1155-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(_msgSender() != operator, "ERC1155: setting approval status for self");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

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

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

        address operator = _msgSender();

        _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);

        _balances[id][from] = _balances[id][from].sub(amount, "ERC1155: insufficient balance for transfer");
        _balances[id][to] = _balances[id][to].add(amount);

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

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

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

        address operator = _msgSender();

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

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

            _balances[id][from] = _balances[id][from].sub(
                amount,
                "ERC1155: insufficient balance for transfer"
            );
            _balances[id][to] = _balances[id][to].add(amount);
        }

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

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

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

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

        address operator = _msgSender();

        _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);

        _balances[id][account] = _balances[id][account].add(amount);
        emit TransferSingle(operator, address(0), account, id, amount);

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

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

        address operator = _msgSender();

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

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

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

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

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

        address operator = _msgSender();

        _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");

        _balances[id][account] = _balances[id][account].sub(
            amount,
            "ERC1155: burn amount exceeds balance"
        );

        emit TransferSingle(operator, account, address(0), id, amount);
    }

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

        address operator = _msgSender();

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

        for (uint i = 0; i < ids.length; i++) {
            _balances[ids[i]][account] = _balances[ids[i]][account].sub(
                amounts[i],
                "ERC1155: burn amount exceeds balance"
            );
        }

        emit TransferBatch(operator, account, address(0), ids, amounts);
    }

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

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

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

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

        return array;
    }
    uint256[47] private __gap;
}

File 10 of 182 : IERC1155MetadataURIUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

import "./IERC1155Upgradeable.sol";

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

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "../../introspection/IERC165Upgradeable.sol";

/**
 * _Available since v3.1._
 */
interface IERC1155ReceiverUpgradeable is IERC165Upgradeable {

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

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

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

import "../../introspection/IERC165Upgradeable.sol";

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

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

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

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

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

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

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

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

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "../../utils/ContextUpgradeable.sol";
import "./IERC20Upgradeable.sol";
import "../../math/SafeMathUpgradeable.sol";
import "../../proxy/Initializable.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of 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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {
    using SafeMathUpgradeable for uint256;

    mapping (address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    function __ERC20_init(string memory name_, string memory symbol_) internal initializer {
        __Context_init_unchained();
        __ERC20_init_unchained(name_, symbol_);
    }

    function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {
        _name = name_;
        _symbol = symbol_;
        _decimals = 18;
    }

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

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual 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 {_setupDecimals} is
     * called.
     *
     * 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 returns (uint8) {
        return _decimals;
    }

    /**
     * @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}.
     *
     * 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}.
     *
     * 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) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        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].add(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) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is 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);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(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:
     *
     * - `to` 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 = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(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);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(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 Sets {decimals} to a value other than the default one of 18.
     *
     * WARNING: This function should only be called from the constructor. Most
     * applications that interact with token contracts will not expect
     * {decimals} to ever change, and may work incorrectly if it does.
     */
    function _setupDecimals(uint8 decimals_) internal virtual {
        _decimals = decimals_;
    }

    /**
     * @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 to 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 { }
    uint256[44] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20Upgradeable {
    /**
     * @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);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "../../utils/ContextUpgradeable.sol";
import "./IERC721Upgradeable.sol";
import "./IERC721MetadataUpgradeable.sol";
import "./IERC721EnumerableUpgradeable.sol";
import "./IERC721ReceiverUpgradeable.sol";
import "../../introspection/ERC165Upgradeable.sol";
import "../../math/SafeMathUpgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/EnumerableSetUpgradeable.sol";
import "../../utils/EnumerableMapUpgradeable.sol";
import "../../utils/StringsUpgradeable.sol";
import "../../proxy/Initializable.sol";

/**
 * @title ERC721 Non-Fungible Token Standard basic implementation
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable, IERC721EnumerableUpgradeable {
    using SafeMathUpgradeable for uint256;
    using AddressUpgradeable for address;
    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;
    using EnumerableMapUpgradeable for EnumerableMapUpgradeable.UintToAddressMap;
    using StringsUpgradeable for uint256;

    // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;

    // Mapping from holder address to their (enumerable) set of owned tokens
    mapping (address => EnumerableSetUpgradeable.UintSet) private _holderTokens;

    // Enumerable mapping from token ids to their owners
    EnumerableMapUpgradeable.UintToAddressMap private _tokenOwners;

    // 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;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Optional mapping for token URIs
    mapping (uint256 => string) private _tokenURIs;

    // Base URI
    string private _baseURI;

    /*
     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
     *
     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
     */
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;

    /*
     *     bytes4(keccak256('name()')) == 0x06fdde03
     *     bytes4(keccak256('symbol()')) == 0x95d89b41
     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
     *
     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
     */
    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;

    /*
     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd
     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
     *
     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
     */
    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    function __ERC721_init(string memory name_, string memory symbol_) internal initializer {
        __Context_init_unchained();
        __ERC165_init_unchained();
        __ERC721_init_unchained(name_, symbol_);
    }

    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {
        _name = name_;
        _symbol = symbol_;

        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721);
        _registerInterface(_INTERFACE_ID_ERC721_METADATA);
        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
    }

    /**
     * @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 _holderTokens[owner].length();
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
    }

    /**
     * @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 _tokenURI = _tokenURIs[tokenId];
        string memory base = baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return string(abi.encodePacked(base, _tokenURI));
        }
        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
        return string(abi.encodePacked(base, tokenId.toString()));
    }

    /**
    * @dev Returns the base URI set via {_setBaseURI}. This will be
    * automatically added as a prefix in {tokenURI} to each token's URI, or
    * to the token ID if no specific URI is set for that token ID.
    */
    function baseURI() public view virtual returns (string memory) {
        return _baseURI;
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        return _holderTokens[owner].at(index);
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds
        return _tokenOwners.length();
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        (uint256 tokenId, ) = _tokenOwners.at(index);
        return tokenId;
    }

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

        require(_msgSender() == owner || ERC721Upgradeable.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 {
        require(operator != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_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 _tokenOwners.contains(tokenId);
    }

    /**
     * @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 = ERC721Upgradeable.ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || ERC721Upgradeable.isApprovedForAll(owner, spender));
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     d*
     * - `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);

        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

        emit Transfer(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 = ERC721Upgradeable.ownerOf(tokenId); // internal owner

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

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

        // Clear metadata (if any)
        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }

        _holderTokens[owner].remove(tokenId);

        _tokenOwners.remove(tokenId);

        emit Transfer(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(ERC721Upgradeable.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); // internal 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);

        _holderTokens[from].remove(tokenId);
        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
        require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
        _tokenURIs[tokenId] = _tokenURI;
    }

    /**
     * @dev Internal function to set the base URI for all token IDs. It is
     * automatically added as a prefix to the value returned in {tokenURI},
     * or to the token ID if {tokenURI} is empty.
     */
    function _setBaseURI(string memory baseURI_) internal virtual {
        _baseURI = baseURI_;
    }

    /**
     * @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()) {
            return true;
        }
        bytes memory returndata = to.functionCall(abi.encodeWithSelector(
            IERC721ReceiverUpgradeable(to).onERC721Received.selector,
            _msgSender(),
            from,
            tokenId,
            _data
        ), "ERC721: transfer to non ERC721Receiver implementer");
        bytes4 retval = abi.decode(returndata, (bytes4));
        return (retval == _ERC721_RECEIVED);
    }

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

    /**
     * @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 { }
    uint256[41] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

import "./IERC721Upgradeable.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721EnumerableUpgradeable is IERC721Upgradeable {

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

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

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

import "./IERC721Upgradeable.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721MetadataUpgradeable is IERC721Upgradeable {

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

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

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721ReceiverUpgradeable {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

import "../../introspection/IERC165Upgradeable.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721Upgradeable is IERC165Upgradeable {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

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

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

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

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

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

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

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

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 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");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;
import "../proxy/Initializable.sol";

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

    function __Context_init_unchained() internal initializer {
    }
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Library for managing an enumerable variant of Solidity's
 * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
 * type.
 *
 * Maps have the following properties:
 *
 * - Entries are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Entries are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableMap for EnumerableMap.UintToAddressMap;
 *
 *     // Declare a set state variable
 *     EnumerableMap.UintToAddressMap private myMap;
 * }
 * ```
 *
 * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are
 * supported.
 */
library EnumerableMapUpgradeable {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Map type with
    // bytes32 keys and values.
    // The Map implementation uses private functions, and user-facing
    // implementations (such as Uint256ToAddressMap) are just wrappers around
    // the underlying Map.
    // This means that we can only create new EnumerableMaps for types that fit
    // in bytes32.

    struct MapEntry {
        bytes32 _key;
        bytes32 _value;
    }

    struct Map {
        // Storage of map keys and values
        MapEntry[] _entries;

        // Position of the entry defined by a key in the `entries` array, plus 1
        // because index 0 means a key is not in the map.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {
        // We read and store the key's index to prevent multiple reads from the same storage slot
        uint256 keyIndex = map._indexes[key];

        if (keyIndex == 0) { // Equivalent to !contains(map, key)
            map._entries.push(MapEntry({ _key: key, _value: value }));
            // The entry is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            map._indexes[key] = map._entries.length;
            return true;
        } else {
            map._entries[keyIndex - 1]._value = value;
            return false;
        }
    }

    /**
     * @dev Removes a key-value pair from a map. O(1).
     *
     * Returns true if the key was removed from the map, that is if it was present.
     */
    function _remove(Map storage map, bytes32 key) private returns (bool) {
        // We read and store the key's index to prevent multiple reads from the same storage slot
        uint256 keyIndex = map._indexes[key];

        if (keyIndex != 0) { // Equivalent to contains(map, key)
            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one
            // in the array, and then remove the last entry (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = keyIndex - 1;
            uint256 lastIndex = map._entries.length - 1;

            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            MapEntry storage lastEntry = map._entries[lastIndex];

            // Move the last entry to the index where the entry to delete is
            map._entries[toDeleteIndex] = lastEntry;
            // Update the index for the moved entry
            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved entry was stored
            map._entries.pop();

            // Delete the index for the deleted slot
            delete map._indexes[key];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the key is in the map. O(1).
     */
    function _contains(Map storage map, bytes32 key) private view returns (bool) {
        return map._indexes[key] != 0;
    }

    /**
     * @dev Returns the number of key-value pairs in the map. O(1).
     */
    function _length(Map storage map) private view returns (uint256) {
        return map._entries.length;
    }

   /**
    * @dev Returns the key-value pair stored at position `index` in the map. O(1).
    *
    * Note that there are no guarantees on the ordering of entries inside the
    * array, and it may change when more entries are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
        require(map._entries.length > index, "EnumerableMap: index out of bounds");

        MapEntry storage entry = map._entries[index];
        return (entry._key, entry._value);
    }

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     */
    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {
        uint256 keyIndex = map._indexes[key];
        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)
        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function _get(Map storage map, bytes32 key) private view returns (bytes32) {
        uint256 keyIndex = map._indexes[key];
        require(keyIndex != 0, "EnumerableMap: nonexistent key"); // Equivalent to contains(map, key)
        return map._entries[keyIndex - 1]._value; // All indexes are 1-based
    }

    /**
     * @dev Same as {_get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {_tryGet}.
     */
    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {
        uint256 keyIndex = map._indexes[key];
        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)
        return map._entries[keyIndex - 1]._value; // All indexes are 1-based
    }

    // UintToAddressMap

    struct UintToAddressMap {
        Map _inner;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the key was removed from the map, that is if it was present.
     */
    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
        return _remove(map._inner, bytes32(key));
    }

    /**
     * @dev Returns true if the key is in the map. O(1).
     */
    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
        return _contains(map._inner, bytes32(key));
    }

    /**
     * @dev Returns the number of elements in the map. O(1).
     */
    function length(UintToAddressMap storage map) internal view returns (uint256) {
        return _length(map._inner);
    }

   /**
    * @dev Returns the element stored at position `index` in the set. O(1).
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
        (bytes32 key, bytes32 value) = _at(map._inner, index);
        return (uint256(key), address(uint160(uint256(value))));
    }

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     *
     * _Available since v3.4._
     */
    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));
        return (success, address(uint160(uint256(value))));
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
        return address(uint160(uint256(_get(map._inner, bytes32(key)))));
    }

    /**
     * @dev Same as {get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryGet}.
     */
    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {
        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSetUpgradeable {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

File 24 of 182 : StringsUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev String operations.
 */
library StringsUpgradeable {
    /**
     * @dev Converts a `uint256` to its ASCII `string` 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);
        uint256 index = digits - 1;
        temp = value;
        while (temp != 0) {
            buffer[index--] = bytes1(uint8(48 + temp % 10));
            temp /= 10;
        }
        return string(buffer);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "../utils/Context.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 () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), 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 {
        emit OwnershipTransferred(_owner, address(0));
        _owner = 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");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
abstract contract ERC165 is IERC165 {
    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    constructor () internal {
        // Derived contracts need only register support for their own interfaces,
        // we register support for ERC165 itself here
        _registerInterface(_INTERFACE_ID_ERC165);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     *
     * Time complexity O(1), guaranteed to always use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return _supportedInterfaces[interfaceId];
    }

    /**
     * @dev Registers the contract as an implementer of the interface defined by
     * `interfaceId`. Support of the actual ERC165 interface is automatic and
     * registering its interface id is not required.
     *
     * See {IERC165-supportsInterface}.
     *
     * Requirements:
     *
     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
     */
    function _registerInterface(bytes4 interfaceId) internal virtual {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Proxy.sol";
import "../utils/Address.sol";
import "./IBeacon.sol";

/**
 * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.
 *
 * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't
 * conflict with the storage layout of the implementation behind the proxy.
 *
 * _Available since v3.4._
 */
contract BeaconProxy is Proxy {
    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 private constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Initializes the proxy with `beacon`.
     *
     * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This
     * will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity
     * constructor.
     *
     * Requirements:
     *
     * - `beacon` must be a contract with the interface {IBeacon}.
     */
    constructor(address beacon, bytes memory data) public payable {
        assert(_BEACON_SLOT == bytes32(uint256(keccak256("eip1967.proxy.beacon")) - 1));
        _setBeacon(beacon, data);
    }

    /**
     * @dev Returns the current beacon address.
     */
    function _beacon() internal view virtual returns (address beacon) {
        bytes32 slot = _BEACON_SLOT;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            beacon := sload(slot)
        }
    }

    /**
     * @dev Returns the current implementation address of the associated beacon.
     */
    function _implementation() internal view virtual override returns (address) {
        return IBeacon(_beacon()).implementation();
    }

    /**
     * @dev Changes the proxy to use a new beacon.
     *
     * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.
     *
     * Requirements:
     *
     * - `beacon` must be a contract.
     * - The implementation returned by `beacon` must be a contract.
     */
    function _setBeacon(address beacon, bytes memory data) internal virtual {
        require(
            Address.isContract(beacon),
            "BeaconProxy: beacon is not a contract"
        );
        require(
            Address.isContract(IBeacon(beacon).implementation()),
            "BeaconProxy: beacon implementation is not a contract"
        );
        bytes32 slot = _BEACON_SLOT;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(slot, beacon)
        }

        if (data.length > 0) {
            Address.functionDelegateCall(_implementation(), data, "BeaconProxy: function call failed");
        }
    }
}

File 30 of 182 : IBeacon.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeacon {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internall call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 { revert(0, returndatasize()) }
            default { return(0, returndatasize()) }
        }
    }

    /**
     * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internall call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback () external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive () external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overriden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "../access/Ownable.sol";
import "./TransparentUpgradeableProxy.sol";

/**
 * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an
 * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.
 */
contract ProxyAdmin is Ownable {

    /**
     * @dev Returns the current implementation of `proxy`.
     *
     * Requirements:
     *
     * - This contract must be the admin of `proxy`.
     */
    function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {
        // We need to manually run the static call since the getter cannot be flagged as view
        // bytes4(keccak256("implementation()")) == 0x5c60da1b
        (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b");
        require(success);
        return abi.decode(returndata, (address));
    }

    /**
     * @dev Returns the current admin of `proxy`.
     *
     * Requirements:
     *
     * - This contract must be the admin of `proxy`.
     */
    function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {
        // We need to manually run the static call since the getter cannot be flagged as view
        // bytes4(keccak256("admin()")) == 0xf851a440
        (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440");
        require(success);
        return abi.decode(returndata, (address));
    }

    /**
     * @dev Changes the admin of `proxy` to `newAdmin`.
     *
     * Requirements:
     *
     * - This contract must be the current admin of `proxy`.
     */
    function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {
        proxy.changeAdmin(newAdmin);
    }

    /**
     * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.
     *
     * Requirements:
     *
     * - This contract must be the admin of `proxy`.
     */
    function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {
        proxy.upgradeTo(implementation);
    }

    /**
     * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See
     * {TransparentUpgradeableProxy-upgradeToAndCall}.
     *
     * Requirements:
     *
     * - This contract must be the admin of `proxy`.
     */
    function upgradeAndCall(TransparentUpgradeableProxy proxy, address implementation, bytes memory data) public payable virtual onlyOwner {
        proxy.upgradeToAndCall{value: msg.value}(implementation, data);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./UpgradeableProxy.sol";

/**
 * @dev This contract implements a proxy that is upgradeable by an admin.
 *
 * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
 * clashing], which can potentially be used in an attack, this contract uses the
 * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
 * things that go hand in hand:
 *
 * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
 * that call matches one of the admin functions exposed by the proxy itself.
 * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
 * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
 * "admin cannot fallback to proxy target".
 *
 * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
 * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
 * to sudden errors when trying to call a function from the proxy implementation.
 *
 * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
 * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
 */
contract TransparentUpgradeableProxy is UpgradeableProxy {
    /**
     * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
     * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.
     */
    constructor(address _logic, address admin_, bytes memory _data) public payable UpgradeableProxy(_logic, _data) {
        assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
        _setAdmin(admin_);
    }

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
     */
    modifier ifAdmin() {
        if (msg.sender == _admin()) {
            _;
        } else {
            _fallback();
        }
    }

    /**
     * @dev Returns the current admin.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
     *
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
     */
    function admin() external ifAdmin returns (address admin_) {
        admin_ = _admin();
    }

    /**
     * @dev Returns the current implementation.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
     *
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
     */
    function implementation() external ifAdmin returns (address implementation_) {
        implementation_ = _implementation();
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
     */
    function changeAdmin(address newAdmin) external virtual ifAdmin {
        require(newAdmin != address(0), "TransparentUpgradeableProxy: new admin is the zero address");
        emit AdminChanged(_admin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev Upgrade the implementation of the proxy.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
     */
    function upgradeTo(address newImplementation) external virtual ifAdmin {
        _upgradeTo(newImplementation);
    }

    /**
     * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
     * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
     * proxied contract.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
     */
    function upgradeToAndCall(address newImplementation, bytes calldata data) external payable virtual ifAdmin {
        _upgradeTo(newImplementation);
        Address.functionDelegateCall(newImplementation, data);
    }

    /**
     * @dev Returns the current admin.
     */
    function _admin() internal view virtual returns (address adm) {
        bytes32 slot = _ADMIN_SLOT;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            adm := sload(slot)
        }
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        bytes32 slot = _ADMIN_SLOT;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(slot, newAdmin)
        }
    }

    /**
     * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
     */
    function _beforeFallback() internal virtual override {
        require(msg.sender != _admin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
        super._beforeFallback();
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IBeacon.sol";
import "../access/Ownable.sol";
import "../utils/Address.sol";

/**
 * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their
 * implementation contract, which is where they will delegate all function calls.
 *
 * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.
 */
contract UpgradeableBeacon is IBeacon, Ownable {
    address private _implementation;

    /**
     * @dev Emitted when the implementation returned by the beacon is changed.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the
     * beacon.
     */
    constructor(address implementation_) public {
        _setImplementation(implementation_);
    }

    /**
     * @dev Returns the current implementation address.
     */
    function implementation() public view virtual override returns (address) {
        return _implementation;
    }

    /**
     * @dev Upgrades the beacon to a new implementation.
     *
     * Emits an {Upgraded} event.
     *
     * Requirements:
     *
     * - msg.sender must be the owner of the contract.
     * - `newImplementation` must be a contract.
     */
    function upgradeTo(address newImplementation) public virtual onlyOwner {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Sets the implementation contract address for this beacon
     *
     * Requirements:
     *
     * - `newImplementation` must be a contract.
     */
    function _setImplementation(address newImplementation) private {
        require(Address.isContract(newImplementation), "UpgradeableBeacon: implementation is not a contract");
        _implementation = newImplementation;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Proxy.sol";
import "../utils/Address.sol";

/**
 * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
 * implementation address that can be changed. This address is stored in storage in the location specified by
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
 * implementation behind the proxy.
 *
 * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see
 * {TransparentUpgradeableProxy}.
 */
contract UpgradeableProxy is Proxy {
    /**
     * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
     *
     * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
     * function call, and allows initializating the storage of the proxy like a Solidity constructor.
     */
    constructor(address _logic, bytes memory _data) public payable {
        assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
        _setImplementation(_logic);
        if(_data.length > 0) {
            Address.functionDelegateCall(_logic, _data);
        }
    }

    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Returns the current implementation address.
     */
    function _implementation() internal view virtual override returns (address impl) {
        bytes32 slot = _IMPLEMENTATION_SLOT;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            impl := sload(slot)
        }
    }

    /**
     * @dev Upgrades the proxy to a new implementation.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal virtual {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(Address.isContract(newImplementation), "UpgradeableProxy: new implementation is not a contract");

        bytes32 slot = _IMPLEMENTATION_SLOT;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(slot, newImplementation)
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

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

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

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

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

    /*
     *     bytes4(keccak256('balanceOf(address,uint256)')) == 0x00fdd58e
     *     bytes4(keccak256('balanceOfBatch(address[],uint256[])')) == 0x4e1273f4
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,uint256,bytes)')) == 0xf242432a
     *     bytes4(keccak256('safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)')) == 0x2eb2c2d6
     *
     *     => 0x00fdd58e ^ 0x4e1273f4 ^ 0xa22cb465 ^
     *        0xe985e9c5 ^ 0xf242432a ^ 0x2eb2c2d6 == 0xd9b67a26
     */
    bytes4 private constant _INTERFACE_ID_ERC1155 = 0xd9b67a26;

    /*
     *     bytes4(keccak256('uri(uint256)')) == 0x0e89341c
     */
    bytes4 private constant _INTERFACE_ID_ERC1155_METADATA_URI = 0x0e89341c;

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

        // register the supported interfaces to conform to ERC1155 via ERC165
        _registerInterface(_INTERFACE_ID_ERC1155);

        // register the supported interfaces to conform to ERC1155MetadataURI via ERC165
        _registerInterface(_INTERFACE_ID_ERC1155_METADATA_URI);
    }

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

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

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

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

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

        return batchBalances;
    }

    /**
     * @dev See {IERC1155-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(_msgSender() != operator, "ERC1155: setting approval status for self");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

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

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

        address operator = _msgSender();

        _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);

        _balances[id][from] = _balances[id][from].sub(amount, "ERC1155: insufficient balance for transfer");
        _balances[id][to] = _balances[id][to].add(amount);

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

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

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

        address operator = _msgSender();

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

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

            _balances[id][from] = _balances[id][from].sub(
                amount,
                "ERC1155: insufficient balance for transfer"
            );
            _balances[id][to] = _balances[id][to].add(amount);
        }

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

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

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

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

        address operator = _msgSender();

        _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);

        _balances[id][account] = _balances[id][account].add(amount);
        emit TransferSingle(operator, address(0), account, id, amount);

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

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

        address operator = _msgSender();

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

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

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

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

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

        address operator = _msgSender();

        _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");

        _balances[id][account] = _balances[id][account].sub(
            amount,
            "ERC1155: burn amount exceeds balance"
        );

        emit TransferSingle(operator, account, address(0), id, amount);
    }

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

        address operator = _msgSender();

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

        for (uint i = 0; i < ids.length; i++) {
            _balances[ids[i]][account] = _balances[ids[i]][account].sub(
                amounts[i],
                "ERC1155: burn amount exceeds balance"
            );
        }

        emit TransferBatch(operator, account, address(0), ids, amounts);
    }

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

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

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

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

        return array;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./ERC1155Receiver.sol";

/**
 * @dev _Available since v3.1._
 */
contract ERC1155Holder is ERC1155Receiver {
    function onERC1155Received(address, address, uint256, uint256, bytes memory) public virtual override returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory) public virtual override returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }
}

File 38 of 182 : ERC1155Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC1155Receiver.sol";
import "../../introspection/ERC165.sol";

/**
 * @dev _Available since v3.1._
 */
abstract contract ERC1155Receiver is ERC165, IERC1155Receiver {
    constructor() internal {
        _registerInterface(
            ERC1155Receiver(address(0)).onERC1155Received.selector ^
            ERC1155Receiver(address(0)).onERC1155BatchReceived.selector
        );
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

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

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

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

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

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

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

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

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

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

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

import "./IERC1155.sol";

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

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

/**
 * _Available since v3.1._
 */
interface IERC1155Receiver is IERC165 {

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

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

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC721Receiver.sol";

  /**
   * @dev Implementation of the {IERC721Receiver} interface.
   *
   * Accepts all token transfers. 
   * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}.
   */
contract ERC721Holder is IERC721Receiver {

    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     *
     * Always returns `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @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
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 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");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN 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 payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor () internal {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@rarible/exchange-interfaces/contracts/IAssetMatcher.sol";
import "@rarible/lazy-mint/contracts/erc-721/LibERC721LazyMint.sol";
import "@rarible/lazy-mint/contracts/erc-1155/LibERC1155LazyMint.sol";

/*
 * Custom matcher for collection (assetClass, that need any/all elements from collection)
 */
contract AssetMatcherCollection is IAssetMatcher {

    bytes constant EMPTY = "";

    function matchAssets(LibAsset.AssetType memory leftAssetType, LibAsset.AssetType memory rightAssetType) external view override returns (LibAsset.AssetType memory) {
        if (
            (rightAssetType.assetClass == LibAsset.ERC721_ASSET_CLASS) || 
            (rightAssetType.assetClass == LibERC721LazyMint.ERC721_LAZY_ASSET_CLASS) ||
            (rightAssetType.assetClass == LibAsset.ERC1155_ASSET_CLASS) || 
            (rightAssetType.assetClass == LibERC1155LazyMint.ERC1155_LAZY_ASSET_CLASS) ||
            (rightAssetType.assetClass == LibAsset.CRYPTO_PUNKS)
        ) {
          (address leftToken) = abi.decode(leftAssetType.data, (address));
          (address rightToken,) = abi.decode(rightAssetType.data, (address, uint));
          if (leftToken == rightToken) {
              return LibAsset.AssetType(rightAssetType.assetClass, rightAssetType.data);
          }
        }
        return LibAsset.AssetType(0, EMPTY);
    }
}

File 48 of 182 : IAssetMatcher.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@rarible/lib-asset/contracts/LibAsset.sol";

interface IAssetMatcher {
    function matchAssets(
        LibAsset.AssetType memory leftAssetType,
        LibAsset.AssetType memory rightAssetType
    ) external view returns (LibAsset.AssetType memory);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";

interface IERC20TransferProxy {
    function erc20safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) external;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol";

interface INftTransferProxy {
    function erc721safeTransferFrom(IERC721Upgradeable token, address from, address to, uint256 tokenId) external;

    function erc1155safeTransferFrom(IERC1155Upgradeable token, address from, address to, uint256 id, uint256 value, bytes calldata data) external;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
pragma abicoder v2;

import "@rarible/lib-part/contracts/LibPart.sol";

interface IRoyaltiesProvider {
    function getRoyalties(address token, uint tokenId) external returns (LibPart.Part[] memory);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

import "@rarible/lib-asset/contracts/LibAsset.sol";

interface ITransferProxy {
    function transfer(LibAsset.Asset calldata asset, address from, address to) external;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@rarible/exchange-interfaces/contracts/IAssetMatcher.sol";
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

abstract contract AssetMatcher is Initializable, OwnableUpgradeable {

    bytes constant EMPTY = "";
    mapping(bytes4 => address) internal matchers;

    event MatcherChange(bytes4 indexed assetType, address matcher);

    function setAssetMatcher(bytes4 assetType, address matcher) external onlyOwner {
        matchers[assetType] = matcher;
        emit MatcherChange(assetType, matcher);
    }

    function matchAssets(LibAsset.AssetType memory leftAssetType, LibAsset.AssetType memory rightAssetType) internal view returns (LibAsset.AssetType memory) {
        LibAsset.AssetType memory result = matchAssetOneSide(leftAssetType, rightAssetType);
        if (result.assetClass == 0) {
            return matchAssetOneSide(rightAssetType, leftAssetType);
        } else {
            return result;
        }
    }

    function matchAssetOneSide(LibAsset.AssetType memory leftAssetType, LibAsset.AssetType memory rightAssetType) private view returns (LibAsset.AssetType memory) {
        bytes4 classLeft = leftAssetType.assetClass;
        bytes4 classRight = rightAssetType.assetClass;
        if (classLeft == LibAsset.ETH_ASSET_CLASS) {
            if (classRight == LibAsset.ETH_ASSET_CLASS) {
                return leftAssetType;
            }
            return LibAsset.AssetType(0, EMPTY);
        }
        if (classLeft == LibAsset.ERC20_ASSET_CLASS) {
            if (classRight == LibAsset.ERC20_ASSET_CLASS) {
                return simpleMatch(leftAssetType, rightAssetType);
            }
            return LibAsset.AssetType(0, EMPTY);
        }
        if (classLeft == LibAsset.ERC721_ASSET_CLASS) {
            if (classRight == LibAsset.ERC721_ASSET_CLASS) {
                return simpleMatch(leftAssetType, rightAssetType);
            }
            return LibAsset.AssetType(0, EMPTY);
        }
        if (classLeft == LibAsset.ERC1155_ASSET_CLASS) {
            if (classRight == LibAsset.ERC1155_ASSET_CLASS) {
                return simpleMatch(leftAssetType, rightAssetType);
            }
            return LibAsset.AssetType(0, EMPTY);
        }
        address matcher = matchers[classLeft];
        if (matcher != address(0)) {
            return IAssetMatcher(matcher).matchAssets(leftAssetType, rightAssetType);
        }
        if (classLeft == classRight) {
            return simpleMatch(leftAssetType, rightAssetType);
        }
        revert("not found IAssetMatcher");
    }

    function simpleMatch(LibAsset.AssetType memory leftAssetType, LibAsset.AssetType memory rightAssetType) private pure returns (LibAsset.AssetType memory) {
        bytes32 leftHash = keccak256(leftAssetType.data);
        bytes32 rightHash = keccak256(rightAssetType.data);
        if (leftHash == rightHash) {
            return leftAssetType;
        }
        return LibAsset.AssetType(0, EMPTY);
    }

    uint256[49] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "./ExchangeV2Core.sol";
import "@rarible/transfer-manager/contracts/RaribleTransferManager.sol";

contract ExchangeV2 is ExchangeV2Core, RaribleTransferManager {
    function __ExchangeV2_init(
        address _transferProxy,
        address _erc20TransferProxy,
        uint newProtocolFee,
        address newDefaultFeeReceiver,
        IRoyaltiesProvider newRoyaltiesProvider
    ) external initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
        __TransferExecutor_init_unchained(_transferProxy, _erc20TransferProxy);
        __RaribleTransferManager_init_unchained(newProtocolFee, newDefaultFeeReceiver, newRoyaltiesProvider);
        __OrderValidator_init_unchained();
    }

}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "./libraries/LibFill.sol";
import "./libraries/LibOrderData.sol";
import "./libraries/LibDirectTransfer.sol";
import "./OrderValidator.sol";
import "./AssetMatcher.sol";

import "@rarible/transfer-manager/contracts/TransferExecutor.sol";
import "@rarible/transfer-manager/contracts/interfaces/ITransferManager.sol";
import "@rarible/transfer-manager/contracts/lib/LibDeal.sol";

abstract contract ExchangeV2Core is Initializable, OwnableUpgradeable, AssetMatcher, TransferExecutor, OrderValidator, ITransferManager {
    using SafeMathUpgradeable for uint;
    using LibTransfer for address;

    uint256 private constant UINT256_MAX = type(uint256).max;

    //state of the orders
    mapping(bytes32 => uint) public fills;

    //events
    event Cancel(bytes32 hash);
    event Match(bytes32 leftHash, bytes32 rightHash, uint newLeftFill, uint newRightFill);

    function cancel(LibOrder.Order memory order) external {
        require(_msgSender() == order.maker, "not a maker");
        require(order.salt != 0, "0 salt can't be used");
        bytes32 orderKeyHash = LibOrder.hashKey(order);
        fills[orderKeyHash] = UINT256_MAX;
        emit Cancel(orderKeyHash);
    }

    /**
     * @dev function, generate sellOrder and buyOrder from parameters and call validateAndMatch() for purchase transaction
 
    */

    function directPurchase(
        LibDirectTransfer.Purchase calldata direct
    ) external payable{
        LibAsset.AssetType memory paymentAssetType = getPaymentAssetType(direct.paymentToken);
                
        LibOrder.Order memory sellOrder = LibOrder.Order(
            direct.sellOrderMaker,
            LibAsset.Asset(
                LibAsset.AssetType(
                    direct.nftAssetClass,
                    direct.nftData
                ),
                direct.sellOrderNftAmount
            ),
            address(0),
            LibAsset.Asset(
                paymentAssetType,
                direct.sellOrderPaymentAmount
            ),
            direct.sellOrderSalt,
            direct.sellOrderStart,
            direct.sellOrderEnd,
            direct.sellOrderDataType,
            direct.sellOrderData
        );

        LibOrder.Order memory buyOrder = LibOrder.Order(
            address(0),
            LibAsset.Asset(
                paymentAssetType,
                direct.buyOrderPaymentAmount
            ),
            address(0),
            LibAsset.Asset(
                LibAsset.AssetType(
                    direct.nftAssetClass,
                    direct.nftData
                ),
                direct.buyOrderNftAmount
            ),
            0,
            0,
            0,
            direct.sellOrderDataType,
            direct.buyOrderData
        );

        validateFull(sellOrder, direct.sellOrderSignature);

        matchAndTransfer(sellOrder, buyOrder);
    }

    /**
     * @dev function, generate sellOrder and buyOrder from parameters and call validateAndMatch() for accept bid transaction
     * @param direct struct with parameters for accept bid operation
     */
    function directAcceptBid(
        LibDirectTransfer.AcceptBid calldata direct
    ) external payable {
        LibAsset.AssetType memory paymentAssetType = getPaymentAssetType(direct.paymentToken);

        LibOrder.Order memory buyOrder = LibOrder.Order(
            direct.bidMaker,
            LibAsset.Asset(
                paymentAssetType,
                direct.bidPaymentAmount
            ),
            address(0),
            LibAsset.Asset(
                LibAsset.AssetType(
                    direct.nftAssetClass,
                    direct.nftData
                ),
                direct.bidNftAmount
            ),
            direct.bidSalt,
            direct.bidStart,
            direct.bidEnd,
            direct.bidDataType,
            direct.bidData
        );

        LibOrder.Order memory sellOrder = LibOrder.Order(
            address(0),
            LibAsset.Asset(
                LibAsset.AssetType(
                    direct.nftAssetClass,
                    direct.nftData
                ),
                direct.sellOrderNftAmount
            ),
            address(0),
            LibAsset.Asset(
                paymentAssetType,
                direct.sellOrderPaymentAmount
            ),
            0,
            0,
            0,
            direct.bidDataType,
            direct.sellOrderData
        );

        validateFull(buyOrder, direct.bidSignature);

        matchAndTransfer(sellOrder, buyOrder);
    }

    function matchOrders(
        LibOrder.Order memory orderLeft,
        bytes memory signatureLeft,
        LibOrder.Order memory orderRight,
        bytes memory signatureRight
    ) external payable {
        validateOrders(orderLeft, signatureLeft, orderRight, signatureRight);
        matchAndTransfer(orderLeft, orderRight);
    }

    /**
      * @dev function, validate orders
      * @param orderLeft left order
      * @param signatureLeft order left signature
      * @param orderRight right order
      * @param signatureRight order right signature
      */
    function validateOrders(LibOrder.Order memory orderLeft, bytes memory signatureLeft, LibOrder.Order memory orderRight, bytes memory signatureRight) internal view {
        validateFull(orderLeft, signatureLeft);
        validateFull(orderRight, signatureRight);
        if (orderLeft.taker != address(0)) {
            if (orderRight.maker != address(0))
                require(orderRight.maker == orderLeft.taker, "leftOrder.taker verification failed");
        }
        if (orderRight.taker != address(0)) {
            if (orderLeft.maker != address(0))
                require(orderRight.taker == orderLeft.maker, "rightOrder.taker verification failed");
        }
    }

    /**
        @notice matches valid orders and transfers their assets
        @param orderLeft the left order of the match
        @param orderRight the right order of the match
    */
    function matchAndTransfer(LibOrder.Order memory orderLeft, LibOrder.Order memory orderRight) internal {
        (LibAsset.AssetType memory makeMatch, LibAsset.AssetType memory takeMatch) = matchAssets(orderLeft, orderRight);

        (LibOrderData.GenericOrderData memory leftOrderData, LibOrderData.GenericOrderData memory rightOrderData, LibFill.FillResult memory newFill) =
            parseOrdersSetFillEmitMatch(orderLeft, orderRight);

        (uint totalMakeValue, uint totalTakeValue) = doTransfers(
            LibDeal.DealSide({
                asset: LibAsset.Asset({
                    assetType: makeMatch,
                    value: newFill.leftValue
                }),
                payouts: leftOrderData.payouts,
                originFees: leftOrderData.originFees,
                proxy: proxies[makeMatch.assetClass],
                from: orderLeft.maker,
                protocolFeeEnabled: leftOrderData.protocolFeeEnabled
            }), 
            LibDeal.DealSide({
                asset: LibAsset.Asset( 
                    takeMatch,
                    newFill.rightValue
                ),
                payouts: rightOrderData.payouts,
                originFees: rightOrderData.originFees,
                proxy: proxies[takeMatch.assetClass],
                from: orderRight.maker,
                protocolFeeEnabled: rightOrderData.protocolFeeEnabled
            }),
            LibFeeSide.getFeeSide(makeMatch.assetClass, takeMatch.assetClass)
        );
        if (makeMatch.assetClass == LibAsset.ETH_ASSET_CLASS) {
            require(takeMatch.assetClass != LibAsset.ETH_ASSET_CLASS);
            require(msg.value >= totalMakeValue, "not enough eth");
            if (msg.value > totalMakeValue) {
                address(msg.sender).transferEth(msg.value.sub(totalMakeValue));
            }
        } else if (takeMatch.assetClass == LibAsset.ETH_ASSET_CLASS) {
            require(msg.value >= totalTakeValue, "not enough eth");
            if (msg.value > totalTakeValue) {
                address(msg.sender).transferEth(msg.value.sub(totalTakeValue));
            }
        }
    }

    function parseOrdersSetFillEmitMatch(
        LibOrder.Order memory orderLeft,
        LibOrder.Order memory orderRight
    ) internal returns (LibOrderData.GenericOrderData memory leftOrderData, LibOrderData.GenericOrderData memory rightOrderData, LibFill.FillResult memory newFill) {
        bytes32 leftOrderKeyHash = LibOrder.hashKey(orderLeft);
        bytes32 rightOrderKeyHash = LibOrder.hashKey(orderRight);

        address msgSender = _msgSender();
        if (orderLeft.maker == address(0)) {
            orderLeft.maker = msgSender;
        }
        if (orderRight.maker == address(0)) {
            orderRight.maker = msgSender;
        }

        leftOrderData = LibOrderData.parse(orderLeft);
        rightOrderData = LibOrderData.parse(orderRight);

        newFill = setFillEmitMatch(
            orderLeft,
            orderRight,
            leftOrderKeyHash,
            rightOrderKeyHash,
            leftOrderData.isMakeFill,
            rightOrderData.isMakeFill
        );
    }

    /**
        @notice calculates fills for the matched orders and set them in "fills" mapping
        @param orderLeft left order of the match
        @param orderRight right order of the match
        @param leftMakeFill true if the left orders uses make-side fills, false otherwise
        @param rightMakeFill true if the right orders uses make-side fills, false otherwise
        @return returns change in orders' fills by the match 
    */
    function setFillEmitMatch(
        LibOrder.Order memory orderLeft,
        LibOrder.Order memory orderRight,
        bytes32 leftOrderKeyHash,
        bytes32 rightOrderKeyHash,
        bool leftMakeFill,
        bool rightMakeFill
    ) internal returns (LibFill.FillResult memory) {
        uint leftOrderFill = getOrderFill(orderLeft.salt, leftOrderKeyHash);
        uint rightOrderFill = getOrderFill(orderRight.salt, rightOrderKeyHash);
        LibFill.FillResult memory newFill = LibFill.fillOrder(orderLeft, orderRight, leftOrderFill, rightOrderFill, leftMakeFill, rightMakeFill);

        if (orderLeft.makeAsset.value != 0 || orderRight.takeAsset.value != 0) {
            require(newFill.leftValue > 0, "nothing to fill");
        }
        if (orderLeft.takeAsset.value != 0 || orderRight.makeAsset.value != 0) {
            require(newFill.rightValue > 0, "nothing to fill");
        }

        if (orderLeft.salt != 0) {
            if (leftMakeFill) {
                fills[leftOrderKeyHash] = leftOrderFill.add(newFill.leftValue);
            } else {
                fills[leftOrderKeyHash] = leftOrderFill.add(newFill.rightValue);
            }
        }

        if (orderRight.salt != 0) {
            if (rightMakeFill) {
                fills[rightOrderKeyHash] = rightOrderFill.add(newFill.rightValue);
            } else {
                fills[rightOrderKeyHash] = rightOrderFill.add(newFill.leftValue);
            }
        }

        emit Match(leftOrderKeyHash, rightOrderKeyHash, newFill.rightValue, newFill.leftValue);

        return newFill;
    }

    function getOrderFill(uint salt, bytes32 hash) internal view returns (uint fill) {
        if (salt == 0) {
            fill = 0;
        } else {
            fill = fills[hash];
        }
    }

    function matchAssets(LibOrder.Order memory orderLeft, LibOrder.Order memory orderRight) internal view returns (LibAsset.AssetType memory makeMatch, LibAsset.AssetType memory takeMatch) {
        makeMatch = matchAssets(orderLeft.makeAsset.assetType, orderRight.takeAsset.assetType);
        require(makeMatch.assetClass != 0, "assets don't match");
        takeMatch = matchAssets(orderLeft.takeAsset.assetType, orderRight.makeAsset.assetType);
        require(takeMatch.assetClass != 0, "assets don't match");
    }

    function validateFull(LibOrder.Order memory order, bytes memory signature) internal view {
        LibOrder.validateOrderTime(order);
        validate(order, signature);
    }

    function getPaymentAssetType(address token) internal pure returns(LibAsset.AssetType memory){
        LibAsset.AssetType memory result;
        if(token == address(0)) {
            result.assetClass = LibAsset.ETH_ASSET_CLASS;
        } else {
            result.assetClass = LibAsset.ERC20_ASSET_CLASS;
            result.data = abi.encode(token);
        }
        return result;
    }

    uint256[49] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "./libraries/LibOrder.sol";

import "@rarible/lib-signature/contracts/IERC1271.sol";
import "@rarible/lib-signature/contracts/LibSignature.sol";

import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol";

abstract contract OrderValidator is Initializable, ContextUpgradeable, EIP712Upgradeable {
    using LibSignature for bytes32;
    using AddressUpgradeable for address;
    
    bytes4 constant internal MAGICVALUE = 0x1626ba7e;

    function __OrderValidator_init_unchained() internal initializer {
        __EIP712_init_unchained("Exchange", "2");
    }

    function validate(LibOrder.Order memory order, bytes memory signature) internal view {
        if (order.salt == 0) {
            if (order.maker != address(0)) {
                require(_msgSender() == order.maker, "maker is not tx sender");
            }
        } else {
            if (_msgSender() != order.maker) {
                bytes32 hash = LibOrder.hash(order);
                // if maker is contract checking ERC1271 signature
                if (order.maker.isContract()) {
                    require(
                        IERC1271(order.maker).isValidSignature(_hashTypedDataV4(hash), signature) == MAGICVALUE,
                        "contract order signature verification error"
                    );
                } else {
                    // if maker is not contract then checking ECDSA signature
                    if (_hashTypedDataV4(hash).recover(signature) != order.maker) {
                        revert("order signature verification error");
                    } else {
                        require (order.maker != address(0), "no maker");
                    }
                }
            }
        }
    }

    uint256[50] private __gap;
}

File 57 of 182 : LibDirectTransfer.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@rarible/lib-asset/contracts/LibAsset.sol";

library LibDirectTransfer { //LibDirectTransfers
    /*All buy parameters need for create buyOrder and sellOrder*/
    struct Purchase {
        address sellOrderMaker; //
        uint256 sellOrderNftAmount;
        bytes4 nftAssetClass;
        bytes nftData;
        uint256 sellOrderPaymentAmount;
        address paymentToken;
        uint256 sellOrderSalt;
        uint sellOrderStart;
        uint sellOrderEnd;
        bytes4 sellOrderDataType;
        bytes sellOrderData;
        bytes sellOrderSignature;

        uint256 buyOrderPaymentAmount;
        uint256 buyOrderNftAmount;
        bytes buyOrderData;
    }

    /*All accept bid parameters need for create buyOrder and sellOrder*/
    struct AcceptBid {
        address bidMaker; //
        uint256 bidNftAmount;
        bytes4 nftAssetClass;
        bytes nftData;
        uint256 bidPaymentAmount;
        address paymentToken;
        uint256 bidSalt;
        uint bidStart;
        uint bidEnd;
        bytes4 bidDataType;
        bytes bidData;
        bytes bidSignature;

        uint256 sellOrderPaymentAmount;
        uint256 sellOrderNftAmount;
        bytes sellOrderData;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "./LibOrder.sol";

library LibFill {
    struct FillResult {
        uint leftValue;
        uint rightValue;
    }

    struct IsMakeFill {
        bool leftMake;
        bool rightMake;
    }

    /**
     * @dev Should return filled values
     * @param leftOrder left order
     * @param rightOrder right order
     * @param leftOrderFill current fill of the left order (0 if order is unfilled)
     * @param rightOrderFill current fill of the right order (0 if order is unfilled)
     * @param leftIsMakeFill true if left orders fill is calculated from the make side, false if from the take side
     * @param rightIsMakeFill true if right orders fill is calculated from the make side, false if from the take side
     * @return tuple representing fill of both assets
     */
    function fillOrder(LibOrder.Order memory leftOrder, LibOrder.Order memory rightOrder, uint leftOrderFill, uint rightOrderFill, bool leftIsMakeFill, bool rightIsMakeFill) internal pure returns (FillResult memory) {
        (uint leftMakeValue, uint leftTakeValue) = LibOrder.calculateRemaining(leftOrder, leftOrderFill, leftIsMakeFill);
        (uint rightMakeValue, uint rightTakeValue) = LibOrder.calculateRemaining(rightOrder, rightOrderFill, rightIsMakeFill);

        //We have 3 cases here:
        if (rightTakeValue > leftMakeValue || (rightTakeValue == leftMakeValue && leftMakeValue == 0)) { //1nd: left order should be fully filled
            return fillLeft(leftMakeValue, leftTakeValue, rightOrder.makeAsset.value, rightOrder.takeAsset.value);
        }//2st: right order should be fully filled or 3d: both should be fully filled if required values are the same
        return fillRight(leftOrder.makeAsset.value, leftOrder.takeAsset.value, rightMakeValue, rightTakeValue);
    }

    function fillRight(uint leftMakeValue, uint leftTakeValue, uint rightMakeValue, uint rightTakeValue) internal pure returns (FillResult memory result) {
        uint makerValue = LibMath.safeGetPartialAmountFloor(rightTakeValue, leftMakeValue, leftTakeValue);
        require(makerValue <= rightMakeValue, "fillRight: unable to fill");
        return FillResult(rightTakeValue, makerValue);
    }

    function fillLeft(uint leftMakeValue, uint leftTakeValue, uint rightMakeValue, uint rightTakeValue) internal pure returns (FillResult memory result) {
        uint rightTake = LibMath.safeGetPartialAmountFloor(leftTakeValue, rightMakeValue, rightTakeValue);
        require(rightTake <= leftMakeValue, "fillLeft: unable to fill");
        return FillResult(leftMakeValue, leftTakeValue);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";

library LibMath {
    using SafeMathUpgradeable for uint;

    /// @dev Calculates partial value given a numerator and denominator rounded down.
    ///      Reverts if rounding error is >= 0.1%
    /// @param numerator Numerator.
    /// @param denominator Denominator.
    /// @param target Value to calculate partial of.
    /// @return partialAmount value of target rounded down.
    function safeGetPartialAmountFloor(
        uint256 numerator,
        uint256 denominator,
        uint256 target
    ) internal pure returns (uint256 partialAmount) {
        if (isRoundingErrorFloor(numerator, denominator, target)) {
            revert("rounding error");
        }
        partialAmount = numerator.mul(target).div(denominator);
    }

    /// @dev Checks if rounding error >= 0.1% when rounding down.
    /// @param numerator Numerator.
    /// @param denominator Denominator.
    /// @param target Value to multiply with numerator/denominator.
    /// @return isError Rounding error is present.
    function isRoundingErrorFloor(
        uint256 numerator,
        uint256 denominator,
        uint256 target
    ) internal pure returns (bool isError) {
        if (denominator == 0) {
            revert("division by zero");
        }

        // The absolute rounding error is the difference between the rounded
        // value and the ideal value. The relative rounding error is the
        // absolute rounding error divided by the absolute value of the
        // ideal value. This is undefined when the ideal value is zero.
        //
        // The ideal value is `numerator * target / denominator`.
        // Let's call `numerator * target % denominator` the remainder.
        // The absolute error is `remainder / denominator`.
        //
        // When the ideal value is zero, we require the absolute error to
        // be zero. Fortunately, this is always the case. The ideal value is
        // zero iff `numerator == 0` and/or `target == 0`. In this case the
        // remainder and absolute error are also zero.
        if (target == 0 || numerator == 0) {
            return false;
        }

        // Otherwise, we want the relative rounding error to be strictly
        // less than 0.1%.
        // The relative error is `remainder / (numerator * target)`.
        // We want the relative error less than 1 / 1000:
        //        remainder / (numerator * target)  <  1 / 1000
        // or equivalently:
        //        1000 * remainder  <  numerator * target
        // so we have a rounding error iff:
        //        1000 * remainder  >=  numerator * target
        uint256 remainder = mulmod(
            target,
            numerator,
            denominator
        );
        isError = remainder.mul(1000) >= numerator.mul(target);
    }

    function safeGetPartialAmountCeil(
        uint256 numerator,
        uint256 denominator,
        uint256 target
    ) internal pure returns (uint256 partialAmount) {
        if (isRoundingErrorCeil(numerator, denominator, target)) {
            revert("rounding error");
        }
        partialAmount = numerator.mul(target).add(denominator.sub(1)).div(denominator);
    }

    /// @dev Checks if rounding error >= 0.1% when rounding up.
    /// @param numerator Numerator.
    /// @param denominator Denominator.
    /// @param target Value to multiply with numerator/denominator.
    /// @return isError Rounding error is present.
    function isRoundingErrorCeil(
        uint256 numerator,
        uint256 denominator,
        uint256 target
    ) internal pure returns (bool isError) {
        if (denominator == 0) {
            revert("division by zero");
        }

        // See the comments in `isRoundingError`.
        if (target == 0 || numerator == 0) {
            // When either is zero, the ideal value and rounded value are zero
            // and there is no rounding error. (Although the relative error
            // is undefined.)
            return false;
        }
        // Compute remainder as before
        uint256 remainder = mulmod(
            target,
            numerator,
            denominator
        );
        remainder = denominator.sub(remainder) % denominator;
        isError = remainder.mul(1000) >= numerator.mul(target);
        return isError;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@rarible/lib-asset/contracts/LibAsset.sol";

import "./LibMath.sol";
import "./LibOrderDataV3.sol";
import "./LibOrderDataV2.sol";
import "./LibOrderDataV1.sol";

library LibOrder {
    using SafeMathUpgradeable for uint;

    bytes32 constant ORDER_TYPEHASH = keccak256(
        "Order(address maker,Asset makeAsset,address taker,Asset takeAsset,uint256 salt,uint256 start,uint256 end,bytes4 dataType,bytes data)Asset(AssetType assetType,uint256 value)AssetType(bytes4 assetClass,bytes data)"
    );

    bytes4 constant DEFAULT_ORDER_TYPE = 0xffffffff;

    struct Order {
        address maker;
        LibAsset.Asset makeAsset;
        address taker;
        LibAsset.Asset takeAsset;
        uint salt;
        uint start;
        uint end;
        bytes4 dataType;
        bytes data;
    }

    /**
     * @dev Calculate remaining make and take values of the order (after partial filling real make and take decrease)
     * @param order initial order to calculate remaining values for
     * @param fill current fill of the left order (0 if order is unfilled)
     * @param isMakeFill true if order fill is calculated from the make side, false if from the take side
     * @return makeValue remaining make value of the order. if fill = 0 then it's order's make value
     * @return takeValue remaining take value of the order. if fill = 0 then it's order's take value
     */
    function calculateRemaining(Order memory order, uint fill, bool isMakeFill) internal pure returns (uint makeValue, uint takeValue) {
        if (isMakeFill) {
            makeValue = order.makeAsset.value.sub(fill);
            takeValue = LibMath.safeGetPartialAmountFloor(order.takeAsset.value, order.makeAsset.value, makeValue);
        } else {
            takeValue = order.takeAsset.value.sub(fill);
            makeValue = LibMath.safeGetPartialAmountFloor(order.makeAsset.value, order.takeAsset.value, takeValue); 
        } 
    }

    function hashKey(Order memory order) internal pure returns (bytes32) {
        if (order.dataType == LibOrderDataV1.V1 || order.dataType == DEFAULT_ORDER_TYPE) {
            return keccak256(abi.encode(
                order.maker,
                LibAsset.hash(order.makeAsset.assetType),
                LibAsset.hash(order.takeAsset.assetType),
                order.salt
            ));
        } else {
            //order.data is in hash for V2, V3 and all new order
            return keccak256(abi.encode(
                order.maker,
                LibAsset.hash(order.makeAsset.assetType),
                LibAsset.hash(order.takeAsset.assetType),
                order.salt,
                order.data
            ));
        }
    }

    function hash(Order memory order) internal pure returns (bytes32) {
        return keccak256(abi.encode(
                ORDER_TYPEHASH,
                order.maker,
                LibAsset.hash(order.makeAsset),
                order.taker,
                LibAsset.hash(order.takeAsset),
                order.salt,
                order.start,
                order.end,
                order.dataType,
                keccak256(order.data)
            ));
    }

    function validateOrderTime(LibOrder.Order memory order) internal view {
        require(order.start == 0 || order.start < block.timestamp, "Order start validation failed");
        require(order.end == 0 || order.end > block.timestamp, "Order end validation failed");
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "./LibOrder.sol";

library LibOrderData {

    struct GenericOrderData {
        LibPart.Part[] payouts;
        LibPart.Part[] originFees;
        bool isMakeFill;
        bool protocolFeeEnabled;
    } 

    function parse(LibOrder.Order memory order) pure internal returns (GenericOrderData memory dataOrder) {
        dataOrder.protocolFeeEnabled = false;
        if (order.dataType == LibOrderDataV1.V1) {
            LibOrderDataV1.DataV1 memory data = abi.decode(order.data, (LibOrderDataV1.DataV1));
            dataOrder.payouts = data.payouts;
            dataOrder.originFees = data.originFees;
        } else if (order.dataType == LibOrderDataV2.V2) {
            LibOrderDataV2.DataV2 memory data = abi.decode(order.data, (LibOrderDataV2.DataV2));
            dataOrder.payouts = data.payouts;
            dataOrder.originFees = data.originFees;
            dataOrder.isMakeFill = data.isMakeFill;
        } else if (order.dataType == LibOrderDataV3.V3) {
            LibOrderDataV3.DataV3 memory data = abi.decode(order.data, (LibOrderDataV3.DataV3));
            dataOrder.payouts = data.payouts;
            dataOrder.originFees = data.originFees;
            dataOrder.isMakeFill = data.isMakeFill;
            dataOrder.protocolFeeEnabled = true;
        } else if (order.dataType == 0xffffffff) {
        } else {
            revert("Unknown Order data type");
        }
        if (dataOrder.payouts.length == 0) {
            dataOrder.payouts = payoutSet(order.maker);
        }
    }

    function payoutSet(address orderAddress) pure internal returns (LibPart.Part[] memory) {
        LibPart.Part[] memory payout = new LibPart.Part[](1);
        payout[0].account = payable(orderAddress);
        payout[0].value = 10000;
        return payout;
    }

    function parseOriginFeeData(uint dataFirst, uint dataSecond) internal pure returns(LibPart.Part[] memory) {
        LibPart.Part[] memory originFee;

        if (dataFirst > 0 && dataSecond > 0){
            originFee = new LibPart.Part[](2);

            originFee[0] = uintToLibPart(dataFirst);
            originFee[1] = uintToLibPart(dataSecond);
        }

        if (dataFirst > 0 && dataSecond == 0) {
            originFee = new LibPart.Part[](1);

            originFee[0] = uintToLibPart(dataFirst);
        }

        if (dataFirst == 0 && dataSecond > 0) {
            originFee = new LibPart.Part[](1);

            originFee[0] = uintToLibPart(dataSecond);
        }

        return originFee;
    }

    function parsePayouts(uint data) internal pure returns(LibPart.Part[] memory) {
        LibPart.Part[] memory payouts;

        if (data > 0) {
            payouts = new LibPart.Part[](1);
            payouts[0] = uintToLibPart(data);
        }

        return payouts;
    }

    /**
        @notice converts uint to LibPart.Part
        @param data address and value encoded in uint (first 12 bytes )
        @return result LibPart.Part 
     */
    function uintToLibPart(uint data) internal pure returns(LibPart.Part memory result) {
        if (data > 0){
            result.account = payable(address(data));
            result.value = uint96(data >> 160);
        }
    }

}

File 62 of 182 : LibOrderDataV1.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@rarible/lib-part/contracts/LibPart.sol";

library LibOrderDataV1 {
    bytes4 constant public V1 = bytes4(keccak256("V1"));

    struct DataV1 {
        LibPart.Part[] payouts;
        LibPart.Part[] originFees;
    }

}

File 63 of 182 : LibOrderDataV2.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@rarible/lib-part/contracts/LibPart.sol";

library LibOrderDataV2 {
    bytes4 constant public V2 = bytes4(keccak256("V2"));

    struct DataV2 {
        LibPart.Part[] payouts;
        LibPart.Part[] originFees;
        bool isMakeFill;
    }

}

File 64 of 182 : LibOrderDataV3.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@rarible/lib-part/contracts/LibPart.sol";

library LibOrderDataV3 {
    bytes4 constant public V3 = bytes4(keccak256("V3"));

    struct DataV3 {
        LibPart.Part[] payouts;
        LibPart.Part[] originFees;
        bool isMakeFill;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "../../contracts/ExchangeV2.sol";

contract RaribleTestHelper {
    function encode(LibOrderDataV1.DataV1 memory data)
        external
        pure
        returns (bytes memory)
    {
        return abi.encode(data);
    }

    function encodeV2(LibOrderDataV2.DataV2 memory data)
        external
        pure
        returns (bytes memory)
    {
        return abi.encode(data);
    }

    function encodeV3(LibOrderDataV3.DataV3 memory data)
        external
        pure
        returns (bytes memory)
    {
        return abi.encode(data);
    }

    function encodeOriginFeeIntoUint(address account, uint96 value)
        external
        pure
        returns (uint256)
    {
        return (uint256(value) << 160) + uint256(account);
    }

    function hashKey(LibOrder.Order calldata order)
        external
        pure
        returns (bytes32)
    {
        return LibOrder.hashKey(order);
    }

    function hashV2(
        address maker,
        LibAsset.Asset memory makeAsset,
        LibAsset.Asset memory takeAsset,
        uint256 salt,
        bytes memory data
    ) public pure returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    maker,
                    LibAsset.hash(makeAsset.assetType),
                    LibAsset.hash(takeAsset.assetType),
                    salt,
                    data
                )
            );
    }

    function encodeLazy721(LibERC721LazyMint.Mint721Data memory data, address token)
        external
        pure
        returns (bytes memory)
    {
        return abi.encode(token, data);
    }

    function encodeLazy1155(LibERC1155LazyMint.Mint1155Data memory data, address token)
        external
        pure
        returns (bytes memory)
    {
        return abi.encode(token, data);
    }

}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@rarible/transfer-manager/contracts/lib/LibTransfer.sol";
import "@rarible/lib-bp/contracts/BpLibrary.sol";
import "@rarible/lib-part/contracts/LibPart.sol";

import "@openzeppelin/contracts/math/SafeMath.sol";

import "@openzeppelin/contracts/token/ERC721/ERC721Holder.sol";
import "@openzeppelin/contracts/token/ERC1155/ERC1155Holder.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";

import "./interfaces/IWyvernExchange.sol";
import "./interfaces/IExchangeV2.sol";
import "./interfaces/ISeaPort.sol";
import "./interfaces/Ix2y2.sol";
import "./interfaces/ILooksRare.sol";
import "./interfaces/IBlur.sol";

import "./libraries/IsPausable.sol";

contract RaribleExchangeWrapper is Ownable, ERC721Holder, ERC1155Holder, IsPausable {
    using LibTransfer for address;
    using BpLibrary for uint;
    using SafeMath for uint;

    //marketplaces
    address public immutable wyvernExchange;
    address public immutable exchangeV2;
    address public immutable seaPort_1_1;
    address public immutable x2y2;
    address public immutable looksRare;
    address public immutable sudoswap;
    address public immutable seaPort_1_4;
    address public immutable looksRareV2;
    address public immutable blur;
    address public immutable seaPort_1_5;
    address public immutable seaPort_1_6;

    //currencties
    address public immutable weth;

    //constants
    uint256 private constant UINT256_MAX = type(uint256).max;

    event Execution(bool result);

    enum Markets {
        ExchangeV2,//0
        WyvernExchange,//1
        SeaPort_1_1,//2
        X2Y2,//3
        LooksRareOrders,//4
        SudoSwap,//5
        SeaPort_1_4,//6
        LooksRareV2,//7
        Blur,//8
        SeaPort_1_5,//9
        SeaPort_1_6//10
    }

    enum AdditionalDataTypes {
        NoAdditionalData,
        RoyaltiesAdditionalData
    }

    enum Currencies {
        ETH,
        WETH
    }

    /**
        @notice struct for the purchase data
        @param marketId - market key from Markets enum (what market to use)
        @param amount - eth price (amount of eth that needs to be send to the marketplace)
        @param fees - 2 fees (in base points) that are going to be taken on top of order amount encoded in 1 uint256
                        bytes (25,26) used for currency (0 - ETH, 1 - WETH erc-20)
                        bytes (27,28) used for dataType
                        bytes (29,30) used for the first value (goes to feeRecipientFirst)
                        bytes (31,32) are used for the second value (goes to feeRecipientSecond)
        @param data - data for market call
     */
    struct PurchaseDetails {
        Markets marketId;
        uint256 amount;
        uint fees;
        bytes data;
    }

    /**
        @notice struct for the data with additional Ddta
        @param data - data for market call
        @param additionalRoyalties - array additional Royalties (in base points plus address Royalty recipient)
     */
    struct AdditionalData {
        bytes data;
        uint[] additionalRoyalties;
    }

    constructor(
        address[11] memory marketplaces,
        //address _wyvernExchange, 0
        //address _exchangeV2, 1
        //address _seaPort_1_1, 2
        //address _x2y2, 3
        //address _looksRare, 4
        //address _sudoswap, 5
        //address _seaPort_1_4, 6
        //address _looksRareV2, 7
        //address _blur, 8
        //address _seaPort_1_5, 9
        //address _seaPort_1_6, 10
        address _weth,
        address[] memory transferProxies
    ) {
        wyvernExchange = marketplaces[0];
        exchangeV2 = marketplaces[1];
        seaPort_1_1 = marketplaces[2];
        x2y2 = marketplaces[3];
        looksRare = marketplaces[4];
        sudoswap = marketplaces[5];
        seaPort_1_4 = marketplaces[6];
        looksRareV2 = marketplaces[7];
        blur = marketplaces[8];
        seaPort_1_5 = marketplaces[9];
        seaPort_1_6 = marketplaces[10];

        weth = _weth;

        for (uint i = 0; i < transferProxies.length; ++i) {
            if (_weth != address(0)){
                IERC20Upgradeable(_weth).approve(transferProxies[i], UINT256_MAX);
            }
        }
    }

    /**
        @notice executes a single purchase
        @param purchaseDetails - deatails about the purchase (more info in PurchaseDetails struct)
        @param feeRecipientFirst - address of the first fee recipient
        @param feeRecipientSecond - address of the second fee recipient
     */
    function singlePurchase(PurchaseDetails memory purchaseDetails, address feeRecipientFirst, address feeRecipientSecond) external payable {
        requireNotPaused();
        
        //amount of WETH needed for purchases: 
        uint wethAmountNeeded = getAmountOfWethForPurchase(purchaseDetails);
        
        //transfer WETH to this contract (if needed)
        if (wethAmountNeeded > 0) {
            IERC20Upgradeable(weth).transferFrom(_msgSender(), address(this), wethAmountNeeded);
        }

        Currencies currency = getCurrency(purchaseDetails.fees);
        bool success;
        uint firstFeeAmount;
        uint secondFeeAmount;

        if (currency == Currencies.ETH) {
            (success, firstFeeAmount, secondFeeAmount) = purchase(purchaseDetails, false);
            transferFeeETH(firstFeeAmount, feeRecipientFirst);
            transferFeeETH(secondFeeAmount, feeRecipientSecond);
        } else if (currency == Currencies.WETH) {
            (success, firstFeeAmount, secondFeeAmount) = purchaseWETH(purchaseDetails, false);
            transferFeeWETH(firstFeeAmount, feeRecipientFirst);
            transferFeeWETH(secondFeeAmount, feeRecipientSecond);
        } else {
            revert("Unknown purchase currency");
        }
        
        emit Execution(success);
        
        //transfer ETH change
        transferChange();
        //transfer WETH change
        if (wethAmountNeeded > 0) {
            transferChangeWETH();
        }
    }

    /**
        @notice executes an array of purchases
        @param purchaseDetails - array of deatails about the purchases (more info in PurchaseDetails struct)
        @param feeRecipientFirst - address of the first fee recipient
        @param feeRecipientSecond - address of the second fee recipient
        @param allowFail - true if fails while executing orders are allowed, false if fail of a single order means fail of the whole batch
     */
    
    function bulkPurchase(PurchaseDetails[] memory purchaseDetails, address feeRecipientFirst, address feeRecipientSecond, bool allowFail) external payable {
        requireNotPaused();

        uint sumFirstFeesETH = 0;
        uint sumSecondFeesETH = 0;
        uint sumFirstFeesWETH = 0;
        uint sumSecondFeesWETH = 0;
        bool result = false;

        //amount of WETH needed for purchases: 
        uint wethAmountNeeded = 0;
        for (uint i = 0; i < purchaseDetails.length; ++i) {
            wethAmountNeeded = wethAmountNeeded + getAmountOfWethForPurchase(purchaseDetails[i]);
        }

        //transfer WETH to this contract (if needed)
        if (wethAmountNeeded > 0) {
            IERC20Upgradeable(weth).transferFrom(_msgSender(), address(this), wethAmountNeeded);
        }

        for (uint i = 0; i < purchaseDetails.length; ++i) {
            Currencies currency = getCurrency(purchaseDetails[i].fees);
            bool success;
            uint firstFeeAmount;
            uint secondFeeAmount;

            if (currency == Currencies.ETH) {
                (success, firstFeeAmount, secondFeeAmount) = purchase(purchaseDetails[i], allowFail);
            
                sumFirstFeesETH = sumFirstFeesETH.add(firstFeeAmount);
                sumSecondFeesETH = sumSecondFeesETH.add(secondFeeAmount);
            } else if (currency == Currencies.WETH) {
                (success, firstFeeAmount, secondFeeAmount) = purchaseWETH(purchaseDetails[i], allowFail);
            
                sumFirstFeesWETH = sumFirstFeesWETH.add(firstFeeAmount);
                sumSecondFeesWETH = sumSecondFeesWETH.add(secondFeeAmount);
            } else {
                revert("Unknown purchase currency");
            }
            
            result = result || success;
            emit Execution(success);
        }

        require(result, "no successful executions");

        //pay fees in ETH  
        transferFeeETH(sumFirstFeesETH, feeRecipientFirst);
        transferFeeETH(sumSecondFeesETH, feeRecipientSecond);

        //pay fees in WETH
        transferFeeWETH(sumFirstFeesWETH, feeRecipientFirst);
        transferFeeWETH(sumSecondFeesWETH, feeRecipientSecond);

        //transfer ETH change
        transferChange();
        //transfer WETH change
        if (wethAmountNeeded > 0) {
            transferChangeWETH();
        }
    }

    /**
        @notice executes one purchase in ETH
        @param purchaseDetails - details about the purchase
        @param allowFail - true if errors are handled, false if revert on errors
        @return result false if execution failed, true if succeded
        @return firstFeeAmount amount of the first fee of the purchase, 0 if failed
        @return secondFeeAmount amount of the second fee of the purchase, 0 if failed
     */
    function purchase(PurchaseDetails memory purchaseDetails, bool allowFail) internal returns(bool, uint, uint) {
        (bytes memory marketData, uint[] memory additionalRoyalties) = getDataAndAdditionalData (purchaseDetails.data, purchaseDetails.fees, purchaseDetails.marketId);
        uint paymentAmount = purchaseDetails.amount;
        if (purchaseDetails.marketId == Markets.SeaPort_1_1){
            (bool success,) = address(seaPort_1_1).call{value : paymentAmount}(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase SeaPort_1_1 failed");
            }
        } else if (purchaseDetails.marketId == Markets.WyvernExchange) {
            (bool success,) = address(wyvernExchange).call{value : paymentAmount}(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase wyvernExchange failed");
            }
        } else if (purchaseDetails.marketId == Markets.ExchangeV2) {
            (bool success,) = address(exchangeV2).call{value : paymentAmount}(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase rarible failed");
            }
        } else if (purchaseDetails.marketId == Markets.X2Y2) {
            Ix2y2.RunInput memory input = abi.decode(marketData, (Ix2y2.RunInput));

            if (allowFail) {
                try Ix2y2(x2y2).run{value : paymentAmount}(input) {
                } catch {
                    return (false, 0, 0);
                }
            } else {
                Ix2y2(x2y2).run{value : paymentAmount}(input);
            }

            //for every element in input.details[] getting
            // order = input.details[i].orderIdx
            // and from that order getting item = input.details[i].itemId
            for (uint i = 0; i < input.details.length; ++i) {
                uint orderId = input.details[i].orderIdx;
                uint itemId = input.details[i].itemIdx;
                bytes memory data = input.orders[orderId].items[itemId].data;
                {
                    if (input.orders[orderId].dataMask.length > 0 && input.details[i].dataReplacement.length > 0) {
                        _arrayReplace(data, input.details[i].dataReplacement, input.orders[orderId].dataMask);
                    }
                }

                // 1 = erc-721
                if (input.orders[orderId].delegateType == 1) {
                    Ix2y2.Pair721[] memory pairs = abi.decode(data, (Ix2y2.Pair721[]));

                    for (uint256 j = 0; j < pairs.length; j++) {
                        Ix2y2.Pair721 memory p = pairs[j];
                        IERC721Upgradeable(address(p.token)).safeTransferFrom(address(this), _msgSender(), p.tokenId);
                    }
                } else if (input.orders[orderId].delegateType == 2) {
                    // 2 = erc-1155
                    Ix2y2.Pair1155[] memory pairs = abi.decode(data, (Ix2y2.Pair1155[]));

                    for (uint256 j = 0; j < pairs.length; j++) {
                        Ix2y2.Pair1155 memory p = pairs[j];
                        IERC1155Upgradeable(address(p.token)).safeTransferFrom(address(this),  _msgSender(), p.tokenId, p.amount, "");
                    }
                } else {
                    revert("unknown delegateType x2y2");
                }
            }
        } else if (purchaseDetails.marketId == Markets.LooksRareOrders) {
            (LibLooksRare.TakerOrder memory takerOrder, LibLooksRare.MakerOrder memory makerOrder, bytes4 typeNft) = abi.decode(marketData, (LibLooksRare.TakerOrder, LibLooksRare.MakerOrder, bytes4));
            if (allowFail) {
                try ILooksRare(looksRare).matchAskWithTakerBidUsingETHAndWETH{value : paymentAmount}(takerOrder, makerOrder) {
                }   catch {
                    return (false, 0, 0);
                }
            } else {
                ILooksRare(looksRare).matchAskWithTakerBidUsingETHAndWETH{value : paymentAmount}(takerOrder, makerOrder);
            }
            if (typeNft == LibAsset.ERC721_ASSET_CLASS) {
                IERC721Upgradeable(makerOrder.collection).safeTransferFrom(address(this), _msgSender(), makerOrder.tokenId);
            } else if (typeNft == LibAsset.ERC1155_ASSET_CLASS) {
                IERC1155Upgradeable(makerOrder.collection).safeTransferFrom(address(this), _msgSender(), makerOrder.tokenId, makerOrder.amount, "");
            } else {
                revert("Unknown token type");
            }
        } else if (purchaseDetails.marketId == Markets.SudoSwap) {
            (bool success,) = address(sudoswap).call{value : paymentAmount}(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase sudoswap failed");
            }
        } else if (purchaseDetails.marketId == Markets.SeaPort_1_4){
            (bool success,) = address(seaPort_1_4).call{value : paymentAmount}(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase SeaPort_1_4 failed");
            }
        } else if (purchaseDetails.marketId == Markets.LooksRareV2){
            (bool success,) = address(looksRareV2).call{value : paymentAmount}(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase LooksRareV2 failed");
            }
        } else if (purchaseDetails.marketId == Markets.Blur){
            (IBlur.Input memory sell, IBlur.Input memory buy, bytes4 typeNft) = abi.decode(marketData, (IBlur.Input, IBlur.Input, bytes4));
            if (allowFail) {
                try IBlur(blur).execute{value : paymentAmount}(sell, buy) {
                }   catch {
                    return (false, 0, 0);
                }
            } else {
                IBlur(blur).execute{value : paymentAmount}(sell, buy);
            }
            if (typeNft == LibAsset.ERC721_ASSET_CLASS) {
                IERC721Upgradeable(sell.order.collection).safeTransferFrom(address(this), _msgSender(), sell.order.tokenId);
            } else if (typeNft == LibAsset.ERC1155_ASSET_CLASS) {
                IERC1155Upgradeable(sell.order.collection).safeTransferFrom(address(this), _msgSender(), sell.order.tokenId, sell.order.amount, "");
            } else {
                revert("Unknown token type");
            }
        } else if (purchaseDetails.marketId == Markets.SeaPort_1_5){
            (bool success,) = address(seaPort_1_5).call{value : paymentAmount}(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase SeaPort_1_5 failed");
            }
        } else if (purchaseDetails.marketId == Markets.SeaPort_1_6){
            (bool success,) = address(seaPort_1_6).call{value : paymentAmount}(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase SeaPort_1_6 failed");
            }
        } else {
            revert("Unknown marketId ETH");
        }

        //transferring royalties
        transferAdditionalRoyaltiesETH(additionalRoyalties, purchaseDetails.amount);
        
        (uint firstFeeAmount, uint secondFeeAmount) = getFees(purchaseDetails.fees, purchaseDetails.amount);
        return (true, firstFeeAmount, secondFeeAmount);
    }

    /**
        @notice executes one purchase in WETH
        @param purchaseDetails - details about the purchase
        @param allowFail - true if errors are handled, false if revert on errors
        @return result false if execution failed, true if succeded
        @return firstFeeAmount amount of the first fee of the purchase, 0 if failed
        @return secondFeeAmount amount of the second fee of the purchase, 0 if failed
     */
    function purchaseWETH(PurchaseDetails memory purchaseDetails, bool allowFail) internal returns(bool, uint, uint) {
        (bytes memory marketData, uint[] memory additionalRoyalties) = getDataAndAdditionalData (purchaseDetails.data, purchaseDetails.fees, purchaseDetails.marketId);

        //buying
        if (purchaseDetails.marketId == Markets.SeaPort_1_1){
            (bool success,) = address(seaPort_1_1).call(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase SeaPort_1_1 failed WETH");
            }
        } else if (purchaseDetails.marketId == Markets.ExchangeV2) {
            (bool success,) = address(exchangeV2).call(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase rarible failed WETH");
            }
        } else if (purchaseDetails.marketId == Markets.SeaPort_1_4){
            (bool success,) = address(seaPort_1_4).call(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase SeaPort_1_4 failed WETH");
            }
        } else if (purchaseDetails.marketId == Markets.SeaPort_1_5){
            (bool success,) = address(seaPort_1_5).call(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase SeaPort_1_5 failed WETH");
            }
        } else if (purchaseDetails.marketId == Markets.SeaPort_1_6){
            (bool success,) = address(seaPort_1_6).call(marketData);
            if (allowFail) {
                if (!success) {
                    return (false, 0, 0);
                }
            } else {
                require(success, "Purchase SeaPort_1_6 failed WETH");
            }
        } else {
            revert("Unknown marketId WETH");
        }
        
        //transfer royalties
        transferAdditionalRoyaltiesWETH(additionalRoyalties, purchaseDetails.amount);

        //get fees
        (uint firstFeeAmount, uint secondFeeAmount) = getFees(purchaseDetails.fees, purchaseDetails.amount);
        return (true, firstFeeAmount, secondFeeAmount);
    }

    /**
        @notice transfers ETH fee to feeRecipient
        @param feeAmount - amount to be transfered
        @param feeRecipient - address of the recipient
     */
    function transferFeeETH(uint feeAmount, address feeRecipient) internal {
        if (feeAmount > 0 && feeRecipient != address(0)) {
            LibTransfer.transferEth(feeRecipient, feeAmount);
        }
    }

    /**
        @notice transfers WETH fee to feeRecipient
        @param feeAmount - amount to be transfered
        @param feeRecipient - address of the recipient
     */
    function transferFeeWETH(uint feeAmount, address feeRecipient) internal {
        if (feeAmount > 0 && feeRecipient != address(0)) {
            IERC20Upgradeable(weth).transfer(feeRecipient, feeAmount);
        }
    }

    /**
        @notice transfers change back to sender
     */
    function transferChange() internal {
        uint ethAmount = address(this).balance;
        if (ethAmount > 0) {
            address(msg.sender).transferEth(ethAmount);
        }
    }

    /**
        @notice transfers weth change back to sender
     */
    function transferChangeWETH() internal {
        uint wethAmount = IERC20Upgradeable(weth).balanceOf(address(this));
        if (wethAmount > 0) {
            IERC20Upgradeable(weth).transfer(_msgSender(), wethAmount);
        }
    }

    /**
        @notice parses fees in base points from one uint and calculates real amount of fees
        @param fees two fees encoded in one uint, 29 and 30 bytes are used for the first fee, 31 and 32 bytes for second fee
        @param amount price of the order
        @return firstFeeAmount real amount for the first fee
        @return secondFeeAmount real amount for the second fee
     */
    function getFees(uint fees, uint amount) internal pure returns(uint, uint) {
        uint firstFee = uint(uint16(fees >> 16));
        uint secondFee = uint(uint16(fees));
        return (amount.bp(firstFee), amount.bp(secondFee));
    }

    /**
        @notice parses "fees" field to find the currency for the purchase
        @param fees field with encoded data
        @return 0 if ETH, 1 if WETH ERC-20
     */
    function getCurrency(uint fees) internal pure returns(Currencies) {
        return Currencies(uint16(fees >> 48));
    }


    /**
        @notice parses _data to data for market call and additionalData
        @param feesAndDataType 27 and 28 bytes for dataType
        @return marketData data for market call
        @return additionalRoyalties array uint256, (base point + address)
     */
    function getDataAndAdditionalData (bytes memory _data, uint feesAndDataType, Markets marketId) internal pure returns (bytes memory, uint[] memory) {
        AdditionalDataTypes dataType = AdditionalDataTypes(uint16(feesAndDataType >> 32));
        uint[] memory additionalRoyalties;

        //return no royalties if wrong data type
        if (dataType == AdditionalDataTypes.NoAdditionalData) {
            return (_data, additionalRoyalties);
        }

        if (dataType == AdditionalDataTypes.RoyaltiesAdditionalData) {
            AdditionalData memory additionalData = abi.decode(_data, (AdditionalData));

            //return no royalties if market doesn't support royalties
            if (supportsRoyalties(marketId)) {
                return (additionalData.data, additionalData.additionalRoyalties);
            } else {
                return (additionalData.data, additionalRoyalties);
            } 
        }
        
        revert("unknown additionalDataType");
    }

    /**
        @notice transfer additional royalties in ETH
        @param _additionalRoyalties array uint256 (base point + royalty recipient address)
     */
    function transferAdditionalRoyaltiesETH (uint[] memory _additionalRoyalties, uint amount) internal {
        for (uint i = 0; i < _additionalRoyalties.length; ++i) {
            if (_additionalRoyalties[i] > 0) {
                address payable account = payable(address(_additionalRoyalties[i]));
                uint basePoint = uint(_additionalRoyalties[i] >> 160);
                uint value = amount.bp(basePoint);
                transferFeeETH(value, account);
            }
        }
    }

    /**
        @notice transfer additional royalties in WETH
        @param _additionalRoyalties array uint256 (base point + royalty recipient address)
     */
    function transferAdditionalRoyaltiesWETH (uint[] memory _additionalRoyalties, uint amount) internal {
        for (uint i = 0; i < _additionalRoyalties.length; ++i) {
            if (_additionalRoyalties[i] > 0) {
                address payable account = payable(address(_additionalRoyalties[i]));
                uint basePoint = uint(_additionalRoyalties[i] >> 160);
                uint value = amount.bp(basePoint);
                transferFeeWETH(value, account);
            }
        }
    }

    // modifies `src`
    function _arrayReplace(
        bytes memory src,
        bytes memory replacement,
        bytes memory mask
    ) internal view virtual {
        require(src.length == replacement.length);
        require(src.length == mask.length);

        for (uint256 i = 0; i < src.length; ++i) {
            if (mask[i] != 0) {
                src[i] = replacement[i];
            }
        }
    }

    /**
        @notice returns true if this contract supports additional royalties for the marketplace;
        now royalties are supported for:
          1. SudoSwap
          2. LooksRare old
          3. LooksRare V2
    */
    function supportsRoyalties(Markets marketId) internal pure returns (bool){
        if (
            marketId == Markets.SudoSwap ||
            marketId == Markets.LooksRareOrders ||
            marketId == Markets.LooksRareV2
        ) {
            return true;
        }

        return false;
    }

    function getAmountOfWethForPurchase(PurchaseDetails memory detail) internal pure returns (uint) {
        uint result = 0;

        Currencies currency = getCurrency(detail.fees);

        //for every purchase with WETH we sum amount, fees and royalties needed
            if (currency == Currencies.WETH) {

                //add amount
                result = result + detail.amount;

                //add fees
                (uint firstFeeAmount, uint secondFeeAmount) = getFees(detail.fees, detail.amount);
                result = result + firstFeeAmount + secondFeeAmount;

                //add royalties
                (, uint[] memory royalties) = getDataAndAdditionalData (detail.data, detail.fees, detail.marketId);
                for (uint j = 0; j < royalties.length; ++j) {
                    uint royaltyBasePoint = uint(royalties[j] >> 160);
                    uint royaltyValue = detail.amount.bp(royaltyBasePoint);
                    result = result + royaltyValue;
                }
            }

        return result;
    }

    /**
        @notice approves weth for a list of the addresses
        @param transferProxies - array of addresses to approve WETH for
    */
    function approveWETH(address[] calldata transferProxies) external onlyOwner {
        for (uint i = 0; i < transferProxies.length; ++i) {
            IERC20Upgradeable(weth).approve(transferProxies[i], UINT256_MAX);
        }
    }

    receive() external payable {}
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;


interface IBlur {
    enum Side { Buy, Sell }
    enum SignatureVersion { Single, Bulk }
    enum AssetType { ERC721, ERC1155 }

    struct Fee {
        uint16 rate;
        address payable recipient;
    }
        
    struct Order {
        address trader;
        Side side;
        address matchingPolicy;
        address collection;
        uint256 tokenId;
        uint256 amount;
        address paymentToken;
        uint256 price;
        uint256 listingTime;
        /* Order expiration timestamp - 0 for oracle cancellations. */
        uint256 expirationTime;
        Fee[] fees;
        uint256 salt;
        bytes extraParams;
    }

    struct Input {
        Order order;
        uint8 v;
        bytes32 r;
        bytes32 s;
        bytes extraSignature;
        SignatureVersion signatureVersion;
        uint256 blockNumber;
    }

    function execute(Input calldata sell, Input calldata buy)
        external
        payable;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

import "@rarible/exchange-v2/contracts/ExchangeV2.sol";

import {RoyaltiesRegistry} from "@rarible/royalties-registry/contracts/RoyaltiesRegistry.sol";
import {TransferProxy} from "@rarible/transfer-proxy/contracts/proxy/TransferProxy.sol";
import {ERC20TransferProxy} from "@rarible/transfer-proxy/contracts/proxy/ERC20TransferProxy.sol";

interface IExchangeV2 {
    function matchOrders(
        LibOrder.Order memory orderLeft,
        bytes memory signatureLeft,
        LibOrder.Order memory orderRight,
        bytes memory signatureRight
    ) external payable;

    function directPurchase(
        LibDirectTransfer.Purchase calldata direct
    ) external payable;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

interface ILSSVMRouter {
    struct PairSwapSpecific {
        address pair;
        uint256[] nftIds;
    }

    /**
        @notice Swaps ETH into specific NFTs using multiple pairs.
        @param swapList The list of pairs to trade with and the IDs of the NFTs to buy from each.
        @param ethRecipient The address that will receive the unspent ETH input
        @param nftRecipient The address that will receive the NFT output
        @param deadline The Unix timestamp (in seconds) at/after which the swap will revert
        @return remainingValue The unspent ETH amount
     */
    function swapETHForSpecificNFTs(
        PairSwapSpecific[] calldata swapList,
        address payable ethRecipient,
        address nftRecipient,
        uint256 deadline
    )
        external
        payable
        returns (uint256 remainingValue);
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "../libraries/LibLooksRare.sol";

interface ILooksRare {
    function matchAskWithTakerBidUsingETHAndWETH(LibLooksRare.TakerOrder calldata takerBid, LibLooksRare.MakerOrder calldata makerAsk) external payable;

    /**
     * @notice This function allows a user to execute a taker bid (against a maker ask).
     * @param takerBid Taker bid struct
     * @param makerAsk Maker ask struct
     * @param makerSignature Maker signature
     * @param merkleTree Merkle tree struct (if the signature contains multiple maker orders)
     * @param affiliate Affiliate address
     */
    function executeTakerBid(LibLooksRare.Taker calldata takerBid, LibLooksRare.Maker calldata makerAsk, bytes calldata makerSignature, LibLooksRare.MerkleTree calldata merkleTree, address affiliate) external payable;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

import "../libraries/LibSeaPort.sol";

interface ISeaPort {
    function fulfillAdvancedOrder(
        LibSeaPort.AdvancedOrder calldata advancedOrder,
        LibSeaPort.CriteriaResolver[] calldata criteriaResolvers,
        bytes32 fulfillerConduitKey,
        address recipient
    ) external payable returns (bool fulfilled);

    function fulfillAvailableAdvancedOrders(
        LibSeaPort.AdvancedOrder[] memory advancedOrders,
        LibSeaPort.CriteriaResolver[] calldata criteriaResolvers,
        LibSeaPort.FulfillmentComponent[][] calldata offerFulfillments,
        LibSeaPort.FulfillmentComponent[][] calldata considerationFulfillments,
        bytes32 fulfillerConduitKey,
        address recipient,
        uint256 maximumFulfilled
    ) external payable returns (bool[] memory availableOrders, LibSeaPort.Execution[] memory executions);

    function fulfillBasicOrder(LibSeaPort.BasicOrderParameters calldata parameters)
        external
        payable
        returns (bool fulfilled);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

interface IWyvernExchange {
    function atomicMatch_(
        address[14] memory addrs,
        uint[18] memory uints,
        uint8[8] memory feeMethodsSidesKindsHowToCalls,
        bytes memory calldataBuy,
        bytes memory calldataSell,
        bytes memory replacementPatternBuy,
        bytes memory replacementPatternSell,
        bytes memory staticExtradataBuy,
        bytes memory staticExtradataSell,
        uint8[2] memory vs,
        bytes32[5] memory rssMetadata)
    external
    payable;

    enum Side {
        Buy,
        Sell
    }

    enum SaleKind {
        FixedPrice,
        DutchAuction
    }

    function calculateFinalPrice(
        Side side,
        SaleKind saleKind,
        uint256 basePrice,
        uint256 extra,
        uint256 listingTime,
        uint256 expirationTime
    ) external view returns (uint256);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

interface Ix2y2 {

    struct OrderItem {
        uint256 price;
        bytes data;
    }

    struct Pair721 {
        address token;
        uint256 tokenId;
    }

    struct Pair1155 {
        address token;
        uint256 tokenId;
        uint256 amount;
    }

    struct Order {
        uint256 salt;
        address user;
        uint256 network;
        uint256 intent;
        uint256 delegateType;
        uint256 deadline;
        address currency;
        bytes dataMask;
        OrderItem[] items;
        // signature
        bytes32 r;
        bytes32 s;
        uint8 v;
        uint8 signVersion;
    }

    struct Fee {
        uint256 percentage;
        address to;
    }

    struct SettleDetail {
        Op op;
        uint256 orderIdx;
        uint256 itemIdx;
        uint256 price;
        bytes32 itemHash;
        address executionDelegate;
        bytes dataReplacement;
        uint256 bidIncentivePct;
        uint256 aucMinIncrementPct;
        uint256 aucIncDurationSecs;
        Fee[] fees;
    }

    struct SettleShared {
        uint256 salt;
        uint256 deadline;
        uint256 amountToEth;
        uint256 amountToWeth;
        address user;
        bool canFail;
    }

    struct RunInput {
        Order[] orders;
        SettleDetail[] details;
        SettleShared shared;
        // signature
        bytes32 r;
        bytes32 s;
        uint8 v;
    }

    enum Op {
        INVALID,
        // off-chain
        COMPLETE_SELL_OFFER,
        COMPLETE_BUY_OFFER,
        CANCEL_OFFER,
        // auction
        BID,
        COMPLETE_AUCTION,
        REFUND_AUCTION,
        REFUND_AUCTION_STUCK_ITEM
    }

    function run(RunInput memory input) external payable;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@openzeppelin/contracts/access/Ownable.sol";

abstract contract IsPausable is Ownable {
    bool public paused;

    event Paused(bool paused);

    function pause(bool _paused) external onlyOwner {
        paused = _paused;
        emit Paused(_paused);
    }

    function requireNotPaused() internal view {
        require (!paused, "the contract is paused");
    }

}

File 75 of 182 : LibLooksRare.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

library LibLooksRare {
    struct MakerOrder {
        bool isOrderAsk; // true --> ask / false --> bid
        address signer; // signer of the maker order
        address collection; // collection address
        uint256 price; // price (used as )
        uint256 tokenId; // id of the token
        uint256 amount; // amount of tokens to sell/purchase (must be 1 for ERC721, 1+ for ERC1155)
        address strategy; // strategy for trade execution (e.g., DutchAuction, StandardSaleForFixedPrice)
        address currency; // currency (e.g., WETH)
        uint256 nonce; // order nonce (must be unique unless new maker order is meant to override existing one e.g., lower ask price)
        uint256 startTime; // startTime in timestamp
        uint256 endTime; // endTime in timestamp
        uint256 minPercentageToAsk; // slippage protection (9000 --> 90% of the final price must return to ask)
        bytes params; // additional parameters
        uint8 v; // v: parameter (27 or 28)
        bytes32 r; // r: parameter
        bytes32 s; // s: parameter
    }

    struct TakerOrder {
        bool isOrderAsk; // true --> ask / false --> bid
        address taker; // msg.sender
        uint256 price; // final price for the purchase
        uint256 tokenId;
        uint256 minPercentageToAsk; // // slippage protection (9000 --> 90% of the final price must return to ask)
        bytes params; // other params (e.g., tokenId)
    }

    /**
     * @notice CollectionType is used in OrderStructs.Maker's collectionType to determine the collection type being traded.
     */
    enum CollectionType {
        ERC721,
        ERC1155
    }

    /**
     * @notice QuoteType is used in OrderStructs.Maker's quoteType to determine whether the maker order is a bid or an ask.
     */
    enum QuoteType {
        Bid,
        Ask
    }
    /**
     * 1. Maker struct
     */

    /**
     * @notice Maker is the struct for a maker order.
     * @param quoteType Quote type (i.e. 0 = BID, 1 = ASK)
     * @param globalNonce Global user order nonce for maker orders
     * @param subsetNonce Subset nonce (shared across bid/ask maker orders)
     * @param orderNonce Order nonce (it can be shared across bid/ask maker orders)
     * @param strategyId Strategy id
     * @param collectionType Collection type (i.e. 0 = ERC721, 1 = ERC1155)
     * @param collection Collection address
     * @param currency Currency address (@dev address(0) = ETH)
     * @param signer Signer address
     * @param startTime Start timestamp
     * @param endTime End timestamp
     * @param price Minimum price for maker ask, maximum price for maker bid
     * @param itemIds Array of itemIds
     * @param amounts Array of amounts
     * @param additionalParameters Extra data specific for the order
     */
    struct Maker {
        QuoteType quoteType;
        uint256 globalNonce;
        uint256 subsetNonce;
        uint256 orderNonce;
        uint256 strategyId;
        CollectionType collectionType;
        address collection;
        address currency;
        address signer;
        uint256 startTime;
        uint256 endTime;
        uint256 price;
        uint256[] itemIds;
        uint256[] amounts;
        bytes additionalParameters;
    }

    /**
     * 2. Taker struct
     */

    /**
     * @notice Taker is the struct for a taker ask/bid order. It contains the parameters required for a direct purchase.
     * @dev Taker struct is matched against MakerAsk/MakerBid structs at the protocol level.
     * @param recipient Recipient address (to receive NFTs or non-fungible tokens)
     * @param additionalParameters Extra data specific for the order
     */
    struct Taker {
        address recipient;
        bytes additionalParameters;
    }

    /**
     * 3. Merkle tree struct
     */

    enum MerkleTreeNodePosition {
        Left,
        Right
    }

    /**
     * @notice MerkleTreeNode is a MerkleTree's node.
     * @param value It can be an order hash or a proof
     * @param position The node's position in its branch.
     *                 It can be left or right or none
     *                 (before the tree is sorted).
     */
    struct MerkleTreeNode {
        bytes32 value;
        MerkleTreeNodePosition position;
    }

    /**
     * @notice MerkleTree is the struct for a merkle tree of order hashes.
     * @dev A Merkle tree can be computed with order hashes.
     *      It can contain order hashes from both maker bid and maker ask structs.
     * @param root Merkle root
     * @param proof Array containing the merkle proof
     */
    struct MerkleTree {
        bytes32 root;
        MerkleTreeNode[] proof;
    }
}

File 76 of 182 : LibSeaPort.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

library LibSeaPort {
    /**
      * @dev For basic orders involving ETH / native / ERC20 <=> ERC721 / ERC1155
      *      matching, a group of six functions may be called that only requires a
      *      subset of the usual order arguments. Note the use of a "basicOrderType"
      *      enum; this represents both the usual order type as well as the "route"
      *      of the basic order (a simple derivation function for the basic order
      *      type is `basicOrderType = orderType + (4 * basicOrderRoute)`.)
      */
    struct BasicOrderParameters {
        address considerationToken; // 0x24
        uint256 considerationIdentifier; // 0x44
        uint256 considerationAmount; // 0x64
        address payable offerer; // 0x84
        address zone; // 0xa4
        address offerToken; // 0xc4
        uint256 offerIdentifier; // 0xe4
        uint256 offerAmount; // 0x104
        BasicOrderType basicOrderType; // 0x124
        uint256 startTime; // 0x144
        uint256 endTime; // 0x164
        bytes32 zoneHash; // 0x184
        uint256 salt; // 0x1a4
        bytes32 offererConduitKey; // 0x1c4
        bytes32 fulfillerConduitKey; // 0x1e4
        uint256 totalOriginalAdditionalRecipients; // 0x204
        AdditionalRecipient[] additionalRecipients; // 0x224
        bytes signature; // 0x244
    }
    /**
     * @dev Basic orders can supply any number of additional recipients, with the
     *      implied assumption that they are supplied from the offered ETH (or other
     *      native token) or ERC20 token for the order.
     */
    struct AdditionalRecipient {
        uint256 amount;
        address payable recipient;
    }

    // prettier-ignore
    enum BasicOrderType {
        // 0: no partial fills, anyone can execute
        ETH_TO_ERC721_FULL_OPEN,

        // 1: partial fills supported, anyone can execute
        ETH_TO_ERC721_PARTIAL_OPEN,

        // 2: no partial fills, only offerer or zone can execute
        ETH_TO_ERC721_FULL_RESTRICTED,

        // 3: partial fills supported, only offerer or zone can execute
        ETH_TO_ERC721_PARTIAL_RESTRICTED,

        // 4: no partial fills, anyone can execute
        ETH_TO_ERC1155_FULL_OPEN,

        // 5: partial fills supported, anyone can execute
        ETH_TO_ERC1155_PARTIAL_OPEN,

        // 6: no partial fills, only offerer or zone can execute
        ETH_TO_ERC1155_FULL_RESTRICTED,

        // 7: partial fills supported, only offerer or zone can execute
        ETH_TO_ERC1155_PARTIAL_RESTRICTED,

        // 8: no partial fills, anyone can execute
        ERC20_TO_ERC721_FULL_OPEN,

        // 9: partial fills supported, anyone can execute
        ERC20_TO_ERC721_PARTIAL_OPEN,

        // 10: no partial fills, only offerer or zone can execute
        ERC20_TO_ERC721_FULL_RESTRICTED,

        // 11: partial fills supported, only offerer or zone can execute
        ERC20_TO_ERC721_PARTIAL_RESTRICTED,

        // 12: no partial fills, anyone can execute
        ERC20_TO_ERC1155_FULL_OPEN,

        // 13: partial fills supported, anyone can execute
        ERC20_TO_ERC1155_PARTIAL_OPEN,

        // 14: no partial fills, only offerer or zone can execute
        ERC20_TO_ERC1155_FULL_RESTRICTED,

        // 15: partial fills supported, only offerer or zone can execute
        ERC20_TO_ERC1155_PARTIAL_RESTRICTED,

        // 16: no partial fills, anyone can execute
        ERC721_TO_ERC20_FULL_OPEN,

        // 17: partial fills supported, anyone can execute
        ERC721_TO_ERC20_PARTIAL_OPEN,

        // 18: no partial fills, only offerer or zone can execute
        ERC721_TO_ERC20_FULL_RESTRICTED,

        // 19: partial fills supported, only offerer or zone can execute
        ERC721_TO_ERC20_PARTIAL_RESTRICTED,

        // 20: no partial fills, anyone can execute
        ERC1155_TO_ERC20_FULL_OPEN,

        // 21: partial fills supported, anyone can execute
        ERC1155_TO_ERC20_PARTIAL_OPEN,

        // 22: no partial fills, only offerer or zone can execute
        ERC1155_TO_ERC20_FULL_RESTRICTED,

        // 23: partial fills supported, only offerer or zone can execute
        ERC1155_TO_ERC20_PARTIAL_RESTRICTED
    }

     /**
     * @dev The full set of order components, with the exception of the counter,
     *      must be supplied when fulfilling more sophisticated orders or groups of
     *      orders. The total number of original consideration items must also be
     *      supplied, as the caller may specify additional consideration items.
     */
    struct OrderParameters {
        address offerer; // 0x00
        address zone; // 0x20
        OfferItem[] offer; // 0x40
        ConsiderationItem[] consideration; // 0x60
        OrderType orderType; // 0x80
        uint256 startTime; // 0xa0
        uint256 endTime; // 0xc0
        bytes32 zoneHash; // 0xe0
        uint256 salt; // 0x100
        bytes32 conduitKey; // 0x120
        uint256 totalOriginalConsiderationItems; // 0x140
        // offer.length                          // 0x160
    }

    /**
     * @dev Orders require a signature in addition to the other order parameters.
     */
    struct Order {
        OrderParameters parameters;
        bytes signature;
    }

    struct AdvancedOrder {
        OrderParameters parameters;
        uint120 numerator;
        uint120 denominator;
        bytes signature;
        bytes extraData;
    }

    struct OfferItem {
        ItemType itemType;
        address token;
        uint256 identifierOrCriteria;
        uint256 startAmount;
        uint256 endAmount;
    }

    /**
     * @dev A consideration item has the same five components as an offer item and
     *      an additional sixth component designating the required recipient of the
     *      item.
     */
    struct ConsiderationItem {
        ItemType itemType;
        address token;
        uint256 identifierOrCriteria;
        uint256 startAmount;
        uint256 endAmount;
        address payable recipient;
    }

    // prettier-ignore
    enum OrderType {
        // 0: no partial fills, anyone can execute
        FULL_OPEN,

        // 1: partial fills supported, anyone can execute
        PARTIAL_OPEN,

        // 2: no partial fills, only offerer or zone can execute
        FULL_RESTRICTED,

        // 3: partial fills supported, only offerer or zone can execute
        PARTIAL_RESTRICTED
    }

    // prettier-ignore
    enum ItemType {
        // 0: ETH on mainnet, MATIC on polygon, etc.
        NATIVE,

        // 1: ERC20 items (ERC777 and ERC20 analogues could also technically work)
        ERC20,

        // 2: ERC721 items
        ERC721,

        // 3: ERC1155 items
        ERC1155,

        // 4: ERC721 items where a number of tokenIds are supported
        ERC721_WITH_CRITERIA,

        // 5: ERC1155 items where a number of ids are supported
        ERC1155_WITH_CRITERIA
    }

    /**
     * @dev A fulfillment is applied to a group of orders. It decrements a series of
     *      offer and consideration items, then generates a single execution
     *      element. A given fulfillment can be applied to as many offer and
     *      consideration items as desired, but must contain at least one offer and
     *      at least one consideration that match. The fulfillment must also remain
     *      consistent on all key parameters across all offer items (same offerer,
     *      token, type, tokenId, and conduit preference) as well as across all
     *      consideration items (token, type, tokenId, and recipient).
     */
    struct Fulfillment {
        FulfillmentComponent[] offerComponents;
        FulfillmentComponent[] considerationComponents;
    }

    /**
     * @dev Each fulfillment component contains one index referencing a specific
     *      order and another referencing a specific offer or consideration item.
     */
    struct FulfillmentComponent {
        uint256 orderIndex;
        uint256 itemIndex;
    }

    /**
     * @dev An execution is triggered once all consideration items have been zeroed
     *      out. It sends the item in question from the offerer to the item's
     *      recipient, optionally sourcing approvals from either this contract
     *      directly or from the offerer's chosen conduit if one is specified. An
     *      execution is not provided as an argument, but rather is derived via
     *      orders, criteria resolvers, and fulfillments (where the total number of
     *      executions will be less than or equal to the total number of indicated
     *      fulfillments) and returned as part of `matchOrders`.
     */
    struct Execution {
        ReceivedItem item;
        address offerer;
        bytes32 conduitKey;
    }

    /**
 * @dev A received item is translated from a utilized consideration item and has
 *      the same four components as a spent item, as well as an additional fifth
 *      component designating the required recipient of the item.
 */
    struct ReceivedItem {
        ItemType itemType;
        address token;
        uint256 identifier;
        uint256 amount;
        address payable recipient;
    }

    struct CriteriaResolver {
        uint256 orderIndex;
        Side side;
        uint256 index;
        uint256 identifier;
        bytes32[] criteriaProof;
    }

    // prettier-ignore
    enum Side {
        // 0: Items that can be spent
        OFFER,

        // 1: Items that must be received
        CONSIDERATION
    }
}

File 77 of 182 : WrapperHelper.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import {IERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import {IERC1155Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol";

import {IWyvernExchange} from "../../contracts/interfaces/IWyvernExchange.sol";
import {IExchangeV2} from "../../contracts/interfaces/IExchangeV2.sol";
import {LibOrder} from "../../contracts/RaribleExchangeWrapper.sol";
import {LibDirectTransfer} from "../../contracts/RaribleExchangeWrapper.sol";

import {LibSeaPort} from "../../contracts/libraries/LibSeaPort.sol";
import {ISeaPort} from "../../contracts/interfaces/ISeaPort.sol";
import {Ix2y2} from "../../contracts/interfaces/Ix2y2.sol";
import {LibLooksRare} from "../../contracts/libraries/LibLooksRare.sol";
import {ILooksRare} from "../../contracts/interfaces/ILooksRare.sol";
import {ILSSVMRouter} from "../../contracts/interfaces/ILSSVMRouter.sol";
import {IBlur} from "../../contracts/interfaces/IBlur.sol";

interface IERC1155 {
    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
}

interface IERC721 {
    function safeTransferFrom(address from, address to, uint256 tokenId) external;
    function transferFrom(address from, address to, uint256 tokenId) external;
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}

interface IMatchERC721{
    function matchERC721UsingCriteria(
        address from,
        address to,
        IERC721 token,
        uint256 tokenId,
        bytes32 root,
        bytes32[] calldata proof
    ) external returns (bool);
}

interface IMatchERC1155{
    /*This method  Merkle validator https://etherscan.io/address/0xbaf2127b49fc93cbca6269fade0f7f31df4c88a7#code
    */
    function matchERC1155UsingCriteria(
        address from,
        address to,
        IERC1155 token,
        uint256 tokenId,
        uint256 amount,
        bytes32 root,
        bytes32[] calldata proof
    ) external returns (bool);
}

/*Interface with error*/
interface IWyvernExchangeError {
    /*method is not exist in WyvernBulkExchange contract*/
    function atomicMatchError_(
        address[14] memory addrs,
        uint[18] memory uints,
        uint8[8] memory feeMethodsSidesKindsHowToCalls,
        bytes memory calldataBuy,
        bytes memory calldataSell,
        bytes memory replacementPatternBuy,
        bytes memory replacementPatternSell,
        bytes memory staticExtradataBuy,
        bytes memory staticExtradataSell,
        uint8[2] memory vs,
        bytes32[5] memory rssMetadata)
    external
    payable;
}

contract WrapperHelper {

    struct WyvernOrders {
        address[14] addrs;
        uint[18]  uints;
        uint8[8]  feeMethodsSidesKindsHowToCalls;
        bytes  calldataBuy;
        bytes  calldataSell;
        bytes  replacementPatternBuy;
        bytes  replacementPatternSell;
        bytes  staticExtradataBuy;
        bytes  staticExtradataSell;
        uint8[2]  vs;
        bytes32[5]  rssMetadata;
    }

    struct RaribleBuy {
        LibOrder.Order orderLeft;
        bytes signatureLeft;
        LibOrder.Order orderRight;
        bytes signatureRight;
    }

    struct AdditionalData {
        bytes data;
        uint[] additionalRoyalties;
    }

    function getDataWyvernAtomicMatch(WyvernOrders memory _openSeaBuy) external pure returns(bytes memory _data) {
        _data = abi.encodeWithSelector(IWyvernExchange.atomicMatch_.selector, _openSeaBuy.addrs, _openSeaBuy.uints, _openSeaBuy.feeMethodsSidesKindsHowToCalls, _openSeaBuy.calldataBuy, _openSeaBuy.calldataSell, _openSeaBuy.replacementPatternBuy, _openSeaBuy.replacementPatternSell, _openSeaBuy.staticExtradataBuy, _openSeaBuy.staticExtradataSell, _openSeaBuy.vs, _openSeaBuy.rssMetadata);
    }

    function getDataWyvernAtomicMatchWithError(WyvernOrders memory _openSeaBuy) external pure returns(bytes memory _data) {
        _data = abi.encodeWithSelector(IWyvernExchangeError.atomicMatchError_.selector, _openSeaBuy.addrs, _openSeaBuy.uints, _openSeaBuy.feeMethodsSidesKindsHowToCalls, _openSeaBuy.calldataBuy, _openSeaBuy.calldataSell, _openSeaBuy.replacementPatternBuy, _openSeaBuy.replacementPatternSell, _openSeaBuy.staticExtradataBuy, _openSeaBuy.staticExtradataSell, _openSeaBuy.vs, _openSeaBuy.rssMetadata);
    }

    function getDataERC721UsingCriteria(
        address from,
        address to,
        IERC721Upgradeable token,
        uint256 tokenId
    ) external pure returns(bytes memory _data) {
        _data = abi.encodeWithSelector(IMatchERC721.matchERC721UsingCriteria.selector, from, to, token, tokenId);
    }

    function getDataERC1155UsingCriteria(
        address from,
        address to,
        IERC1155Upgradeable token,
        uint256 tokenId,
        uint256 amount
    ) external pure returns(bytes memory _data) {
        _data = abi.encodeWithSelector(IMatchERC1155.matchERC1155UsingCriteria.selector, from, to, token, tokenId, amount);
    }

    function encodeOriginFeeIntoUint(address account, uint96 value) external pure returns(uint){
        return (uint(value) << 160) + uint(account);
    }

    function getDataDirectPurchase(LibDirectTransfer.Purchase memory data) external pure returns(bytes memory result) {
        result = abi.encodeWithSelector(IExchangeV2.directPurchase.selector, data);
    }

    function getDataSeaPortFulfillAdvancedOrder(
        LibSeaPort.AdvancedOrder memory _advancedOrder,
        LibSeaPort.CriteriaResolver[] memory _criteriaResolvers,
        bytes32 _fulfillerConduitKey,
        address _recipient
    ) external pure returns(bytes memory _data) {
        _data = abi.encodeWithSelector(ISeaPort.fulfillAdvancedOrder.selector, _advancedOrder, _criteriaResolvers, _fulfillerConduitKey, _recipient);
    }

    function getDataSeaPortFulfillAvailableAdvancedOrders(
        LibSeaPort.AdvancedOrder[] memory _orders,
        LibSeaPort.CriteriaResolver[] memory _criteriaResolvers,
        LibSeaPort.FulfillmentComponent[][] memory _offerFulfillments,
        LibSeaPort.FulfillmentComponent[][] memory _considerationFulfillments,
        bytes32 _fulfillerConduitKey,
        address _recipient,
        uint256 _maximumFulfilled
    ) external pure returns(bytes memory _data) {
        _data = abi.encodeWithSelector(
            ISeaPort.fulfillAvailableAdvancedOrders.selector,
            _orders,
            _criteriaResolvers,
            _offerFulfillments,
            _considerationFulfillments,
            _fulfillerConduitKey,
            _recipient,
            _maximumFulfilled
        );
    }

    function getDataSeaPortBasic(LibSeaPort.BasicOrderParameters calldata seaPortBasic, bytes4 typeNft) external pure returns(bytes memory _data) {
        _data = abi.encode(seaPortBasic, typeNft);
    }

    function encodeData(Ix2y2.Pair721[] calldata data) external pure returns(bytes memory){
        return abi.encode(data);
    }

    function encodeData1155(Ix2y2.Pair1155[] calldata data) external pure returns(bytes memory){
        return abi.encode(data);
    }

    function hashItem(Ix2y2.Order memory order, Ix2y2.OrderItem memory item)
        external
        pure
        returns (bytes32)
    {
        return
            keccak256(
                abi.encode(
                    order.salt,
                    order.user,
                    order.network,
                    order.intent,
                    order.delegateType,
                    order.deadline,
                    order.currency,
                    order.dataMask,
                    item
                )
            );
    }

    function encodeX2Y2Call(Ix2y2.RunInput calldata data) external pure returns(bytes memory) {
        return abi.encode(data);
    }

    
    function getDataWrapperMatchAskWithTakerBidUsingETHAndWETH(LibLooksRare.TakerOrder calldata _takerBid, LibLooksRare.MakerOrder calldata _makerAsk, bytes4 typeNft) external pure returns(bytes memory _data) {
        _data = abi.encode(_takerBid, _makerAsk, typeNft);
    }

    function encodeFees(uint first, uint second) external pure returns(uint){
        return (uint(uint16(first)) << 16) + uint(uint16(second));
    }

    function encodeFeesPlusDataType(uint dataType, uint first, uint second) external pure returns(uint){
        return (uint(uint16(dataType)) << 32) + (uint(uint16(first)) << 16) + uint(uint16(second));
    }

    function encodeCurrencyAndDataTypeAndFees(uint currency, uint dataType, uint first, uint second) external pure returns(uint){
        return (uint(uint16(currency)) << 48) + (uint(uint16(dataType)) << 32) + (uint(uint16(first)) << 16) + uint(uint16(second));
    }

    function encodeDataPlusRoyalties(AdditionalData calldata data) external pure returns(bytes memory) {
        return abi.encode(data);
    }

    function encodeBpPlusAccount(uint bp, address account) external pure returns (uint) {
        return (uint(bp) << 160) + uint(account);
    }

    function decodeFees(uint data) external pure returns(uint, uint) {
        uint first = uint(uint16(data >> 16));
        uint second = uint(uint16(data));
        return (first, second);
    }

    function encodeSudoSwapCall(
        ILSSVMRouter.PairSwapSpecific[] calldata swapList,
        address payable ethRecipient,
        address nftRecipient,
        uint256 deadline
    ) external pure returns (bytes memory _data) {
        _data = abi.encodeWithSelector(ILSSVMRouter.swapETHForSpecificNFTs.selector, swapList, ethRecipient, nftRecipient, deadline);
    }

    function encodeLooksRareV2Call(LibLooksRare.Taker calldata takerBid, LibLooksRare.Maker calldata makerAsk, bytes calldata makerSignature, LibLooksRare.MerkleTree calldata merkleTree, address affiliate) external pure returns (bytes memory _data) {
        _data = abi.encodeWithSelector(ILooksRare.executeTakerBid.selector, takerBid, makerAsk, makerSignature, merkleTree, affiliate);
    }

    function encodeBlurData(IBlur.Input memory sell, IBlur.Input memory buy, bytes4 typeNft) external pure returns(bytes memory _data) {
        _data = abi.encode(sell, buy, typeNft);
    }

}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol";
import "./LibERC1155LazyMint.sol";
import "@rarible/lib-part/contracts/LibPart.sol";

interface IERC1155LazyMint is IERC1155Upgradeable {

    event Supply(
        uint256 tokenId,
        uint256 value
    );
    event Creators(
        uint256 tokenId,
        LibPart.Part[] creators
    );

    function mintAndTransfer(
        LibERC1155LazyMint.Mint1155Data memory data,
        address to,
        uint256 _amount
    ) external;

    function transferFromOrMint(
        LibERC1155LazyMint.Mint1155Data memory data,
        address from,
        address to,
        uint256 amount
    ) external;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

import "@rarible/lib-part/contracts/LibPart.sol";

library LibERC1155LazyMint {
    bytes4 constant public ERC1155_LAZY_ASSET_CLASS = bytes4(keccak256("ERC1155_LAZY"));
    bytes4 constant _INTERFACE_ID_MINT_AND_TRANSFER = 0x6db15a0f;

    struct Mint1155Data {
        uint tokenId;
        string tokenURI;
        uint supply;
        LibPart.Part[] creators;
        LibPart.Part[] royalties;
        bytes[] signatures;
    }

    bytes32 public constant MINT_AND_TRANSFER_TYPEHASH = keccak256("Mint1155(uint256 tokenId,uint256 supply,string tokenURI,Part[] creators,Part[] royalties)Part(address account,uint96 value)");

    function hash(Mint1155Data memory data) internal pure returns (bytes32) {
        bytes32[] memory royaltiesBytes = new bytes32[](data.royalties.length);
        for (uint i = 0; i < data.royalties.length; ++i) {
            royaltiesBytes[i] = LibPart.hash(data.royalties[i]);
        }
        bytes32[] memory creatorsBytes = new bytes32[](data.creators.length);
        for (uint i = 0; i < data.creators.length; ++i) {
            creatorsBytes[i] = LibPart.hash(data.creators[i]);
        }
        return keccak256(abi.encode(
                MINT_AND_TRANSFER_TYPEHASH,
                data.tokenId,
                data.supply,
                keccak256(bytes(data.tokenURI)),
                keccak256(abi.encodePacked(creatorsBytes)),
                keccak256(abi.encodePacked(royaltiesBytes))
            ));
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "./LibERC721LazyMint.sol";
import "@rarible/lib-part/contracts/LibPart.sol";

interface IERC721LazyMint is IERC721Upgradeable {

    event Creators(
        uint256 tokenId,
        LibPart.Part[] creators
    );

    function mintAndTransfer(
        LibERC721LazyMint.Mint721Data memory data,
        address to
    ) external;

    function transferFromOrMint(
        LibERC721LazyMint.Mint721Data memory data,
        address from,
        address to
    ) external;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

import "@rarible/lib-part/contracts/LibPart.sol";

library LibERC721LazyMint {
    bytes4 constant public ERC721_LAZY_ASSET_CLASS = bytes4(keccak256("ERC721_LAZY"));
    bytes4 constant _INTERFACE_ID_MINT_AND_TRANSFER = 0x8486f69f;

    struct Mint721Data {
        uint tokenId;
        string tokenURI;
        LibPart.Part[] creators;
        LibPart.Part[] royalties;
        bytes[] signatures;
    }

    bytes32 public constant MINT_AND_TRANSFER_TYPEHASH = keccak256("Mint721(uint256 tokenId,string tokenURI,Part[] creators,Part[] royalties)Part(address account,uint96 value)");

    function hash(Mint721Data memory data) internal pure returns (bytes32) {
        bytes32[] memory royaltiesBytes = new bytes32[](data.royalties.length);
        for (uint i = 0; i < data.royalties.length; ++i) {
            royaltiesBytes[i] = LibPart.hash(data.royalties[i]);
        }
        bytes32[] memory creatorsBytes = new bytes32[](data.creators.length);
        for (uint i = 0; i < data.creators.length; ++i) {
            creatorsBytes[i] = LibPart.hash(data.creators[i]);
        }
        return keccak256(abi.encode(
                MINT_AND_TRANSFER_TYPEHASH,
                data.tokenId,
                keccak256(bytes(data.tokenURI)),
                keccak256(abi.encodePacked(creatorsBytes)),
                keccak256(abi.encodePacked(royaltiesBytes))
            ));
    }

}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "../../contracts/erc-721/IERC721LazyMint.sol";

contract ERC721LazyMintTest is IERC721LazyMint, ERC721Upgradeable {
    function mintAndTransfer(
        LibERC721LazyMint.Mint721Data memory data,
        address to
    ) external override {
        _mint(to, data.tokenId);
    }

    function transferFromOrMint(
        LibERC721LazyMint.Mint721Data memory data,
        address from,
        address to
    ) external override {
        if (_exists(data.tokenId)) {
            safeTransferFrom(from, to, data.tokenId);
        } else {
            this.mintAndTransfer(data, to);
        }
    }

    function encode(LibERC721LazyMint.Mint721Data memory data)
        external
        view
        returns (bytes memory)
    {
        return abi.encode(address(this), data);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

library LibAsset {
    bytes4 constant public ETH_ASSET_CLASS = bytes4(keccak256("ETH"));
    bytes4 constant public ERC20_ASSET_CLASS = bytes4(keccak256("ERC20"));
    bytes4 constant public ERC721_ASSET_CLASS = bytes4(keccak256("ERC721"));
    bytes4 constant public ERC1155_ASSET_CLASS = bytes4(keccak256("ERC1155"));
    bytes4 constant public COLLECTION = bytes4(keccak256("COLLECTION"));
    bytes4 constant public CRYPTO_PUNKS = bytes4(keccak256("CRYPTO_PUNKS"));

    bytes32 constant ASSET_TYPE_TYPEHASH = keccak256(
        "AssetType(bytes4 assetClass,bytes data)"
    );

    bytes32 constant ASSET_TYPEHASH = keccak256(
        "Asset(AssetType assetType,uint256 value)AssetType(bytes4 assetClass,bytes data)"
    );

    struct AssetType {
        bytes4 assetClass;
        bytes data;
    }

    struct Asset {
        AssetType assetType;
        uint value;
    }

    function hash(AssetType memory assetType) internal pure returns (bytes32) {
        return keccak256(abi.encode(
                ASSET_TYPE_TYPEHASH,
                assetType.assetClass,
                keccak256(assetType.data)
            ));
    }

    function hash(Asset memory asset) internal pure returns (bytes32) {
        return keccak256(abi.encode(
                ASSET_TYPEHASH,
                hash(asset.assetType),
                asset.value
            ));
    }

}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";

library BpLibrary {
    using SafeMathUpgradeable for uint;

    function bp(uint value, uint bpValue) internal pure returns (uint) {
        return value.mul(bpValue).div(10000);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

library LibPart {
    bytes32 public constant TYPE_HASH = keccak256("Part(address account,uint96 value)");

    struct Part {
        address payable account;
        uint96 value;
    }

    function hash(Part memory part) internal pure returns (bytes32) {
        return keccak256(abi.encode(TYPE_HASH, part.account, part.value));
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

abstract contract ERC1271 {
    bytes4 constant public ERC1271_INTERFACE_ID = 0xfb855dc9; // this.isValidSignature.selector

    bytes4 constant public ERC1271_RETURN_VALID_SIGNATURE =   0x1626ba7e;
    bytes4 constant public ERC1271_RETURN_INVALID_SIGNATURE = 0x00000000;

    /**
    * @dev Function must be implemented by deriving contract
    * @param _hash Arbitrary length data signed on the behalf of address(this)
    * @param _signature Signature byte array associated with _data
    * @return A bytes4 magic value 0x1626ba7e if the signature check passes, 0x00000000 if not
    *
    * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)
    * MUST allow external calls
    */
    function isValidSignature(bytes32 _hash, bytes memory _signature) public virtual view returns (bytes4);

    function returnIsValidSignatureMagicNumber(bool isValid) internal pure returns (bytes4) {
        return isValid ? ERC1271_RETURN_VALID_SIGNATURE : ERC1271_RETURN_INVALID_SIGNATURE;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

interface IERC1271 {

    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param _hash Hash of the data signed on the behalf of address(this)
     * @param _signature Signature byte array associated with _data
     *
     * MUST return the bytes4 magic value 0x1626ba7e when function passes.
     * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)
     * MUST allow external calls
     */
    function isValidSignature(bytes32 _hash, bytes calldata _signature) virtual external view returns (bytes4 magicValue);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

library LibSignature {
    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature)
        internal
        pure
        returns (address)
    {
        // Check the signature length
        if (signature.length != 65) {
            revert("ECDSA: invalid signature length");
        }

        // Divide the signature in r, s and v variables
        bytes32 r;
        bytes32 s;
        uint8 v;

        // ecrecover takes the signature parameters, and the only way to get them
        // currently is to use assembly.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := byte(0, mload(add(signature, 0x60)))
        }

        return recover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        require(
            uint256(s) <=
                0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
            "ECDSA: invalid signature 's' value"
        );

        // If the signature is valid (and not malleable), return the signer address
        // v > 30 is a special case, we need to adjust hash with "\x19Ethereum Signed Message:\n32"
        // and v = v - 4
        address signer;
        if (v > 30) {
            require(
                v - 4 == 27 || v - 4 == 28,
                "ECDSA: invalid signature 'v' value"
            );
            signer = ecrecover(toEthSignedMessageHash(hash), v - 4, r, s);
        } else {
            require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value");
            signer = ecrecover(hash, v, r, s);
        }

        require(signer != address(0), "ECDSA: invalid signature");

        return signer;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * replicates the behavior of the
     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]
     * JSON-RPC method.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash)
        internal
        pure
        returns (bytes32)
    {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return
            keccak256(
                abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)
            );
    }
}

//SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";

abstract contract EIP712MetaTransaction is ContextUpgradeable {
    using SafeMath for uint256;

    bytes32 private constant META_TRANSACTION_TYPEHASH = keccak256(bytes("MetaTransaction(uint256 nonce,address from,bytes functionSignature)"));
    bytes32 internal constant EIP712_DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)");

    mapping(address => uint256) private nonces;
    bytes32 internal domainSeparator;

    /*
     * Meta transaction structure.
     * No point of including value field here as if user is doing value transfer then he has the funds to pay for gas
     * He should call the desired function directly in that case.
     */
    struct MetaTransaction {
        uint256 nonce;
        address from;
        bytes functionSignature;
    }

    /*
     * Domain structure.
     * Data(information to for making metaTransaction method uniq.) about method and contract
     */
    struct EIP712Domain {
        string name;
        string version;
        address verifyingContract;
        bytes32 salt;
    }

    event MetaTransactionExecuted(address userAddress, address payable relayerAddress, bytes functionSignature);

    function __MetaTransaction_init_unchained(string memory name, string memory version) internal {
        domainSeparator = keccak256(abi.encode(
                EIP712_DOMAIN_TYPEHASH,
                keccak256(bytes(name)),
                keccak256(bytes(version)),
                address(this),
                getSalt()
            ));
    }

    function convertBytesToBytes4(bytes memory inBytes) internal pure returns (bytes4 outBytes4) {
        if (inBytes.length == 0) {
            return 0x0;
        }

        assembly {
            outBytes4 := mload(add(inBytes, 32))
        }
    }

    function executeMetaTransaction(address userAddress,
        bytes memory functionSignature, bytes32 sigR, bytes32 sigS, uint8 sigV) external payable returns (bytes memory) {
        bytes4 destinationFunctionSig = convertBytesToBytes4(functionSignature);
        require(destinationFunctionSig != msg.sig, "Wrong functionSignature");
        MetaTransaction memory metaTx = MetaTransaction({
        nonce : nonces[userAddress],
        from : userAddress,
        functionSignature : functionSignature
        });
        require(verify(userAddress, metaTx, sigR, sigS, sigV), "Signer and signature do not match");
        nonces[userAddress] = nonces[userAddress].add(1);
        // Append userAddress at the end to extract it from calling context
        (bool success, bytes memory returnData) = address(this).call(abi.encodePacked(functionSignature, userAddress));

        require(success, "Function call not successful");
        emit MetaTransactionExecuted(userAddress, msg.sender, functionSignature);
        return returnData;
    }

    function hashMetaTransaction(MetaTransaction memory metaTx) internal pure returns (bytes32) {
        return keccak256(abi.encode(
                META_TRANSACTION_TYPEHASH,
                metaTx.nonce,
                metaTx.from,
                keccak256(metaTx.functionSignature)
            ));
    }

    function getNonce(address user) external view returns (uint256 nonce) {
        nonce = nonces[user];
    }

    function verify(address user, MetaTransaction memory metaTx, bytes32 sigR, bytes32 sigS, uint8 sigV) internal view returns (bool) {
        address signer = ecrecover(toTypedMessageHash(hashMetaTransaction(metaTx)), sigV, sigR, sigS);
        require(signer != address(0), "Invalid signature");
        return signer == user;
    }

    function _msgSender() internal view virtual override returns (address payable sender) {
        if (msg.sender == address(this)) {
            bytes memory array = msg.data;
            uint256 index = msg.data.length;
            assembly {
            // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
                sender := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)
            }
        } else {
            sender = msg.sender;
        }
        return sender;
    }

    function getSalt() internal pure returns (bytes32) {
        return bytes32(getChainID());
    }

    function getChainID() internal pure returns (uint256 id) {
        assembly {
            id := chainid()
        }
    }

    function getDomainSeparator() private view returns (bytes32) {
        return domainSeparator;
    }

    /**
    * Accept message hash and returns hash message in EIP712 compatible form
    * So that it can be used to recover signer from signature signed using EIP712 formatted data
    * https://eips.ethereum.org/EIPS/eip-712
    * "\\x19" makes the encoding deterministic
    * "\\x01" is the version byte to make it compatible to EIP-191
    */
    function toTypedMessageHash(bytes32 messageHash) internal view returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", getDomainSeparator(), messageHash));
    }

    /**
         * @dev verifies the call result and bubbles up revert reason for failed calls
         *
         * @param success : outcome of forwarded call
         * @param returndata : returned data from the frowarded call
         * @param errorMessage : fallback error message to show
         */
    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure {
        if (!success) {
            // 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

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

contract OperatorRole is OwnableUpgradeable {
    mapping (address => bool) operators;

    function __OperatorRole_init() external initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
    }

    function addOperator(address operator) external onlyOwner {
        operators[operator] = true;
    }

    function removeOperator(address operator) external onlyOwner {
        operators[operator] = false;
    }

    modifier onlyOperator() {
        require(operators[_msgSender()], "OperatorRole: caller is not the operator");
        _;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
pragma abicoder v2;

import "@rarible/exchange-interfaces/contracts/IRoyaltiesProvider.sol";
import "@rarible/royalties/contracts/LibRoyaltiesV2.sol";
import "@rarible/royalties/contracts/LibRoyaltiesV1.sol";
import "@rarible/royalties/contracts/LibRoyalties2981.sol";
import "@rarible/royalties/contracts/RoyaltiesV1.sol";
import "@rarible/royalties/contracts/RoyaltiesV2.sol";
import "@rarible/royalties/contracts/IERC2981.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

contract RoyaltiesRegistry is IRoyaltiesProvider, OwnableUpgradeable {
    /// @dev deprecated
    event RoyaltiesSetForToken(address indexed token, uint indexed tokenId, LibPart.Part[] royalties);
    /// @dev emitted when royalties set for token in 
    event RoyaltiesSetForContract(address indexed token, LibPart.Part[] royalties);

    /// @dev struct to store royalties in royaltiesByToken
    struct RoyaltiesSet {
        bool initialized;
        LibPart.Part[] royalties;
    }

    /// @dev deprecated
    mapping(bytes32 => RoyaltiesSet) public royaltiesByTokenAndTokenId;
    /// @dev stores royalties for token contract, set in setRoyaltiesByToken() method
    mapping(address => RoyaltiesSet) public royaltiesByToken;
    /// @dev stores external provider and royalties type for token contract
    mapping(address => uint) public royaltiesProviders;

    /// @dev total amount or supported royalties types
    // 0 - royalties type is unset
    // 1 - royaltiesByToken, 2 - v2, 3 - v1,
    // 4 - external provider, 5 - EIP-2981
    // 6 - unsupported/nonexistent royalties type
    uint constant royaltiesTypesAmount = 6;

    function __RoyaltiesRegistry_init() external initializer {
        __Ownable_init_unchained();
    }

    /// @dev sets external provider for token contract, and royalties type = 4
    function setProviderByToken(address token, address provider) external {
        checkOwner(token);
        setRoyaltiesType(token, 4, provider);
    }

    /// @dev returns provider address for token contract from royaltiesProviders mapping
    function getProvider(address token) public view returns(address) {
        return address(royaltiesProviders[token]);
    }

    /// @dev returns royalties type for token contract
    function getRoyaltiesType(address token) external view returns(uint) {
        return _getRoyaltiesType(royaltiesProviders[token]);
    }

    /// @dev returns royalties type from uint
    function _getRoyaltiesType(uint data) internal pure returns(uint) {
        for (uint i = 1; i <= royaltiesTypesAmount; ++i) {
            if (data / 2**(256-i) == 1) {
                return i;
            }
        }
        return 0;
    }

    /// @dev sets royalties type for token contract
    function setRoyaltiesType(address token, uint royaltiesType, address royaltiesProvider) internal {
        require(royaltiesType > 0 && royaltiesType <= royaltiesTypesAmount, "wrong royaltiesType");
        royaltiesProviders[token] = uint(royaltiesProvider) + 2**(256 - royaltiesType);
    }

    /// @dev clears and sets new royalties type for token contract
    function forceSetRoyaltiesType(address token, uint royaltiesType) external {
        checkOwner(token);
        setRoyaltiesType(token, royaltiesType, getProvider(token));
    }

    /// @dev clears royalties type for token contract
    function clearRoyaltiesType(address token) external {
        checkOwner(token);
        royaltiesProviders[token] = uint(getProvider(token));
    }

    /// @dev sets royalties for token contract in royaltiesByToken mapping and royalties type = 1
    function setRoyaltiesByToken(address token, LibPart.Part[] memory royalties) external {
        checkOwner(token);
        //clearing royaltiesProviders value for the token
        delete royaltiesProviders[token];
        // setting royaltiesType = 1 for the token
        setRoyaltiesType(token, 1, address(0));
        uint sumRoyalties = 0;
        delete royaltiesByToken[token];
        for (uint i = 0; i < royalties.length; ++i) {
            require(royalties[i].account != address(0x0), "RoyaltiesByToken recipient should be present");
            require(royalties[i].value != 0, "Royalty value for RoyaltiesByToken should be > 0");
            royaltiesByToken[token].royalties.push(royalties[i]);
            sumRoyalties += royalties[i].value;
        }
        require(sumRoyalties < 10000, "Set by token royalties sum more, than 100%");
        royaltiesByToken[token].initialized = true;
        emit RoyaltiesSetForContract(token, royalties);
    }

    /// @dev checks if msg.sender is owner of this contract or owner of the token contract
    function checkOwner(address token) internal view {
        if ((owner() != _msgSender()) && (OwnableUpgradeable(token).owner() != _msgSender())) {
            revert("Token owner not detected");
        }
    }

    /// @dev calculates royalties type for token contract
    function calculateRoyaltiesType(address token, address royaltiesProvider ) internal view returns(uint) {   
        try IERC165Upgradeable(token).supportsInterface(LibRoyaltiesV2._INTERFACE_ID_ROYALTIES) returns(bool result) {
            if (result) {
                return 2;
            }
        } catch { }

        try IERC165Upgradeable(token).supportsInterface(LibRoyaltiesV1._INTERFACE_ID_FEES) returns(bool result) {
            if (result) {
                return 3;
            }
        } catch { }
        
        try IERC165Upgradeable(token).supportsInterface(LibRoyalties2981._INTERFACE_ID_ROYALTIES) returns(bool result) {
            if (result) {
                return 5;
            }
        } catch { }
        
        if (royaltiesProvider != address(0)) {
            return 4;
        }

        if (royaltiesByToken[token].initialized) {
            return 1;
        }

        return 6;
    }

    /// @dev returns royalties for token contract and token id
    function getRoyalties(address token, uint tokenId) override external returns (LibPart.Part[] memory) {
        uint royaltiesProviderData = royaltiesProviders[token];

        address royaltiesProvider = address(royaltiesProviderData);
        uint royaltiesType = _getRoyaltiesType(royaltiesProviderData);

        // case when royaltiesType is not set
        if (royaltiesType == 0) {
            // calculating royalties type for token
            royaltiesType = calculateRoyaltiesType(token, royaltiesProvider);
            
            //saving royalties type
            setRoyaltiesType(token, royaltiesType, royaltiesProvider);
        }

        //case royaltiesType = 1, royalties are set in royaltiesByToken
        if (royaltiesType == 1) {
            return royaltiesByToken[token].royalties;
        }

        //case royaltiesType = 2, royalties rarible v2
        if (royaltiesType == 2) {
            return getRoyaltiesRaribleV2(token,tokenId);
        }

        //case royaltiesType = 3, royalties rarible v1
        if (royaltiesType == 3) {
            return getRoyaltiesRaribleV1(token, tokenId);
        }

        //case royaltiesType = 4, royalties from external provider
        if (royaltiesType == 4) {
            return providerExtractor(token, tokenId, royaltiesProvider);
        }

        //case royaltiesType = 5, royalties EIP-2981
        if (royaltiesType == 5) {
            return getRoyaltiesEIP2981(token, tokenId);
        }

        // case royaltiesType = 6, unknown/empty royalties
        if (royaltiesType == 6) {
            return new LibPart.Part[](0);
        } 

        revert("something wrong in getRoyalties");
    }

    /// @dev tries to get royalties rarible-v2 for token and tokenId
    function getRoyaltiesRaribleV2(address token, uint tokenId) internal view returns (LibPart.Part[] memory) {
        try RoyaltiesV2(token).getRaribleV2Royalties(tokenId) returns (LibPart.Part[] memory result) {
            return result;
        } catch {
            return new LibPart.Part[](0);
        }
    }

    /// @dev tries to get royalties rarible-v1 for token and tokenId
    function getRoyaltiesRaribleV1(address token, uint tokenId) internal view returns (LibPart.Part[] memory) {
        RoyaltiesV1 v1 = RoyaltiesV1(token);
        address payable[] memory recipients;
        try v1.getFeeRecipients(tokenId) returns (address payable[] memory resultRecipients) {
            recipients = resultRecipients;
        } catch {
            return new LibPart.Part[](0);
        }
        uint[] memory values;
        try v1.getFeeBps(tokenId) returns (uint[] memory resultValues) {
            values = resultValues;
        } catch {
            return new LibPart.Part[](0);
        }
        if (values.length != recipients.length) {
            return new LibPart.Part[](0);
        }
        LibPart.Part[] memory result = new LibPart.Part[](values.length);
        for (uint256 i = 0; i < values.length; ++i) {
            result[i].value = uint96(values[i]);
            result[i].account = recipients[i];
        }
        return result;
    }

    /// @dev tries to get royalties EIP-2981 for token and tokenId
    function getRoyaltiesEIP2981(address token, uint tokenId) internal view returns (LibPart.Part[] memory) {
        try IERC2981(token).royaltyInfo(tokenId, LibRoyalties2981._WEIGHT_VALUE) returns (address receiver, uint256 royaltyAmount) {
            return LibRoyalties2981.calculateRoyalties(receiver, royaltyAmount);
        } catch {
            return new LibPart.Part[](0);
        }
    }

    /// @dev tries to get royalties for token and tokenId from external provider set in royaltiesProviders
    function providerExtractor(address token, uint tokenId, address providerAddress) internal returns (LibPart.Part[] memory) {
        try IRoyaltiesProvider(providerAddress).getRoyalties(token, tokenId) returns (LibPart.Part[] memory result) {
            return result;
        } catch {
            return new LibPart.Part[](0);
        }
    }

    uint256[46] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

import "@rarible/exchange-interfaces/contracts/IRoyaltiesProvider.sol";
import "./RoyaltyArtBlocks.sol";
import "@rarible/lib-bp/contracts/BpLibrary.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract RoyaltiesProviderArtBlocks is IRoyaltiesProvider, Ownable {
    using SafeMathUpgradeable for uint;
    using BpLibrary for uint;

    uint96 public artblocksPercentage = 250;

    event ArtblocksPercentageChanged(address _who, uint96 _old, uint96 _new);

    function getRoyalties(address token, uint tokenId) override external view returns(LibPart.Part[] memory) {

        RoyaltyArtBlocks artBlocks = RoyaltyArtBlocks(token);

        //gettign artist and additionalPayee royalty part
        (address artistAddress, address additionalPayee, uint256 additionalPayeePercentage, uint256 royaltyFeeByID) = artBlocks.getRoyaltyData(tokenId);

        require(additionalPayeePercentage <= 100 && royaltyFeeByID <= 100, "wrong royalties percentages from artBlocks");

        //resulting royalties
        LibPart.Part[] memory result;

        //if no artist royalty
        if (royaltyFeeByID == 0) {
            //if artblocksPercentage > 0
            if (artblocksPercentage > 0) {
                result = new LibPart.Part[](1);

                //calculating artBLocks part
                result[0].account = payable(owner());
                result[0].value = artblocksPercentage;
            }
            //if artblocksPercentage = 0 then result is empty
            return result;

        //if royaltyFeeByID > 0 and  0 < additionalPayeePercentage < 100
        } else if (additionalPayeePercentage > 0 && additionalPayeePercentage < 100) {
            result = new LibPart.Part[](3);

            //calculating artBLocks part
            result[0].account = payable(owner());
            result[0].value = artblocksPercentage;

             // additional payee percentage * 100
            uint96 additionalPart = uint96(royaltyFeeByID.mul(100).bp(additionalPayeePercentage.mul(100)));

            //artist part
            result[1].account = payable(artistAddress);
            result[1].value = uint96(royaltyFeeByID.mul(100).sub(additionalPart));

            result[2].account = payable(additionalPayee);
            result[2].value = additionalPart;
            
        //if royaltyFeeByID > 0 and additionalPayeePercentage == 0 or 100
        } else {
            result = new LibPart.Part[](2);

            //calculating artBLocks part
            result[0].account = payable(owner());
            result[0].value = artblocksPercentage;

            // additional payee percentage * 100
            uint96 additionalPart = uint96(royaltyFeeByID.mul(100).bp(additionalPayeePercentage.mul(100)));

            //artist part
            if (additionalPayeePercentage == 0) {
                result[1].account = payable(artistAddress);
                result[1].value = uint96(royaltyFeeByID.mul(100).sub(additionalPart));
            }

            //additional payee part
            if (additionalPayeePercentage == 100) {
                result[1].account = payable(additionalPayee);
                result[1].value = additionalPart;
            }
        } 

        return result;
    }

    //sets new value for artblocksPercentage
    function setArtblocksPercentage(uint96 _artblocksPercentage) onlyOwner public {
        require(_artblocksPercentage <= 10000,"_artblocksPercentage can't be > 100%");
        emit ArtblocksPercentageChanged(_msgSender(), artblocksPercentage, _artblocksPercentage);
        artblocksPercentage = _artblocksPercentage;
    }

}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

import "@rarible/exchange-interfaces/contracts/IRoyaltiesProvider.sol";
import "./RoyaltyArtBlocksV2.sol";

contract RoyaltiesProviderArtBlocksV2 is IRoyaltiesProvider {

    function getRoyalties(address token, uint tokenId) override external view returns(LibPart.Part[] memory) {
        RoyaltyArtBlocksV2 artBlocksV2 = RoyaltyArtBlocksV2(token);

        (address payable[] memory recipients, uint256[] memory bps) = artBlocksV2.getRoyalties(tokenId);
        
        uint256 len = recipients.length;

        LibPart.Part[] memory result = new LibPart.Part[](len);
        
        for (uint i = 0; i < len; i++) {
            result[i].account = recipients[i];
            result[i].value = uint96(bps[i]);
        }

        return result;
    }

}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

import "@rarible/exchange-interfaces/contracts/IRoyaltiesProvider.sol";
import "./RoyaltyV2Legacy.sol";

contract RoyaltiesProviderV2Legacy is IRoyaltiesProvider {
    function getRoyalties(address token, uint tokenId) override external view returns(LibPart.Part[] memory) {
        return RoyaltyV2Legacy(token).getRoyalties(tokenId);
    }
}

File 95 of 182 : RoyaltyArtBlocks.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
pragma abicoder v2;

import "@rarible/lib-part/contracts/LibPart.sol";

abstract contract RoyaltyArtBlocks {
    
    function getRoyaltyData(uint256 _tokenId) external virtual view returns (address artistAddress, address additionalPayee, uint256 additionalPayeePercentage, uint256 royaltyFeeByID);

}

File 96 of 182 : RoyaltyArtBlocksV2.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
pragma abicoder v2;

import "@rarible/lib-part/contracts/LibPart.sol";

abstract contract RoyaltyArtBlocksV2 {
    
    /**
     * @notice Gets royalty Basis Points (BPS) for token ID `_tokenId`.
     * This conforms to the IManifold interface designated in the Royalty
     * Registry's RoyaltyEngineV1.sol contract.
     * ref: https://github.com/manifoldxyz/royalty-registry-solidity
     * @param _tokenId Token ID to be queried.
     * @return recipients Array of royalty payment recipients
     * @return bps Array of Basis Points (BPS) allocated to each recipient,
     * aligned by index.
     * @dev reverts if invalid _tokenId
     * @dev only returns recipients that have a non-zero BPS allocation
     */
    function getRoyalties(uint256 _tokenId) 
        external 
        view
        virtual
        returns (
            address payable[] memory recipients, 
            uint256[] memory bps
        );

}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
pragma abicoder v2;

import "@rarible/lib-part/contracts/LibPart.sol";

interface RoyaltyV2Legacy {
    event RoyaltiesSet(uint256 tokenId, LibPart.Part[] royalties);

    function getRoyalties(uint256 id) external view returns (LibPart.Part[] memory);
}

File 98 of 182 : RoyaltiesV2Upgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol";
import "@rarible/royalties/contracts/LibRoyaltiesV2.sol";
import "@rarible/royalties/contracts/RoyaltiesV2.sol";

abstract contract RoyaltiesV2Upgradeable is ERC165Upgradeable, RoyaltiesV2 {
    function __RoyaltiesV2Upgradeable_init_unchained() internal initializer {
        _registerInterface(LibRoyaltiesV2._INTERFACE_ID_ROYALTIES);
    }
}

File 99 of 182 : IERC2981.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
import "@rarible/lib-part/contracts/LibPart.sol";
///
/// @dev Interface for the NFT Royalty Standard
///
//interface IERC2981 is IERC165 {
interface IERC2981 {
    /// ERC165 bytes to add to interface array - set in parent contract
    /// implementing this standard
    ///
    /// bytes4(keccak256("royaltyInfo(uint256,uint256)")) == 0x2a55205a
    /// bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;
    /// _registerInterface(_INTERFACE_ID_ERC2981);

    /// @notice Called with the sale price to determine how much royalty
    //          is owed and to whom.
    /// @param _tokenId - the NFT asset queried for royalty information
    /// @param _salePrice - the sale price of the NFT asset specified by _tokenId
    /// @return receiver - address of who should be sent the royalty payment
    /// @return royaltyAmount - the royalty payment amount for _salePrice
    function royaltyInfo(
        uint256 _tokenId,
        uint256 _salePrice
    ) external view returns (
        address receiver,
        uint256 royaltyAmount
    );
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

import "@rarible/lib-part/contracts/LibPart.sol";

library LibRoyalties2981 {
    /*
     * https://eips.ethereum.org/EIPS/eip-2981: bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;
     */
    bytes4 constant _INTERFACE_ID_ROYALTIES = 0x2a55205a;
    uint96 constant _WEIGHT_VALUE = 1000000;

    /*Method for converting amount to percent and forming LibPart*/
    function calculateRoyalties(address to, uint256 amount) internal view returns (LibPart.Part[] memory) {
        LibPart.Part[] memory result;
        if (amount == 0) {
            return result;
        }
        uint256 percent = amount * 10000 / _WEIGHT_VALUE;
        require(percent < 10000, "Royalties 2981 exceeds 100%");
        result = new LibPart.Part[](1);
        result[0].account = payable(to);
        result[0].value = uint96(percent);
        return result;
    }
}

File 101 of 182 : LibRoyaltiesV1.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

library LibRoyaltiesV1 {
    /*
     * bytes4(keccak256('getFeeBps(uint256)')) == 0x0ebd4c7f
     * bytes4(keccak256('getFeeRecipients(uint256)')) == 0xb9c4d9fb
     *
     * => 0x0ebd4c7f ^ 0xb9c4d9fb == 0xb7799584
     */
    bytes4 constant _INTERFACE_ID_FEES = 0xb7799584;
}

File 102 of 182 : LibRoyaltiesV2.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

library LibRoyaltiesV2 {
    /*
     * bytes4(keccak256('getRaribleV2Royalties(uint256)')) == 0xcad96cca
     */
    bytes4 constant _INTERFACE_ID_ROYALTIES = 0xcad96cca;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

interface RoyaltiesV1 {
    event SecondarySaleFees(uint256 tokenId, address[] recipients, uint[] bps);

    function getFeeRecipients(uint256 id) external view returns (address payable[] memory);
    function getFeeBps(uint256 id) external view returns (uint[] memory);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
pragma abicoder v2;

import "@rarible/lib-part/contracts/LibPart.sol";

interface RoyaltiesV2 {
    event RoyaltiesSet(uint256 tokenId, LibPart.Part[] royalties);

    function getRaribleV2Royalties(uint256 id) external view returns (LibPart.Part[] memory);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

import "@rarible/lib-part/contracts/LibPart.sol";

abstract contract AbstractRoyalties {
    mapping (uint256 => LibPart.Part[]) internal royalties;

    function _saveRoyalties(uint256 id, LibPart.Part[] memory _royalties) internal {
        uint256 totalValue;
        for (uint i = 0; i < _royalties.length; ++i) {
            require(_royalties[i].account != address(0x0), "Recipient should be present");
            require(_royalties[i].value != 0, "Royalty value should be positive");
            totalValue += _royalties[i].value;
            royalties[id].push(_royalties[i]);
        }
        require(totalValue < 10000, "Royalty total value should be < 10000");
        _onRoyaltiesSet(id, _royalties);
    }

    function _updateAccount(uint256 _id, address _from, address _to) internal {
        uint length = royalties[_id].length;
        for(uint i = 0; i < length; ++i) {
            if (royalties[_id][i].account == _from) {
                royalties[_id][i].account = payable(address(uint160(_to)));
            }
        }
    }

    function _onRoyaltiesSet(uint256 id, LibPart.Part[] memory _royalties) virtual internal;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

import "./AbstractRoyalties.sol";
import "../RoyaltiesV1.sol";

contract RoyaltiesV1Impl is AbstractRoyalties, RoyaltiesV1 {

    function getFeeRecipients(uint256 id) public override view returns (address payable[] memory) {
        LibPart.Part[] memory _royalties = royalties[id];
        address payable[] memory result = new address payable[](_royalties.length);
        for (uint i = 0; i < _royalties.length; ++i) {
            result[i] = address(uint160(_royalties[i].account));
        }
        return result;
    }

    function getFeeBps(uint256 id) public override view returns (uint[] memory) {
        LibPart.Part[] memory _royalties = royalties[id];
        uint[] memory result = new uint[](_royalties.length);
        for (uint i = 0; i < _royalties.length; ++i) {
            result[i] = _royalties[i].value;
        }
        return result;
    }

    function _onRoyaltiesSet(uint256 id, LibPart.Part[] memory _royalties) override internal {
        address[] memory recipients = new address[](_royalties.length);
        uint[] memory bps = new uint[](_royalties.length);
        for (uint i = 0; i < _royalties.length; ++i) {
            recipients[i] = _royalties[i].account;
            bps[i] = _royalties[i].value;
        }
        emit SecondarySaleFees(id, recipients, bps);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
pragma abicoder v2;

import "./AbstractRoyalties.sol";
import "../RoyaltiesV2.sol";
import "../IERC2981.sol";
import "../LibRoyalties2981.sol";

contract RoyaltiesV2Impl is AbstractRoyalties, RoyaltiesV2, IERC2981 {

    function getRaribleV2Royalties(uint256 id) override external view returns (LibPart.Part[] memory) {
        return royalties[id];
    }

    function _onRoyaltiesSet(uint256 id, LibPart.Part[] memory _royalties) override internal {
        emit RoyaltiesSet(id, _royalties);
    }

    /*
    *Token (ERC721, ERC721Minimal, ERC721MinimalMeta, ERC1155 ) can have a number of different royalties beneficiaries
    *calculate sum all royalties, but royalties beneficiary will be only one royalties[0].account, according to rules of IERC2981
    */
    function royaltyInfo(uint256 id, uint256 _salePrice) override external view returns (address receiver, uint256 royaltyAmount) {
        if (royalties[id].length == 0) {
            receiver = address(0);
            royaltyAmount = 0;
            return(receiver, royaltyAmount);
        }
        LibPart.Part[] memory _royalties = royalties[id];
        receiver = _royalties[0].account;
        uint percent;
        for (uint i = 0; i < _royalties.length; ++i) {
            percent += _royalties[i].value;
        }
        //don`t need require(percent < 10000, "Token royalty > 100%"); here, because check later in calculateRoyalties
        royaltyAmount = percent * _salePrice / 10000;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol";
import "../../contracts/impl/RoyaltiesV2Impl.sol";
import "../../contracts/LibRoyaltiesV2.sol";

contract TestERC1155RoyaltiesV2 is RoyaltiesV2Impl, ERC1155Upgradeable {
    function initialize() public initializer {
        _registerInterface(LibRoyaltiesV2._INTERFACE_ID_ROYALTIES);
    }
    function mint(address to, uint tokenId, uint amount, LibPart.Part[] memory _fees) external {
        _mint(to, tokenId, amount, "");
        _saveRoyalties(tokenId, _fees);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "../../contracts/impl/RoyaltiesV1Impl.sol";
import "../../contracts/LibRoyaltiesV1.sol";

contract TestERC721RoyaltiesV1 is RoyaltiesV1Impl, ERC721Upgradeable {
    function initialize() public initializer {
        _registerInterface(LibRoyaltiesV1._INTERFACE_ID_FEES);
    }
    function mint(address to, uint tokenId, LibPart.Part[] memory _fees) external {
        _mint(to, tokenId);
        _saveRoyalties(tokenId, _fees);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "../../contracts/impl/RoyaltiesV2Impl.sol";
import "../../contracts/LibRoyaltiesV2.sol";

contract TestERC721RoyaltiesV2 is RoyaltiesV2Impl, ERC721Upgradeable {
    function initialize() public initializer {
        _registerInterface(LibRoyaltiesV2._INTERFACE_ID_ROYALTIES);
    }
    function mint(address to, uint tokenId, LibPart.Part[] memory _fees) external {
        _mint(to, tokenId);
        _saveRoyalties(tokenId, _fees);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol";
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";

contract TestERC1155 is ERC1155, Pausable {
    constructor() ERC1155("uri"){

    }

    function mint(address to, uint tokenId, uint amount) external {
        _mint(to, tokenId, amount, "");
    }

    function batchSafeTransferFrom(
        address[] memory froms,
        address[] memory tos,
        uint256[] memory ids,
        uint256[] memory amounts
    ) external {
        require(froms.length == tos.length, "wrong length 1");
        require(tos.length == ids.length, "wrong length 2");
        require(ids.length == amounts.length, "wrong length 3");

        for (uint i = 0; i < froms.length; i ++) {
            safeTransferFrom(froms[i], tos[i], ids[i], amounts[i], "");
        }
    }

    function emitPauseEvent(bool paused) external {
        if (paused) {
            emit Paused(address(0));
        } else {
            emit Unpaused(address(0));
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";

contract TestERC20 is ERC20Upgradeable {
    function mint(address to, uint amount) external {
        _mint(to, amount);
    }

    function init() external {
        __ERC20_init("TestERC20", "TE20");
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "./dependencies/Ownable.sol";
import "./dependencies/RenderingContract.sol";
import "./dependencies/IERC4906.sol";


contract TestERC721 is ERC721Upgradeable, Ownable, RenderingContract, IERC4906 {
    constructor(string memory _name, string memory _symbol) public {
        __ERC721_init(_name, _symbol);
        _setupOwner(msg.sender);
    }

    function mint(address to, uint tokenId) external {
        _mint(to, tokenId);
    }

    function setBaseURI(string calldata uri) external {

    }

    function reveal(uint256 _index) external {
        emit TokenURIRevealed(_index, "test");
    }

    function getBatchIdAtIndex(uint256 _index) external view returns (uint256) {
        return 10;
    }

    function _canSetOwner() internal virtual view override returns (bool) {
        return msg.sender == owner();
    }

    function mintWithPrice(address to, uint[] memory tokenIds, address currency, uint256 pricePerToken) external {
        for (uint i = 0; i < tokenIds.length; i++) {
            _mint(to, tokenIds[i]);
        }
        IERC20Upgradeable(currency).transferFrom(msg.sender, owner(), pricePerToken * tokenIds.length);
    }

    function updateMetaData(uint256 _tokenId) external {
        emit MetadataUpdate(_tokenId);
    }

    function updateBatchMetaData(uint256 _fromTokenId, uint256 _toTokenId) external {
        emit BatchMetadataUpdate(_fromTokenId, _toTokenId);
    }

    event TokenURIRevealed(uint256 indexed index, string revealedURI);
}

File 114 of 182 : IERC4906.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.7.6;

/// @title ERC-721 Metadata Update Extension
interface IERC4906 {
    /// @dev This event emits when the metadata of a token is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFT.
    event MetadataUpdate(uint256 _tokenId);

    /// @dev This event emits when the metadata of a range of tokens is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFTs.
    event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}

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

/// @author thirdweb

/**
 *  Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading
 *  who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses
 *  information about who the contract's owner is.
 */

interface IOwnable {
    /// @dev Returns the owner of the contract.
    function owner() external view returns (address);

    /// @dev Lets a module admin set a new owner for the contract. The new owner must be a module admin.
    function setOwner(address _newOwner) external;

    /// @dev Emitted when a new Owner is set.
    event OwnerUpdated(address indexed prevOwner, address indexed newOwner);
}

// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.7.6;

/// @author thirdweb

import "./IOwnable.sol";

/**
 *  @title   Ownable
 *  @notice  Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading
 *           who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses
 *           information about who the contract's owner is.
 */

abstract contract Ownable is IOwnable {
    /// @dev Owner of the contract (purpose: OpenSea compatibility)
    address private _owner;

    /// @dev Reverts if caller is not the owner.
    modifier onlyOwner() {
        if (msg.sender != _owner) {
            revert("unauthorized");
        }
        _;
    }

    /**
     *  @notice Returns the owner of the contract.
     */
    function owner() public view override returns (address) {
        return _owner;
    }

    /**
     *  @notice Lets an authorized wallet set a new owner for the contract.
     *  @param _newOwner The address to set as the new owner of the contract.
     */
    function setOwner(address _newOwner) external override {
        if (!_canSetOwner()) {
            revert("unauthorized");
        }
        _setupOwner(_newOwner);
    }

    /// @dev Lets a contract admin set a new owner for the contract. The new owner must be a contract admin.
    function _setupOwner(address _newOwner) internal {
        address _prevOwner = _owner;
        _owner = _newOwner;

        emit OwnerUpdated(_prevOwner, _newOwner);
    }

    /// @dev Returns whether owner can be set in the given execution context.
    function _canSetOwner() internal view virtual returns (bool);
}

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

interface ITokenURIGenerator {
    function tokenURI(uint tokenId) external view returns (string memory);
}

abstract contract RenderingContract {
    ITokenURIGenerator public renderingContract;

    function setRenderingContract(ITokenURIGenerator _contract) external {
        renderingContract = _contract;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol";

abstract contract HasContractURI is ERC165Upgradeable {

    string public contractURI;

    /*
     * bytes4(keccak256('contractURI()')) == 0xe8a3d485
     */
    bytes4 private constant _INTERFACE_ID_CONTRACT_URI = 0xe8a3d485;

    function __HasContractURI_init_unchained(string memory _contractURI) internal initializer {
        contractURI = _contractURI;
        _registerInterface(_INTERFACE_ID_CONTRACT_URI);
    }

    /**
     * @dev Internal function to set the contract URI
     * @param _contractURI string URI prefix to assign
     */
    function _setContractURI(string memory _contractURI) internal {
        contractURI = _contractURI;
    }

    uint256[49] private __gap;
}

File 119 of 182 : IsPrivateCollection.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

contract IsPrivateCollection {
    /// @dev true if collection is private, false if public
    bool isPrivate;

    uint256[49] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

library LibURI {
    /// @dev checks if _tokenURI starts with base. if true returns _tokenURI, else base + _tokenURI
    function checkPrefix(string memory base, string memory _tokenURI)
        internal
        pure
        returns (string memory)
    {
        bytes memory whatBytes = bytes(base);
        bytes memory whereBytes = bytes(_tokenURI);

        if (whatBytes.length > whereBytes.length) {
            return string(abi.encodePacked(base, _tokenURI));
        }

        for (uint256 j = 0; j < whatBytes.length; j++) {
            if (whereBytes[j] != whatBytes[j]) {
                return string(abi.encodePacked(base, _tokenURI));
            }
        }

        return _tokenURI;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "./erc-1271/ERC1271Validator.sol";
import "@rarible/lazy-mint/contracts/erc-721/LibERC721LazyMint.sol";

contract Mint721Validator is ERC1271Validator {
    function __Mint721Validator_init_unchained() internal initializer {
        __EIP712_init_unchained("Mint721", "1");
    }

    function validate(address account, bytes32 hash, bytes memory signature) internal view {
        validate1271(account, hash, signature);
    }
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

abstract contract MinterAccessControl is OwnableUpgradeable {
    mapping(address => bool) private _minters;
    
    event MinterStatusChanged(address indexed minter, bool indexed status);

    function __MinterAccessControl_init() internal initializer {
        __Ownable_init_unchained();
        __MinterAccessControl_init_unchained();
    }

    function __MinterAccessControl_init_unchained() internal initializer {
    }

    /**
     * @dev Add `minter` to the list of allowed minters.
     */
    function addMinter(address minter) external onlyOwner {
        _minters[minter] = true;
        emit MinterStatusChanged(minter, true);
    }

    /**
     * @dev Add `minters` to the list of allowed minters.
     */
    function addMinters(address[] memory minters) external onlyOwner {
        for (uint i = 0; i < minters.length; ++i) {
            address minter = minters[i];
            _minters[minter] = true;
            emit MinterStatusChanged(minter, true);
        }
    }

    /**
     * @dev Revoke `_minter` from the list of allowed minters.
     */
    function removeMinter(address _minter) external onlyOwner {
        _minters[_minter] = false;
        emit MinterStatusChanged(_minter, false);
    }

    /**
     * @dev Returns `true` if `account` has been granted to minters.
     */
    function isMinter(address account) public view returns (bool) {
        return _minters[account];
    }

    uint256[50] private __gap;
}

File 123 of 182 : ERC1155RaribleBeacon.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

import "@openzeppelin/contracts/proxy/UpgradeableBeacon.sol";

contract ERC1155RaribleBeacon is UpgradeableBeacon {
    constructor(address impl) UpgradeableBeacon(impl) {

    }
}

File 124 of 182 : ERC1155RaribleBeaconMeta.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

import "@openzeppelin/contracts/proxy/UpgradeableBeacon.sol";

contract ERC1155RaribleBeaconMeta is UpgradeableBeacon {
    constructor(address impl) UpgradeableBeacon(impl) {

    }
}

File 125 of 182 : ERC721RaribleBeacon.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

import "@openzeppelin/contracts/proxy/UpgradeableBeacon.sol";

contract ERC721RaribleBeacon is UpgradeableBeacon {
    constructor(address impl) UpgradeableBeacon(impl) {

    }
}

File 126 of 182 : ERC721RaribleMinimalBeacon.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

import "@openzeppelin/contracts/proxy/UpgradeableBeacon.sol";

contract ERC721RaribleMinimalBeacon is UpgradeableBeacon {
    constructor(address impl) UpgradeableBeacon(impl) {

    }
}

File 127 of 182 : ERC721RaribleMinimalBeaconMeta.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

import "@openzeppelin/contracts/proxy/UpgradeableBeacon.sol";

contract ERC721RaribleMinimalBeaconMeta is UpgradeableBeacon {
    constructor(address impl) UpgradeableBeacon(impl) {

    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
pragma abicoder v2;

import "../erc-1155/ERC1155Rarible.sol";
import "@openzeppelin/contracts/proxy/BeaconProxy.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @dev This contract is for creating proxy to access ERC1155Rarible token.
 *
 * The beacon should be initialized before call ERC1155RaribleFactoryC2 constructor.
 *
 */
contract ERC1155RaribleFactoryC2 is Ownable{
    address public beacon;
    address transferProxy;
    address lazyTransferProxy;

    event Create1155RaribleProxy(address proxy);
    event Create1155RaribleUserProxy(address proxy);

    constructor(address _beacon, address _transferProxy, address _lazyTransferProxy) {
        beacon = _beacon;
        transferProxy = _transferProxy;
        lazyTransferProxy = _lazyTransferProxy;
    }

    function createToken(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, uint salt) external {        
        address beaconProxy = deployProxy(getData(_name, _symbol, baseURI, contractURI), salt);

        ERC1155Rarible token = ERC1155Rarible(beaconProxy);
        token.transferOwnership(_msgSender());
        emit Create1155RaribleProxy(beaconProxy);
    }
    
    function createToken(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address[] memory operators, uint salt) external {
        address beaconProxy = deployProxy(getData(_name, _symbol, baseURI, contractURI, operators), salt);

        ERC1155Rarible token = ERC1155Rarible(address(beaconProxy));
        token.transferOwnership(_msgSender());
        emit Create1155RaribleUserProxy(beaconProxy);
    }

    //deploying BeaconProxy contract with create2
    function deployProxy(bytes memory data, uint salt) internal returns(address proxy){
        bytes memory bytecode = getCreationBytecode(data);
        assembly {
            proxy := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
            if iszero(extcodesize(proxy)) {
                revert(0, 0)
            }
        }
    }

    //adding constructor arguments to BeaconProxy bytecode
    function getCreationBytecode(bytes memory _data) internal view returns (bytes memory) {
        return abi.encodePacked(type(BeaconProxy).creationCode, abi.encode(beacon, _data));
    }

    //returns address that contract with such arguments will be deployed on
    function getAddress(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, uint _salt)
        public
        view
        returns (address)
    {   
        bytes memory bytecode = getCreationBytecode(getData(_name, _symbol, baseURI, contractURI));

        bytes32 hash = keccak256(
            abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode))
        );

        return address(uint160(uint(hash)));
    }

    function getData(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI) view internal returns(bytes memory){
        return abi.encodeWithSelector(ERC1155Rarible(0).__ERC1155Rarible_init.selector, _name, _symbol, baseURI, contractURI, transferProxy, lazyTransferProxy);
    }

    //returns address that contract with such arguments will be deployed on
    function getAddress(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address[] memory operators, uint _salt)
        public
        view
        returns (address)
    {   
        bytes memory bytecode = getCreationBytecode(getData(_name, _symbol, baseURI, contractURI, operators));

        bytes32 hash = keccak256(
            abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode))
        );

        return address(uint160(uint(hash)));
    }

    function getData(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address[] memory operators) view internal returns(bytes memory){
        return abi.encodeWithSelector(ERC1155Rarible(0).__ERC1155RaribleUser_init.selector, _name, _symbol, baseURI, contractURI, operators, transferProxy, lazyTransferProxy);
    }

}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;
pragma abicoder v2;

import "../erc-721-minimal/ERC721RaribleMinimal.sol";
import "@openzeppelin/contracts/proxy/BeaconProxy.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @dev This contract is for creating proxy to access ERC721Rarible token.
 *
 * The beacon should be initialized before call ERC721RaribleFactoryC2 constructor.
 *
 */
contract ERC721RaribleFactoryC2 is Ownable {
    address public beacon;
    address transferProxy;
    address lazyTransferProxy;

    event Create721RaribleProxy(address proxy);
    event Create721RaribleUserProxy(address proxy);

    constructor(address _beacon, address _transferProxy, address _lazyTransferProxy) {
        beacon = _beacon;
        transferProxy = _transferProxy;
        lazyTransferProxy = _lazyTransferProxy;
    }

    function createToken(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, uint salt) external {
        address beaconProxy = deployProxy(getData(_name, _symbol, baseURI, contractURI), salt);
        ERC721RaribleMinimal token = ERC721RaribleMinimal(address(beaconProxy));
        token.transferOwnership(_msgSender());
        emit Create721RaribleProxy(beaconProxy);
    }

    function createToken(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address[] memory operators, uint salt) external {
        address beaconProxy = deployProxy(getData(_name, _symbol, baseURI, contractURI, operators), salt);
        ERC721RaribleMinimal token = ERC721RaribleMinimal(address(beaconProxy));
        token.transferOwnership(_msgSender());
        emit Create721RaribleUserProxy(beaconProxy);
    }

    //deploying BeaconProxy contract with create2
    function deployProxy(bytes memory data, uint salt) internal returns(address proxy){
        bytes memory bytecode = getCreationBytecode(data);
        assembly {
            proxy := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
            if iszero(extcodesize(proxy)) {
                revert(0, 0)
            }
        }
    }

    //adding constructor arguments to BeaconProxy bytecode
    function getCreationBytecode(bytes memory _data) internal view returns (bytes memory) {
        return abi.encodePacked(type(BeaconProxy).creationCode, abi.encode(beacon, _data));
    }

    //returns address that contract with such arguments will be deployed on
    function getAddress(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, uint _salt)
        public
        view
        returns (address)
    {   
        bytes memory bytecode = getCreationBytecode(getData(_name, _symbol, baseURI, contractURI));

        bytes32 hash = keccak256(
            abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode))
        );

        return address(uint160(uint(hash)));
    }

    function getData(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI) view internal returns(bytes memory){
        return abi.encodeWithSelector(ERC721RaribleMinimal(0).__ERC721Rarible_init.selector, _name, _symbol, baseURI, contractURI, transferProxy, lazyTransferProxy);
    }

    //returns address that private contract with such arguments will be deployed on
    function getAddress(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address[] memory operators, uint _salt)
        public
        view
        returns (address)
    {   
        bytes memory bytecode = getCreationBytecode(getData(_name, _symbol, baseURI, contractURI, operators));

        bytes32 hash = keccak256(
            abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode))
        );

        return address(uint160(uint(hash)));
    }

    function getData(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address[] memory operators) view internal returns(bytes memory){
        return abi.encodeWithSelector(ERC721RaribleMinimal(0).__ERC721RaribleUser_init.selector, _name, _symbol, baseURI, contractURI, operators, transferProxy, lazyTransferProxy);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "./ERC1155BurnableUpgradeable.sol";
import "./ERC1155DefaultApproval.sol";
import "./ERC1155Lazy.sol";
import "../HasContractURI.sol";

abstract contract ERC1155Base is OwnableUpgradeable, ERC1155DefaultApproval, ERC1155BurnableUpgradeable, ERC1155Lazy, HasContractURI {
    string public name;
    string public symbol;

    event BurnLazy(address indexed operator, address indexed account, uint256 id, uint256 amount);
    event BurnLazyBatch(address indexed operator, address indexed account, uint256[] ids, uint256[] amounts);
    event BaseUriChanged(string newBaseURI);

    function isApprovedForAll(address _owner, address _operator) public override(ERC1155Upgradeable, ERC1155DefaultApproval, IERC1155Upgradeable) view returns (bool) {
        return ERC1155DefaultApproval.isApprovedForAll(_owner, _operator);
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC1155Lazy, ERC165Upgradeable) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    function burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) public virtual override {
        require(ids.length == amounts.length, "ids != amounts");
        uint256[] memory leftToBurns = new uint256[](ids.length);
        uint256[] memory lazyToBurns = new uint256[](ids.length);
        for (uint i = 0; i < ids.length; ++i) {
            (leftToBurns[i], lazyToBurns[i]) = _burnLazy(ids[i], amounts[i]);
        }
        ERC1155BurnableUpgradeable.burnBatch(account, ids, leftToBurns);
        emit BurnLazyBatch(_msgSender(), account, ids, lazyToBurns);
    }

    function burn(address account, uint256 id, uint256 amount) public virtual override {
        (uint256 leftToBurn, uint256 lazyToBurn) = _burnLazy(id, amount);
        if (leftToBurn > 0) {
            //token exists, burn Minted
            ERC1155BurnableUpgradeable.burn(account, id, leftToBurn);
        }
        if (lazyToBurn > 0) {
            emit BurnLazy(_msgSender(), account, id, lazyToBurn);
        }

    }

    function _burnLazy(uint256 id, uint256 amount) internal returns (uint256 leftToBurn, uint256 lazyToBurn) {
        leftToBurn = amount;
        lazyToBurn = 0;
        address creator = address(id >> 96);
        if (creator == _msgSender()) {
            lazyToBurn = amount;
            uint supply = ERC1155Lazy._getSupply(id);
            if (supply != 0) {
                //calculate Lazy amount available for burn
                uint256 lazyBalance = supply - ERC1155Lazy._getMinted(id);
                if (amount > lazyBalance) {//need to burn more than available
                    lazyToBurn = lazyBalance;
                }
            }
            ERC1155Lazy._addMinted(id, lazyToBurn);
            leftToBurn = amount - lazyToBurn;
        }
    }

    function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual override(ERC1155Upgradeable, ERC1155Lazy) {
        ERC1155Lazy._mint(account, id, amount, data);
    }

    function __ERC1155Base_init_unchained(string memory _name, string memory _symbol) internal {
        name = _name;
        symbol = _symbol;
    }

    function uri(uint id) external view override(ERC1155BaseURI, ERC1155Upgradeable) virtual returns (string memory) {
        return _tokenURI(id);
    }

    function setBaseURI(string memory newBaseURI) external onlyOwner {
        super._setBaseURI(newBaseURI);

        emit BaseUriChanged(newBaseURI);
    }

    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol";
import "../LibURI.sol";

import "./ERC1155Upgradeable.sol";

contract ERC1155BaseURI is ERC1155Upgradeable {
    using StringsUpgradeable for uint;

    // Optional mapping for token URIs
    mapping (uint256 => string) private _tokenURIs;

    // Base URI
    string private _baseURI;

    /**
    * @dev Returns the base URI set via {_setBaseURI}. This will be
    * automatically added as a prefix in {tokenURI} to each token's URI, or
    * to the token ID if no specific URI is set for that token ID.
    */
    function baseURI() public view virtual returns (string memory) {
        return _baseURI;
    }

    function uri(uint id) external view override virtual returns (string memory) {
        return _tokenURI(id);
    }

    function _tokenURI(uint256 tokenId) internal view virtual returns (string memory) {
        string memory __tokenURI = _tokenURIs[tokenId];
        string memory base = baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return __tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(__tokenURI).length > 0) {
            return LibURI.checkPrefix(base, __tokenURI);
        }
        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
        return string(abi.encodePacked(base, tokenId.toString()));
    }

    /**
     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _setTokenURI(uint256 tokenId, string memory _uri) internal virtual {
        _tokenURIs[tokenId] = _uri;
        emit URI(_tokenURI(tokenId), tokenId);
    }

    /**
     * @dev Internal function to set the base URI for all token IDs. It is
     * automatically added as a prefix to the value returned in {tokenURI},
     * or to the token ID if {tokenURI} is empty.
     */
    function _setBaseURI(string memory baseURI_) internal virtual {
        _baseURI = baseURI_;
    }

    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./ERC1155Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";

/**
 * @dev Extension of {ERC1155} that allows token holders to destroy both their
 * own tokens and those that they have been approved to use.
 *
 * _Available since v3.1._
 */
abstract contract ERC1155BurnableUpgradeable is Initializable, ERC1155Upgradeable {
    function __ERC1155Burnable_init() internal {
        __Context_init_unchained();
        __ERC165_init_unchained();
        __ERC1155Burnable_init_unchained();
    }

    function __ERC1155Burnable_init_unchained() internal {
    }
    function burn(address account, uint256 id, uint256 value) public virtual {
        require(
            account == _msgSender() || isApprovedForAll(account, _msgSender()),
            "ERC1155: caller is not owner nor approved"
        );

        _burn(account, id, value);
    }

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

        _burnBatch(account, ids, values);
    }
    
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "./ERC1155Upgradeable.sol";

abstract contract ERC1155DefaultApproval is ERC1155Upgradeable {
    mapping(address => bool) private defaultApprovals;

    event DefaultApproval(address indexed operator, bool hasApproval);

    function _setDefaultApproval(address operator, bool hasApproval) internal {
        defaultApprovals[operator] = hasApproval;
        emit DefaultApproval(operator, hasApproval);
    }

    function isApprovedForAll(address _owner, address _operator) public virtual override view returns (bool) {
        return defaultApprovals[_operator] || super.isApprovedForAll(_owner, _operator);
    }
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "./ERC1155Upgradeable.sol";
import "@rarible/royalties/contracts/impl/RoyaltiesV2Impl.sol";
import "@rarible/royalties-upgradeable/contracts/RoyaltiesV2Upgradeable.sol";
import "@rarible/lazy-mint/contracts/erc-1155/IERC1155LazyMint.sol";
import "./Mint1155Validator.sol";
import "./ERC1155BaseURI.sol";

abstract contract ERC1155Lazy is IERC1155LazyMint, ERC1155BaseURI, Mint1155Validator, RoyaltiesV2Upgradeable, RoyaltiesV2Impl {
    using SafeMathUpgradeable for uint;

    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    bytes4 private constant _INTERFACE_ID_ERC1155 = 0xd9b67a26;
    bytes4 private constant _INTERFACE_ID_ERC1155_METADATA_URI = 0x0e89341c;

    mapping(uint256 => LibPart.Part[]) private creators;
    mapping(uint => uint) private supply;
    mapping(uint => uint) private minted;

    function __ERC1155Lazy_init_unchained() internal {

    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165Upgradeable, ERC165Upgradeable) returns (bool) {
        return interfaceId == LibERC1155LazyMint._INTERFACE_ID_MINT_AND_TRANSFER
        || interfaceId == LibRoyaltiesV2._INTERFACE_ID_ROYALTIES
        || interfaceId == LibRoyalties2981._INTERFACE_ID_ROYALTIES
        || interfaceId == _INTERFACE_ID_ERC165
        || interfaceId == _INTERFACE_ID_ERC1155
        || interfaceId == _INTERFACE_ID_ERC1155_METADATA_URI;
    }

    function transferFromOrMint(
        LibERC1155LazyMint.Mint1155Data memory data,
        address from,
        address to,
        uint256 amount
    ) override external {
        uint balance = balanceOf(from, data.tokenId);
        uint left = amount;
        if (balance != 0) {
            uint transfer = amount;
            if (balance < amount) {
                transfer = balance;
            }
            safeTransferFrom(from, to, data.tokenId, transfer, "");
            left = amount - transfer;
        }
        if (left > 0) {
            require(from == data.creators[0].account, "wrong order maker");
            mintAndTransfer(data, to, left);
        }
    }

    function mintAndTransfer(LibERC1155LazyMint.Mint1155Data memory data, address to, uint256 _amount) public override virtual {
        address minter = address(data.tokenId >> 96);
        address sender = _msgSender();

        require(minter == sender || isApprovedForAll(minter, sender), "ERC1155: transfer caller is not approved");
        require(_amount > 0, "amount incorrect");

        if (supply[data.tokenId] == 0) {
            require(minter == data.creators[0].account, "tokenId incorrect");
            require(data.supply > 0, "supply incorrect");
            require(data.creators.length == data.signatures.length);

            bytes32 hash = LibERC1155LazyMint.hash(data);
            for (uint i = 0; i < data.creators.length; ++i) {
                address creator = data.creators[i].account;
                if (creator != sender) {
                    validate(creator, hash, data.signatures[i]);
                }
            }

            _saveSupply(data.tokenId, data.supply);
            _saveRoyalties(data.tokenId, data.royalties);
            _saveCreators(data.tokenId, data.creators);
            _setTokenURI(data.tokenId, data.tokenURI);
        }

        _mint(to, data.tokenId, _amount, "");
        if (minter != to) {
            emit TransferSingle(sender, address(0), minter, data.tokenId, _amount);
            emit TransferSingle(sender, minter, to, data.tokenId, _amount);
        } else {
            emit TransferSingle(sender, address(0), to, data.tokenId, _amount);
        }
    }

    function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual override {
        uint newMinted = amount.add(minted[id]);
        require(newMinted <= supply[id], "more than supply");
        minted[id] = newMinted;

        require(account != address(0), "ERC1155: mint to the zero address");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);

        _balances[id][account] = _balances[id][account].add(amount);

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

    function _saveSupply(uint tokenId, uint _supply) internal {
        require(supply[tokenId] == 0);
        supply[tokenId] = _supply;
        emit Supply(tokenId, _supply);
    }

    function _saveCreators(uint tokenId, LibPart.Part[] memory _creators) internal {
        LibPart.Part[] storage creatorsOfToken = creators[tokenId];
        uint total = 0;
        for (uint i = 0; i < _creators.length; ++i) {
            require(_creators[i].account != address(0x0), "Account should be present");
            require(_creators[i].value != 0, "Creator share should be positive");
            creatorsOfToken.push(_creators[i]);
            total = total.add(_creators[i].value);
        }
        require(total == 10000, "total amount of creators share should be 10000");
        emit Creators(tokenId, _creators);
    }

    function updateAccount(uint256 _id, address _from, address _to) external {
        require(_msgSender() == _from, "not allowed");
        super._updateAccount(_id, _from, _to);
    }

    function getCreators(uint256 _id) external view returns (LibPart.Part[] memory) {
        return creators[_id];
    }

    function _addMinted(uint256 tokenId, uint amount) internal {
        minted[tokenId] += amount;
    }

    function _getMinted(uint256 tokenId) internal view returns (uint) {
        return minted[tokenId];
    }

    function _getSupply(uint256 tokenId) internal view returns (uint) {
        return supply[tokenId];
    }

    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "./ERC1155Base.sol";
import "../IsPrivateCollection.sol";
import "../access/MinterAccessControl.sol";

contract ERC1155Rarible is ERC1155Base, IsPrivateCollection, MinterAccessControl {
    event CreateERC1155Rarible(address owner, string name, string symbol);
    event CreateERC1155RaribleUser(address owner, string name, string symbol);

    function __ERC1155RaribleUser_init(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address[] memory operators, address transferProxy, address lazyTransferProxy) external virtual {
        __ERC1155Rarible_init_unchained(_name, _symbol, baseURI, contractURI, transferProxy, lazyTransferProxy);
        
        isPrivate = true;
        emit CreateERC1155RaribleUser(_msgSender(), _name, _symbol);
    }
    
    function __ERC1155Rarible_init(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address transferProxy, address lazyTransferProxy) external virtual {
        __ERC1155Rarible_init_unchained(_name, _symbol, baseURI, contractURI, transferProxy, lazyTransferProxy);

        isPrivate = false;
        emit CreateERC1155Rarible(_msgSender(), _name, _symbol);
    }

    function __ERC1155Rarible_init_unchained(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address transferProxy, address lazyTransferProxy) internal initializer {
        __Ownable_init_unchained();
        __ERC1155Lazy_init_unchained();
        __ERC165_init_unchained();
        __Context_init_unchained();
        __Mint1155Validator_init_unchained();
        __ERC1155_init_unchained("");
        __HasContractURI_init_unchained(contractURI);
        __ERC1155Burnable_init_unchained();
        __RoyaltiesV2Upgradeable_init_unchained();
        __ERC1155Base_init_unchained(_name, _symbol);
        __MinterAccessControl_init_unchained();
        _setBaseURI(baseURI);

        //setting default approver for transferProxies
        _setDefaultApproval(transferProxy, true);
        _setDefaultApproval(lazyTransferProxy, true);
    }

    function mintAndTransfer(LibERC1155LazyMint.Mint1155Data memory data, address to, uint256 _amount) public override {
        if (isPrivate){
          require(owner() == data.creators[0].account || isMinter(data.creators[0].account), "not owner or minter");
        }
        super.mintAndTransfer(data, to, _amount);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155MetadataURIUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155ReceiverUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";

/**
 *
 * @dev Implementation of the basic standard multi-token.
 * See https://eips.ethereum.org/EIPS/eip-1155
 * Originally based on code by Enjin: https://github.com/enjin/erc-1155
 *
 * _Available since v3.1._
 */
contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155Upgradeable, IERC1155MetadataURIUpgradeable {
    using SafeMathUpgradeable for uint256;
    using AddressUpgradeable for address;

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

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

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

    /*
     *     bytes4(keccak256('balanceOf(address,uint256)')) == 0x00fdd58e
     *     bytes4(keccak256('balanceOfBatch(address[],uint256[])')) == 0x4e1273f4
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,uint256,bytes)')) == 0xf242432a
     *     bytes4(keccak256('safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)')) == 0x2eb2c2d6
     *
     *     => 0x00fdd58e ^ 0x4e1273f4 ^ 0xa22cb465 ^
     *        0xe985e9c5 ^ 0xf242432a ^ 0x2eb2c2d6 == 0xd9b67a26
     */
    bytes4 private constant _INTERFACE_ID_ERC1155 = 0xd9b67a26;

    /*
     *     bytes4(keccak256('uri(uint256)')) == 0x0e89341c
     */
    bytes4 private constant _INTERFACE_ID_ERC1155_METADATA_URI = 0x0e89341c;

    /**
     * @dev See {_setURI}.
     */
    function __ERC1155_init(string memory uri_) internal initializer {
        __Context_init_unchained();
        __ERC165_init_unchained();
        __ERC1155_init_unchained(uri_);
    }

    function __ERC1155_init_unchained(string memory uri_) internal initializer {
        _setURI(uri_);

        // register the supported interfaces to conform to ERC1155 via ERC165
        _registerInterface(_INTERFACE_ID_ERC1155);

        // register the supported interfaces to conform to ERC1155MetadataURI via ERC165
        _registerInterface(_INTERFACE_ID_ERC1155_METADATA_URI);
    }

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

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

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

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

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

        return batchBalances;
    }

    /**
     * @dev See {IERC1155-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(_msgSender() != operator, "ERC1155: setting approval status for self");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

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

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

        address operator = _msgSender();

        _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);

        _balances[id][from] = _balances[id][from].sub(amount, "ERC1155: insufficient balance for transfer");
        _balances[id][to] = _balances[id][to].add(amount);

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

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

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

        address operator = _msgSender();

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

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

            _balances[id][from] = _balances[id][from].sub(
                amount,
                "ERC1155: insufficient balance for transfer"
            );
            _balances[id][to] = _balances[id][to].add(amount);
        }

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

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

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

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

        address operator = _msgSender();

        _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);

        _balances[id][account] = _balances[id][account].add(amount);
        emit TransferSingle(operator, address(0), account, id, amount);

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

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

        address operator = _msgSender();

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

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

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

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

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

        address operator = _msgSender();

        _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");

        _balances[id][account] = _balances[id][account].sub(
            amount,
            "ERC1155: burn amount exceeds balance"
        );

        emit TransferSingle(operator, account, address(0), id, amount);
    }

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

        address operator = _msgSender();

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

        for (uint i = 0; i < ids.length; ++i) {
            _balances[ids[i]][account] = _balances[ids[i]][account].sub(
                amounts[i],
                "ERC1155: burn amount exceeds balance"
            );
        }

        emit TransferBatch(operator, account, address(0), ids, amounts);
    }

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

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

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

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

        return array;
    }
    uint256[47] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "../erc-1271/ERC1271Validator.sol";
import "@rarible/lazy-mint/contracts/erc-1155/LibERC1155LazyMint.sol";

contract Mint1155Validator is ERC1271Validator {
    function __Mint1155Validator_init_unchained() internal initializer {
        __EIP712_init_unchained("Mint1155", "1");
    }

    function validate(address account, bytes32 hash, bytes memory signature) internal view {
        validate1271(account, hash, signature);
    }
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@rarible/meta-tx/contracts/EIP712MetaTransaction.sol";
import "../ERC1155Base.sol";
import "../../IsPrivateCollection.sol";
import "../../access/MinterAccessControl.sol";

contract ERC1155RaribleMeta is ERC1155Base, IsPrivateCollection, MinterAccessControl, EIP712MetaTransaction {
    event CreateERC1155Rarible(address owner, string name, string symbol);
    event CreateERC1155RaribleUser(address owner, string name, string symbol);

    function __ERC1155RaribleUser_init(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address[] memory operators, address transferProxy, address lazyTransferProxy) external {
        __ERC1155Rarible_init_unchained(_name, _symbol, baseURI, contractURI, transferProxy, lazyTransferProxy);

        __MetaTransaction_init_unchained("ERC1155RaribleUserMeta", "1");
        
        isPrivate = true;

        emit CreateERC1155RaribleUser(_msgSender(), _name, _symbol);
    }
    
    function __ERC1155Rarible_init(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address transferProxy, address lazyTransferProxy) external {
        __ERC1155Rarible_init_unchained(_name, _symbol, baseURI, contractURI, transferProxy, lazyTransferProxy);

        __MetaTransaction_init_unchained("ERC1155RaribleMeta", "1");

        isPrivate = false;

        emit CreateERC1155Rarible(_msgSender(), _name, _symbol);
    }

    function _msgSender() internal view virtual override(ContextUpgradeable, EIP712MetaTransaction) returns (address payable) {
        return super._msgSender();
    }

    function __ERC1155Rarible_init_unchained(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address transferProxy, address lazyTransferProxy) internal initializer {
        __Ownable_init_unchained();
        __ERC1155Lazy_init_unchained();
        __ERC165_init_unchained();
        __Context_init_unchained();
        __Mint1155Validator_init_unchained();
        __ERC1155_init_unchained("");
        __HasContractURI_init_unchained(contractURI);
        __ERC1155Burnable_init_unchained();
        __RoyaltiesV2Upgradeable_init_unchained();
        __ERC1155Base_init_unchained(_name, _symbol);
        __MinterAccessControl_init_unchained();
        _setBaseURI(baseURI);

        //setting default approver for transferProxies
        _setDefaultApproval(transferProxy, true);
        _setDefaultApproval(lazyTransferProxy, true);
    }

    function mintAndTransfer(LibERC1155LazyMint.Mint1155Data memory data, address to, uint256 _amount) public override {
        if (isPrivate){
          require(owner() == data.creators[0].account || isMinter(data.creators[0].account), "not owner or minter");
        }
        super.mintAndTransfer(data, to, _amount);
    }
}

File 139 of 182 : ERC1271Validator.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@rarible/lib-signature/contracts/ERC1271.sol";
import "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol";
import "@rarible/lib-signature/contracts/LibSignature.sol";

abstract contract ERC1271Validator is EIP712Upgradeable {
    using AddressUpgradeable for address;
    using LibSignature for bytes32;

    string constant SIGNATURE_ERROR = "signature verification error";
    bytes4 constant internal MAGICVALUE = 0x1626ba7e;

    function validate1271(address signer, bytes32 structHash, bytes memory signature) internal view {
        bytes32 hash = _hashTypedDataV4(structHash);

        address signerFromSig;
        if (signature.length == 65) {
            signerFromSig = hash.recover(signature);
        }
        if  (signerFromSig != signer) {
            if (signer.isContract()) {
                require(
                    ERC1271(signer).isValidSignature(hash, signature) == MAGICVALUE,
                    SIGNATURE_ERROR
                );
            } else {
                revert(SIGNATURE_ERROR);
            }
        }
    }
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "./ERC721BurnableUpgradeableMinimal.sol";
import "./ERC721DefaultApprovalMinimal.sol";
import "./ERC721LazyMinimal.sol";
import "../HasContractURI.sol";

abstract contract ERC721BaseMinimal is OwnableUpgradeable, ERC721DefaultApprovalMinimal, ERC721BurnableUpgradeableMinimal, ERC721LazyMinimal, HasContractURI {
    event BaseUriChanged(string newBaseURI);

    function _isApprovedOrOwner(address spender, uint256 tokenId) internal virtual override(ERC721UpgradeableMinimal, ERC721DefaultApprovalMinimal) view returns (bool) {
        return ERC721DefaultApprovalMinimal._isApprovedOrOwner(spender, tokenId);
    }

    function isApprovedForAll(address owner, address operator) public view virtual override(ERC721DefaultApprovalMinimal, ERC721UpgradeableMinimal, IERC721Upgradeable) returns (bool) {
        return ERC721DefaultApprovalMinimal.isApprovedForAll(owner, operator);
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, ERC721LazyMinimal) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    function tokenURI(uint256 tokenId) public view virtual override(ERC721UpgradeableMinimal, ERC721LazyMinimal) returns (string memory) {
        return ERC721LazyMinimal.tokenURI(tokenId);
    }

    function _clearMetadata(uint256 tokenId) internal override(ERC721UpgradeableMinimal, ERC721LazyMinimal) virtual {
        return ERC721LazyMinimal._clearMetadata(tokenId);
    }

    function _emitMintEvent(address to, uint tokenId) internal override(ERC721UpgradeableMinimal, ERC721LazyMinimal) virtual {
        return ERC721LazyMinimal._emitMintEvent(to, tokenId);
    }

    function setBaseURI(string memory newBaseURI) external onlyOwner {
        super._setBaseURI(newBaseURI);

        emit BaseUriChanged(newBaseURI);
    }

    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "./ERC721UpgradeableMinimal.sol";

/**
 * @title ERC721 Burnable Token
 * @dev ERC721 Token that can be irreversibly burned (destroyed).
 */
abstract contract ERC721BurnableUpgradeableMinimal is Initializable, ContextUpgradeable, ERC721UpgradeableMinimal {
    function __ERC721Burnable_init() internal initializer {
        __Context_init_unchained();
        __ERC165_init_unchained();
        __ERC721Burnable_init_unchained();
    }

    function __ERC721Burnable_init_unchained() internal initializer {
    }
    /**
     * @dev Burns `tokenId`. See {ERC721-_burn}.
     *
     * Requirements:
     *
     * - The caller must own `tokenId` or be an approved operator.
     */
    function burn(uint256 tokenId) public virtual {
        if(!_exists(tokenId)) {
            address owner = address(tokenId >> 96);
            require(owner == _msgSender(), "ERC721Burnable: caller is not owner, not burn");
            _setBurned(tokenId);
        } else {
            //solhint-disable-next-line max-line-length
            require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721Burnable: caller is not owner nor approved");
            _burn(tokenId);
        }
    }

    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "./ERC721UpgradeableMinimal.sol";

abstract contract ERC721DefaultApprovalMinimal is ERC721UpgradeableMinimal {
    mapping(address => bool) private defaultApprovals;

    event DefaultApproval(address indexed operator, bool hasApproval);

    function _setDefaultApproval(address operator, bool hasApproval) internal {
        defaultApprovals[operator] = hasApproval;
        emit DefaultApproval(operator, hasApproval);
    }

    function _isApprovedOrOwner(address spender, uint256 tokenId) internal virtual override view returns (bool) {
        return defaultApprovals[spender] || super._isApprovedOrOwner(spender, tokenId);
    }

    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return defaultApprovals[operator] || super.isApprovedForAll(owner, operator);
    }
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "./ERC721UpgradeableMinimal.sol";
import "@rarible/royalties/contracts/impl/RoyaltiesV2Impl.sol";
import "@rarible/royalties-upgradeable/contracts/RoyaltiesV2Upgradeable.sol";
import "@rarible/lazy-mint/contracts/erc-721/IERC721LazyMint.sol";
import "../Mint721Validator.sol";
import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import "./ERC721URI.sol";

abstract contract ERC721LazyMinimal is IERC721LazyMint, ERC721UpgradeableMinimal, Mint721Validator, RoyaltiesV2Upgradeable, RoyaltiesV2Impl, ERC721URI {
    using SafeMathUpgradeable for uint;

    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;

    // tokenId => creators
    mapping(uint256 => LibPart.Part[]) private creators;

    function __ERC721Lazy_init_unchained() internal initializer {

    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165Upgradeable, ERC165Upgradeable) returns (bool) {
        return interfaceId == LibERC721LazyMint._INTERFACE_ID_MINT_AND_TRANSFER
        || interfaceId == LibRoyaltiesV2._INTERFACE_ID_ROYALTIES
        || interfaceId == LibRoyalties2981._INTERFACE_ID_ROYALTIES
        || interfaceId == _INTERFACE_ID_ERC165
        || interfaceId == _INTERFACE_ID_ERC721
        || interfaceId == _INTERFACE_ID_ERC721_METADATA
        || interfaceId == _INTERFACE_ID_ERC721_ENUMERABLE;
    }

    function transferFromOrMint(
        LibERC721LazyMint.Mint721Data memory data,
        address from,
        address to
    ) override external {
        if (_exists(data.tokenId)) {
            safeTransferFrom(from, to, data.tokenId);
        } else {
            require(from == data.creators[0].account, "wrong order maker");
            mintAndTransfer(data, to);
        }
    }

    function mintAndTransfer(LibERC721LazyMint.Mint721Data memory data, address to) public override virtual {
        address minter = address(data.tokenId >> 96);
        address sender = _msgSender();

        require(minter == data.creators[0].account, "tokenId incorrect");
        require(data.creators.length == data.signatures.length);
        require(minter == sender || isApprovedForAll(minter, sender), "ERC721: transfer caller is not owner nor approved");

        bytes32 hash = LibERC721LazyMint.hash(data);
        for (uint i = 0; i < data.creators.length; ++i) {
            address creator = data.creators[i].account;
            if (creator != sender) {
                validate(creator, hash, data.signatures[i]);
            }
        }

        _safeMint(to, data.tokenId);
        _saveRoyalties(data.tokenId, data.royalties);
        _saveCreators(data.tokenId, data.creators);
        _setTokenURI(data.tokenId, data.tokenURI);
    }

    function _emitMintEvent(address to, uint tokenId) internal override virtual {
        address minter = address(tokenId >> 96);
        if (minter != to) {
            emit Transfer(address(0), minter, tokenId);
            emit Transfer(minter, to, tokenId);
        } else {
            emit Transfer(address(0), to, tokenId);
        }
    }

    function _saveCreators(uint tokenId, LibPart.Part[] memory _creators) internal {
        LibPart.Part[] storage creatorsOfToken = creators[tokenId];
        uint total = 0;
        for (uint i = 0; i < _creators.length; ++i) {
            require(_creators[i].account != address(0x0), "Account should be present");
            require(_creators[i].value != 0, "Creator share should be positive");
            creatorsOfToken.push(_creators[i]);
            total = total.add(_creators[i].value);
        }
        require(total == 10000, "total amount of creators share should be 10000");
        emit Creators(tokenId, _creators);
    }

    function updateAccount(uint256 _id, address _from, address _to) external {
        require(_msgSender() == _from, "not allowed");
        super._updateAccount(_id, _from, _to);
    }

    function getCreators(uint256 _id) external view returns (LibPart.Part[] memory) {
        return creators[_id];
    }

    function tokenURI(uint256 tokenId) public view virtual override(ERC721UpgradeableMinimal, ERC721URI) returns (string memory) {
        return ERC721URI.tokenURI(tokenId);
    }

    function _clearMetadata(uint256 tokenId) internal override(ERC721UpgradeableMinimal, ERC721URI) virtual {
        return ERC721URI._clearMetadata(tokenId);
    }

    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "./ERC721BaseMinimal.sol";
import "../IsPrivateCollection.sol";
import "../access/MinterAccessControl.sol";

contract ERC721RaribleMinimal is ERC721BaseMinimal, IsPrivateCollection, MinterAccessControl {
    event CreateERC721Rarible(address owner, string name, string symbol);
    event CreateERC721RaribleUser(address owner, string name, string symbol);

    function __ERC721RaribleUser_init(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address[] memory operators, address transferProxy, address lazyTransferProxy) external virtual {
        __ERC721Rarible_init_unchained(_name, _symbol, baseURI, contractURI, transferProxy, lazyTransferProxy);

        isPrivate = true;
        emit CreateERC721RaribleUser(_msgSender(), _name, _symbol);
    }

    function __ERC721Rarible_init(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address transferProxy, address lazyTransferProxy) external virtual {
        __ERC721Rarible_init_unchained(_name, _symbol, baseURI, contractURI, transferProxy, lazyTransferProxy);

        isPrivate = false;
        emit CreateERC721Rarible(_msgSender(), _name, _symbol);
    }

    function __ERC721Rarible_init_unchained(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address transferProxy, address lazyTransferProxy) internal initializer {
        _setBaseURI(baseURI);
        __ERC721Lazy_init_unchained();
        __RoyaltiesV2Upgradeable_init_unchained();
        __Context_init_unchained();
        __ERC165_init_unchained();
        __Ownable_init_unchained();
        __ERC721Burnable_init_unchained();
        __Mint721Validator_init_unchained();
        __MinterAccessControl_init_unchained();
        __HasContractURI_init_unchained(contractURI);
        __ERC721_init_unchained(_name, _symbol);

        //setting default approver for transferProxies
        _setDefaultApproval(transferProxy, true);
        _setDefaultApproval(lazyTransferProxy, true);
    }

    function mintAndTransfer(LibERC721LazyMint.Mint721Data memory data, address to) public override virtual {
        if (isPrivate){
            require(owner() == data.creators[0].account || isMinter(data.creators[0].account), "not owner or minter");
        }
        super.mintAndTransfer(data, to);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "./ERC721UpgradeableMinimal.sol";
import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol";
import "../LibURI.sol";

/**
 * @title ERC721 Burnable Token
 * @dev ERC721 Token that can be irreversibly burned (destroyed).
 */
abstract contract ERC721URI is ContextUpgradeable, ERC721UpgradeableMinimal {
    using StringsUpgradeable for uint256;

    // Optional mapping for token URIs
    mapping (uint256 => string) private _tokenURIs;

    // Base URI
    string private _baseURI;

    /**
     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
        require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
        _tokenURIs[tokenId] = _tokenURI;
    }

    /**
     * @dev Internal function to set the base URI for all token IDs. It is
     * automatically added as a prefix to the value returned in {tokenURI},
     * or to the token ID if {tokenURI} is empty.
     */
    function _setBaseURI(string memory baseURI_) internal virtual {
        _baseURI = baseURI_;
    }

    /**
    * @dev Returns the base URI set via {_setBaseURI}. This will be
    * automatically added as a prefix in {tokenURI} to each token's URI, or
    * to the token ID if no specific URI is set for that token ID.
    */
    function baseURI() public view virtual returns (string memory) {
        return _baseURI;
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _clearMetadata(uint256 tokenId) internal override virtual {
        // Clear metadata (if any)
        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }
    }

    /**
     * @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 _tokenURI = _tokenURIs[tokenId];
        string memory base = baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return LibURI.checkPrefix(base, _tokenURI);
        }
        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
        return string(abi.encodePacked(base, tokenId.toString()));
    }

    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721MetadataUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721UpgradeableMinimal is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable {
    using AddressUpgradeable for address;
    using StringsUpgradeable 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;

    /*
     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
     *
     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
     */
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;

    /*
     *     bytes4(keccak256('name()')) == 0x06fdde03
     *     bytes4(keccak256('symbol()')) == 0x95d89b41
     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
     *
     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
     */
    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;

    // Mapping from token ID to flag == true, means token already burned
    mapping(uint256 => bool) private _burnedTokens;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    function __ERC721_init(string memory name_, string memory symbol_) internal initializer {
        __Context_init_unchained();
        __ERC165_init_unchained();
        __ERC721_init_unchained(name_, symbol_);
    }

    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {
        _name = name_;
        _symbol = symbol_;

        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721);
        _registerInterface(_INTERFACE_ID_ERC721_METADATA);
    }

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

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721UpgradeableMinimal.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 {
        require(operator != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_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 = ERC721UpgradeableMinimal.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(!_burnedTokens[tokenId], "token already burned");
        require(!_exists(tokenId), "ERC721: token already minted");

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

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

        _emitMintEvent(to, tokenId);
    }

    function _emitMintEvent(address to, uint tokenId) internal virtual {
        emit Transfer(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 = ERC721UpgradeableMinimal.ownerOf(tokenId);

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

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

        _clearMetadata(tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];
        //set token is burned
        _setBurned(tokenId);

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

    /*Set token with tokenId burned*/
    function _setBurned(uint256 tokenId) internal {
        _burnedTokens[tokenId] = true;
    }

    function _clearMetadata(uint256 tokenId) internal virtual {
    }

    /**
     * @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(ERC721UpgradeableMinimal.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        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);
    }

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

    /**
     * @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 IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721ReceiverUpgradeable.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 {}
    uint256[43] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@rarible/meta-tx/contracts/EIP712MetaTransaction.sol";
import "../ERC721BaseMinimal.sol";
import "../../IsPrivateCollection.sol";
import "../../access/MinterAccessControl.sol";

contract ERC721RaribleMeta is ERC721BaseMinimal, IsPrivateCollection, MinterAccessControl, EIP712MetaTransaction {
    event CreateERC721Rarible(address owner, string name, string symbol);
    event CreateERC721RaribleUser(address owner, string name, string symbol);

    function __ERC721RaribleUser_init(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address[] memory operators, address transferProxy, address lazyTransferProxy) external {
        __ERC721Rarible_init_unchained(_name, _symbol, baseURI, contractURI, transferProxy, lazyTransferProxy);

        __MetaTransaction_init_unchained("ERC721RaribleUserMeta", "1");

        isPrivate = true;

        emit CreateERC721RaribleUser(_msgSender(), _name, _symbol);
    }

    function __ERC721Rarible_init(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address transferProxy, address lazyTransferProxy) external {
        __ERC721Rarible_init_unchained(_name, _symbol, baseURI, contractURI, transferProxy, lazyTransferProxy);

        __MetaTransaction_init_unchained("ERC721RaribleMeta", "1");

        isPrivate = false;

        emit CreateERC721Rarible(_msgSender(), _name, _symbol);
    }

    function _msgSender() internal view virtual override(ContextUpgradeable, EIP712MetaTransaction) returns (address payable) {
        return super._msgSender();
    }

    function __ERC721Rarible_init_unchained(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address transferProxy, address lazyTransferProxy) internal initializer {
        _setBaseURI(baseURI);
        __ERC721Lazy_init_unchained();
        __RoyaltiesV2Upgradeable_init_unchained();
        __Context_init_unchained();
        __ERC165_init_unchained();
        __Ownable_init_unchained();
        __ERC721Burnable_init_unchained();
        __Mint721Validator_init_unchained();
        __MinterAccessControl_init_unchained();
        __HasContractURI_init_unchained(contractURI);
        __ERC721_init_unchained(_name, _symbol);

        //setting default approver for transferProxies
        _setDefaultApproval(transferProxy, true);
        _setDefaultApproval(lazyTransferProxy, true);
    }

    function mintAndTransfer(LibERC721LazyMint.Mint721Data memory data, address to) public override virtual {
        if (isPrivate){
            require(owner() == data.creators[0].account || isMinter(data.creators[0].account), "not owner or minter");
        }
        super.mintAndTransfer(data, to);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "./ERC721BurnableUpgradeable.sol";
import "./ERC721DefaultApproval.sol";
import "./ERC721Lazy.sol";
import "../HasContractURI.sol";

abstract contract ERC721Base is OwnableUpgradeable, ERC721DefaultApproval, ERC721BurnableUpgradeable, ERC721Lazy, HasContractURI {

    event BaseUriChanged(string newBaseURI);

    function _isApprovedOrOwner(address spender, uint256 tokenId) internal virtual override(ERC721Upgradeable, ERC721DefaultApproval) view returns (bool) {
        return ERC721DefaultApproval._isApprovedOrOwner(spender, tokenId);
    }

    function isApprovedForAll(address owner, address operator) public view virtual override(ERC721DefaultApproval, ERC721Upgradeable, IERC721Upgradeable) returns (bool) {
        return ERC721DefaultApproval.isApprovedForAll(owner, operator);
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, ERC721Lazy) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    function _mint(address to, uint256 tokenId) internal override(ERC721Lazy, ERC721Upgradeable) {
        super._mint(to, tokenId);
    }

    function setBaseURI(string memory newBaseURI) external onlyOwner {
        super._setBaseURI(newBaseURI);

        emit BaseUriChanged(newBaseURI);
    }

    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "./ERC721Upgradeable.sol";

/**
 * @title ERC721 Burnable Token
 * @dev ERC721 Token that can be irreversibly burned (destroyed).
 */
abstract contract ERC721BurnableUpgradeable is Initializable, ContextUpgradeable, ERC721Upgradeable {
    function __ERC721Burnable_init() internal initializer {
        __Context_init_unchained();
        __ERC165_init_unchained();
        __ERC721Burnable_init_unchained();
    }

    function __ERC721Burnable_init_unchained() internal initializer {
    }
    /**
     * @dev Burns `tokenId`. See {ERC721-_burn}.
     *
     * Requirements:
     *
     * - The caller must own `tokenId` or be an approved operator.
     */
    function burn(uint256 tokenId) public virtual {
        if(!_exists(tokenId)) {
            address owner = address(tokenId >> 96);
            require(owner == _msgSender(), "ERC721Burnable: caller is not owner, not burn");
            _setBurned(tokenId);
        } else {
            //solhint-disable-next-line max-line-length
            require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721Burnable: caller is not owner nor approved");
            _burn(tokenId);
        }
    }
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "./ERC721Upgradeable.sol";

abstract contract ERC721DefaultApproval is ERC721Upgradeable {
    mapping(address => bool) private defaultApprovals;

    event DefaultApproval(address indexed operator, bool hasApproval);

    function _setDefaultApproval(address operator, bool hasApproval) internal {
        defaultApprovals[operator] = hasApproval;
        emit DefaultApproval(operator, hasApproval);
    }

    function _isApprovedOrOwner(address spender, uint256 tokenId) internal virtual override view returns (bool) {
        return defaultApprovals[spender] || super._isApprovedOrOwner(spender, tokenId);
    }

    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return defaultApprovals[operator] || super.isApprovedForAll(owner, operator);
    }
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "./ERC721Upgradeable.sol";
import "@rarible/royalties/contracts/impl/RoyaltiesV2Impl.sol";
import "@rarible/royalties-upgradeable/contracts/RoyaltiesV2Upgradeable.sol";
import "@rarible/lazy-mint/contracts/erc-721/IERC721LazyMint.sol";
import "../Mint721Validator.sol";

abstract contract ERC721Lazy is IERC721LazyMint, ERC721Upgradeable, Mint721Validator, RoyaltiesV2Upgradeable, RoyaltiesV2Impl {
    using SafeMathUpgradeable for uint;
    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;
    using EnumerableMapUpgradeable for EnumerableMapUpgradeable.UintToAddressMap;

    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;

    // tokenId => creators
    mapping(uint256 => LibPart.Part[]) private creators;

    function __ERC721Lazy_init_unchained() internal initializer {

    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165Upgradeable, ERC165Upgradeable) returns (bool) {
        return interfaceId == LibERC721LazyMint._INTERFACE_ID_MINT_AND_TRANSFER
        || interfaceId == LibRoyaltiesV2._INTERFACE_ID_ROYALTIES
        || interfaceId == LibRoyalties2981._INTERFACE_ID_ROYALTIES
        || interfaceId == _INTERFACE_ID_ERC165
        || interfaceId == _INTERFACE_ID_ERC721
        || interfaceId == _INTERFACE_ID_ERC721_METADATA
        || interfaceId == _INTERFACE_ID_ERC721_ENUMERABLE;
    }

    function transferFromOrMint(
        LibERC721LazyMint.Mint721Data memory data,
        address from,
        address to
    ) override external {
        if (_exists(data.tokenId)) {
            safeTransferFrom(from, to, data.tokenId);
        } else {
            require(from == data.creators[0].account, "wrong order maker");
            mintAndTransfer(data, to);
        }
    }

    function mintAndTransfer(LibERC721LazyMint.Mint721Data memory data, address to) public override virtual {
        address minter = address(data.tokenId >> 96);
        address sender = _msgSender();

        require(minter == data.creators[0].account, "tokenId incorrect");
        require(data.creators.length == data.signatures.length);
        require(minter == sender || isApprovedForAll(minter, sender), "ERC721: transfer caller is not owner nor approved");

        bytes32 hash = LibERC721LazyMint.hash(data);
        for (uint i = 0; i < data.creators.length; ++i) {
            address creator = data.creators[i].account;
            if (creator != sender) {
                validate(creator, hash, data.signatures[i]);
            }
        }

        _safeMint(to, data.tokenId);
        _saveRoyalties(data.tokenId, data.royalties);
        _saveCreators(data.tokenId, data.creators);
        _setTokenURI(data.tokenId, data.tokenURI);
    }

    function _mint(address to, uint256 tokenId) internal virtual override {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_burned(tokenId), "token already burned");
        require(!_exists(tokenId), "ERC721: token already minted");

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

        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

        address minter = address(tokenId >> 96);
        if (minter != to) {
            emit Transfer(address(0), minter, tokenId);
            emit Transfer(minter, to, tokenId);
        } else {
            emit Transfer(address(0), to, tokenId);
        }
    }

    function _saveCreators(uint tokenId, LibPart.Part[] memory _creators) internal {
        LibPart.Part[] storage creatorsOfToken = creators[tokenId];
        uint total = 0;
        for (uint i = 0; i < _creators.length; ++i) {
            require(_creators[i].account != address(0x0), "Account should be present");
            require(_creators[i].value != 0, "Creator share should be positive");
            creatorsOfToken.push(_creators[i]);
            total = total.add(_creators[i].value);
        }
        require(total == 10000, "total amount of creators share should be 10000");
        emit Creators(tokenId, _creators);
    }

    function updateAccount(uint256 _id, address _from, address _to) external {
        require(_msgSender() == _from, "not allowed");
        super._updateAccount(_id, _from, _to);
    }

    function getCreators(uint256 _id) external view returns (LibPart.Part[] memory) {
        return creators[_id];
    }

    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "./ERC721Base.sol";

contract ERC721Rarible is ERC721Base {

    event CreateERC721Rarible(address owner, string name, string symbol);

    function __ERC721Rarible_init(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address transferProxy, address lazyTransferProxy) external initializer {
        __ERC721Rarible_init_unchained(_name, _symbol, baseURI, contractURI, transferProxy, lazyTransferProxy);
        emit CreateERC721Rarible(_msgSender(), _name, _symbol);
    }

    function __ERC721Rarible_init_unchained(string memory _name, string memory _symbol, string memory baseURI, string memory contractURI, address transferProxy, address lazyTransferProxy) internal {
        _setBaseURI(baseURI);
        __ERC721Lazy_init_unchained();
        __RoyaltiesV2Upgradeable_init_unchained();
        __Context_init_unchained();
        __ERC165_init_unchained();
        __Ownable_init_unchained();
        __ERC721Burnable_init_unchained();
        __Mint721Validator_init_unchained();
        __HasContractURI_init_unchained(contractURI);
        __ERC721_init_unchained(_name, _symbol);

        //setting default approver for transferProxies
        _setDefaultApproval(transferProxy, true);
        _setDefaultApproval(lazyTransferProxy, true);
    }

    uint256[50] private __gap;
}

File 153 of 182 : ERC721Upgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721MetadataUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721EnumerableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/EnumerableMapUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import "../LibURI.sol";

/**
 * @title ERC721 Non-Fungible Token Standard basic implementation
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable, IERC721EnumerableUpgradeable {
    using SafeMathUpgradeable for uint256;
    using AddressUpgradeable for address;
    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;
    using EnumerableMapUpgradeable for EnumerableMapUpgradeable.UintToAddressMap;
    using StringsUpgradeable for uint256;

    // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;

    // Mapping from holder address to their (enumerable) set of owned tokens
    mapping (address => EnumerableSetUpgradeable.UintSet) _holderTokens;

    // Enumerable mapping from token ids to their owners
    EnumerableMapUpgradeable.UintToAddressMap _tokenOwners;

    // 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;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Optional mapping for token URIs
    mapping (uint256 => string) private _tokenURIs;

    // Base URI
    string private _baseURI;

    /*
     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
     *
     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
     */
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;

    /*
     *     bytes4(keccak256('name()')) == 0x06fdde03
     *     bytes4(keccak256('symbol()')) == 0x95d89b41
     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
     *
     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
     */
    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;

    /*
     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd
     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
     *
     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
     */
    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;

    // Mapping from token ID to flag == true, means token already burned
    mapping(uint256 => bool) private _burnedTokens;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    function __ERC721_init(string memory name_, string memory symbol_) internal initializer {
        __Context_init_unchained();
        __ERC165_init_unchained();
        __ERC721_init_unchained(name_, symbol_);
    }

    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {
        _name = name_;
        _symbol = symbol_;

        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721);
        _registerInterface(_INTERFACE_ID_ERC721_METADATA);
        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
    }

    /**
     * @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 _holderTokens[owner].length();
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
    }

    /**
     * @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 _tokenURI = _tokenURIs[tokenId];
        string memory base = baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return LibURI.checkPrefix(base, _tokenURI);
        }
        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
        return string(abi.encodePacked(base, tokenId.toString()));
    }

    /**
    * @dev Returns the base URI set via {_setBaseURI}. This will be
    * automatically added as a prefix in {tokenURI} to each token's URI, or
    * to the token ID if no specific URI is set for that token ID.
    */
    function baseURI() public view virtual returns (string memory) {
        return _baseURI;
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        return _holderTokens[owner].at(index);
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds
        return _tokenOwners.length();
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        (uint256 tokenId, ) = _tokenOwners.at(index);
        return tokenId;
    }

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

        require(_msgSender() == owner || ERC721Upgradeable.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 {
        require(operator != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_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 _tokenOwners.contains(tokenId);
    }

    /**
     * @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 = ERC721Upgradeable.ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || ERC721Upgradeable.isApprovedForAll(owner, spender));
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     d*
     * - `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(!_burnedTokens[tokenId], "token already burned");
        require(!_exists(tokenId), "ERC721: token already minted");

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

        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

        emit Transfer(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 = ERC721Upgradeable.ownerOf(tokenId); // internal owner

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

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

        // Clear metadata (if any)
        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }

        _holderTokens[owner].remove(tokenId);

        _tokenOwners.remove(tokenId);
        _setBurned(tokenId);
        emit Transfer(owner, address(0), tokenId);
    }

    /*Returns true if token with tokenId already burned*/
    function _burned(uint256 tokenId) internal returns (bool) {
        return _burnedTokens[tokenId];
    }

    /*Set token with tokenId burned*/
    function _setBurned(uint256 tokenId) internal {
        _burnedTokens[tokenId] = true;
    }

    /**
     * @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(ERC721Upgradeable.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); // internal 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);

        _holderTokens[from].remove(tokenId);
        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
        require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
        _tokenURIs[tokenId] = _tokenURI;
    }

    /**
     * @dev Internal function to set the base URI for all token IDs. It is
     * automatically added as a prefix to the value returned in {tokenURI},
     * or to the token ID if {tokenURI} is empty.
     */
    function _setBaseURI(string memory baseURI_) internal virtual {
        _baseURI = baseURI_;
    }

    /**
     * @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()) {
            return true;
        }
        bytes memory returndata = to.functionCall(abi.encodeWithSelector(
            IERC721ReceiverUpgradeable(to).onERC721Received.selector,
            _msgSender(),
            from,
            tokenId,
            _data
        ), "ERC721: transfer to non ERC721Receiver implementer");
        bytes4 retval = abi.decode(returndata, (bytes4));
        return (retval == _ERC721_RECEIVED);
    }

    function _approve(address to, uint256 tokenId) private {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId); // internal owner
    }

    /**
     * @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 { }
    uint256[40] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

import "@rarible/lazy-mint/contracts/erc-721/LibERC721LazyMint.sol";
import "@rarible/lazy-mint/contracts/erc-1155/LibERC1155LazyMint.sol";

import "@rarible/exchange-interfaces/contracts/IRoyaltiesProvider.sol";

import "@rarible/lib-bp/contracts/BpLibrary.sol";

import "./interfaces/ITransferManager.sol";

abstract contract RaribleTransferManager is OwnableUpgradeable, ITransferManager {
    using BpLibrary for uint;
    using SafeMathUpgradeable for uint;

    ProtocolFeeData public protocolFee;
    IRoyaltiesProvider public royaltiesRegistry;

    //deprecated
    address private defaultFeeReceiver;
    // deprecated
    mapping(address => address) private feeReceivers;

    /// @dev event that's emitted when ProtocolFeeData buyerAmount changes
    event BuyerFeeAmountChanged(uint oldValue, uint newValue);

    /// @dev event that's emitted when ProtocolFeeData sellerAmount changes
    event SellerFeeAmountChanged(uint oldValue, uint newValue);

    /// @dev event that's emitted when ProtocolFeeData receiver changes
    event FeeReceiverChanged(address oldValue, address newValue);

    /// @dev struct to store protocol fee - receiver address, buyer fee amount (in bp), seller fee amount (in bp)
    struct ProtocolFeeData {
        address receiver;
        uint48 buyerAmount;
        uint48 sellerAmount;
    }

    /**
        @notice initialises RaribleTransferManager state
        @param newProtocolFee deprecated
        @param newDefaultFeeReceiver deprecated
        @param newRoyaltiesProvider royaltiesRegistry contract address
     */
    function __RaribleTransferManager_init_unchained(
        uint newProtocolFee,
        address newDefaultFeeReceiver,
        IRoyaltiesProvider newRoyaltiesProvider
    ) internal initializer {
        royaltiesRegistry = newRoyaltiesProvider;
    }

    function setRoyaltiesRegistry(IRoyaltiesProvider newRoyaltiesRegistry) external onlyOwner {
        royaltiesRegistry = newRoyaltiesRegistry;
    }

    function setPrtocolFeeReceiver(address _receiver) public onlyOwner {
        emit FeeReceiverChanged(protocolFee.receiver, _receiver);
        protocolFee.receiver = _receiver;
    }

    function setPrtocolFeeBuyerAmount(uint48 _buyerAmount) public onlyOwner {
        emit BuyerFeeAmountChanged(protocolFee.buyerAmount, _buyerAmount);
        protocolFee.buyerAmount = _buyerAmount;
    }

    function setPrtocolFeeSellerAmount(uint48 _sellerAmount) public onlyOwner {
        emit SellerFeeAmountChanged(protocolFee.sellerAmount, _sellerAmount);
        protocolFee.sellerAmount = _sellerAmount;
    }

    function setAllProtocolFeeData(address _receiver, uint48 _buyerAmount, uint48 _sellerAmount) public onlyOwner {
        setPrtocolFeeReceiver(_receiver);
        setPrtocolFeeBuyerAmount(_buyerAmount);
        setPrtocolFeeSellerAmount(_sellerAmount);
    }

    /**
        @notice executes transfers for 2 matched orders
        @param left DealSide from the left order (see LibDeal.sol)
        @param right DealSide from the right order (see LibDeal.sol)
        @param feeSide feeSide of the match
        @return totalLeftValue - total amount for the left order
        @return totalRightValue - total amout for the right order
    */
    function doTransfers(
        LibDeal.DealSide memory left,
        LibDeal.DealSide memory right,
        LibFeeSide.FeeSide feeSide
    ) override internal returns (uint totalLeftValue, uint totalRightValue) {
        totalLeftValue = left.asset.value;
        totalRightValue = right.asset.value;

        if (feeSide == LibFeeSide.FeeSide.LEFT) {
            totalLeftValue = doTransfersWithFees(left, right, protocolFee);
            transferPayouts(right.asset.assetType, right.asset.value, right.from, left.payouts, right.proxy);
        } else if (feeSide == LibFeeSide.FeeSide.RIGHT) {
            totalRightValue = doTransfersWithFees(right, left,protocolFee);
            transferPayouts(left.asset.assetType, left.asset.value, left.from, right.payouts, left.proxy);
        } else {
            transferPayouts(left.asset.assetType, left.asset.value, left.from, right.payouts, left.proxy);
            transferPayouts(right.asset.assetType, right.asset.value, right.from, left.payouts, right.proxy);
        }
    }

    /**
        @notice executes the fee-side transfers (payment + fees)
        @param paymentSide DealSide of the fee-side order
        @param nftSide  DealSide of the nft-side order
        @param _protocolFee protocol fee data
        @return totalAmount of fee-side asset
    */
    function doTransfersWithFees(
        LibDeal.DealSide memory paymentSide,
        LibDeal.DealSide memory nftSide,
        ProtocolFeeData memory _protocolFee
    ) internal returns (uint totalAmount) {
        uint buyerProtocolFee = paymentSide.protocolFeeEnabled ? _protocolFee.buyerAmount : 0;
        uint sellerProtocolFee = nftSide.protocolFeeEnabled ? _protocolFee.sellerAmount : 0;
        totalAmount = calculateTotalAmount(paymentSide.asset.value, buyerProtocolFee, paymentSide.originFees);
        uint rest = transferProtocolFee(totalAmount, paymentSide.asset.value, paymentSide.from, buyerProtocolFee + sellerProtocolFee, _protocolFee.receiver, paymentSide.asset.assetType, paymentSide.proxy);

        rest = transferRoyalties(paymentSide.asset.assetType, nftSide.asset.assetType, nftSide.payouts, rest, paymentSide.asset.value, paymentSide.from, paymentSide.proxy);
        if (
            paymentSide.originFees.length  == 1 &&
            nftSide.originFees.length  == 1 &&
            nftSide.originFees[0].account == paymentSide.originFees[0].account
        ) { 
            LibPart.Part[] memory origin = new  LibPart.Part[](1);
            origin[0].account = nftSide.originFees[0].account;
            origin[0].value = nftSide.originFees[0].value + paymentSide.originFees[0].value;
            (rest,) = transferFees(paymentSide.asset.assetType, rest, paymentSide.asset.value, origin, paymentSide.from, paymentSide.proxy);
        } else {
            (rest,) = transferFees(paymentSide.asset.assetType, rest, paymentSide.asset.value, paymentSide.originFees, paymentSide.from, paymentSide.proxy);
            (rest,) = transferFees(paymentSide.asset.assetType, rest, paymentSide.asset.value, nftSide.originFees, paymentSide.from, paymentSide.proxy);
        }
        transferPayouts(paymentSide.asset.assetType, rest, paymentSide.from, nftSide.payouts, paymentSide.proxy);
    }

    /**
        @notice transfers protocol fee to protocol fee receiver
    */
    function transferProtocolFee(
        uint totalAmount,
        uint amount,
        address from,
        uint protocolFeeTotal,
        address protocolFeeReceiver,
        LibAsset.AssetType memory matchCalculate,
        address proxy
    ) internal returns (uint) {
        (uint rest, uint fee) = subFeeInBp(totalAmount, amount, protocolFeeTotal);
        if (fee > 0) {
            transfer(LibAsset.Asset(matchCalculate, fee), from, protocolFeeReceiver, proxy);
        }
        return rest;
    }

    /**
        @notice Transfer royalties. If there is only one royalties receiver and one address in payouts and they match,
           nothing is transferred in this function
        @param paymentAssetType Asset Type which represents payment
        @param nftAssetType Asset Type which represents NFT to pay royalties for
        @param payouts Payouts to be made
        @param rest How much of the amount left after previous transfers
        @param from owner of the Asset to transfer
        @param proxy Transfer proxy to use
        @return How much left after transferring royalties
    */
    function transferRoyalties(
        LibAsset.AssetType memory paymentAssetType,
        LibAsset.AssetType memory nftAssetType,
        LibPart.Part[] memory payouts,
        uint rest,
        uint amount,
        address from,
        address proxy
    ) internal returns (uint) {
        LibPart.Part[] memory royalties = getRoyaltiesByAssetType(nftAssetType);
        if (
            royalties.length == 1 &&
            payouts.length == 1 &&
            royalties[0].account == payouts[0].account
        ) {
            require(royalties[0].value <= 5000, "Royalties are too high (>50%)");
            return rest;
        }
        (uint result, uint totalRoyalties) = transferFees(paymentAssetType, rest, amount, royalties, from, proxy);
        require(totalRoyalties <= 5000, "Royalties are too high (>50%)");
        return result;
    }

    /**
        @notice calculates royalties by asset type. If it's a lazy NFT, then royalties are extracted from asset. otherwise using royaltiesRegistry
        @param nftAssetType NFT Asset Type to calculate royalties for
        @return calculated royalties (Array of LibPart.Part)
    */
    function getRoyaltiesByAssetType(LibAsset.AssetType memory nftAssetType) internal returns (LibPart.Part[] memory) {
        if (nftAssetType.assetClass == LibAsset.ERC1155_ASSET_CLASS || nftAssetType.assetClass == LibAsset.ERC721_ASSET_CLASS) {
            (address token, uint tokenId) = abi.decode(nftAssetType.data, (address, uint));
            return royaltiesRegistry.getRoyalties(token, tokenId);
        } else if (nftAssetType.assetClass == LibERC1155LazyMint.ERC1155_LAZY_ASSET_CLASS) {
            (, LibERC1155LazyMint.Mint1155Data memory data) = abi.decode(nftAssetType.data, (address, LibERC1155LazyMint.Mint1155Data));
            return data.royalties;
        } else if (nftAssetType.assetClass == LibERC721LazyMint.ERC721_LAZY_ASSET_CLASS) {
            (, LibERC721LazyMint.Mint721Data memory data) = abi.decode(nftAssetType.data, (address, LibERC721LazyMint.Mint721Data));
            return data.royalties;
        }
        LibPart.Part[] memory empty;
        return empty;
    }

    /**
        @notice Transfer fees
        @param assetType Asset Type to transfer
        @param rest How much of the amount left after previous transfers
        @param amount Total amount of the Asset. Used as a base to calculate part from (100%)
        @param fees Array of LibPart.Part which represents fees to pay
        @param from owner of the Asset to transfer
        @param proxy Transfer proxy to use
        @return newRest how much left after transferring fees
        @return totalFees total number of fees in bp
    */
    function transferFees(
        LibAsset.AssetType memory assetType,
        uint rest,
        uint amount,
        LibPart.Part[] memory fees,
        address from,
        address proxy
    ) internal returns (uint newRest, uint totalFees) {
        totalFees = 0;
        newRest = rest;
        for (uint256 i = 0; i < fees.length; ++i) {
            totalFees = totalFees.add(fees[i].value);
            uint feeValue;
            (newRest, feeValue) = subFeeInBp(newRest, amount, fees[i].value);
            if (feeValue > 0) {
                transfer(LibAsset.Asset(assetType, feeValue), from, fees[i].account, proxy);
            }
        }
    }

    /**
        @notice transfers main part of the asset (payout)
        @param assetType Asset Type to transfer
        @param amount Amount of the asset to transfer
        @param from Current owner of the asset
        @param payouts List of payouts - receivers of the Asset
        @param proxy Transfer Proxy to use
    */
    function transferPayouts(
        LibAsset.AssetType memory assetType,
        uint amount,
        address from,
        LibPart.Part[] memory payouts,
        address proxy
    ) internal {
        require(payouts.length > 0, "transferPayouts: nothing to transfer");
        uint sumBps = 0;
        uint rest = amount;
        for (uint256 i = 0; i < payouts.length - 1; ++i) {
            uint currentAmount = amount.bp(payouts[i].value);
            sumBps = sumBps.add(payouts[i].value);
            if (currentAmount > 0) {
                rest = rest.sub(currentAmount);
                transfer(LibAsset.Asset(assetType, currentAmount), from, payouts[i].account, proxy);
            }
        }
        LibPart.Part memory lastPayout = payouts[payouts.length - 1];
        sumBps = sumBps.add(lastPayout.value);
        require(sumBps == 10000, "Sum payouts Bps not equal 100%");
        if (rest > 0) {
            transfer(LibAsset.Asset(assetType, rest), from, lastPayout.account, proxy);
        }
    }
    
    /**
        @notice calculates total amount of fee-side asset that is going to be used in match
        @param amount fee-side order value
        @param buyerProtocolFee buyer protocol fee
        @param orderOriginFees fee-side order's origin fee (it adds on top of the amount)
        @return total amount of fee-side asset
    */
    function calculateTotalAmount(
        uint amount,
        uint buyerProtocolFee,
        LibPart.Part[] memory orderOriginFees
    ) internal pure returns (uint) {
        
        uint fees = buyerProtocolFee;
        for (uint256 i = 0; i < orderOriginFees.length; ++i) {
            require(orderOriginFees[i].value <= 10000, "origin fee is too big");
            fees = fees + orderOriginFees[i].value;
        }

        return amount.add(amount.bp(fees));
    }

    function subFeeInBp(uint value, uint total, uint feeInBp) internal pure returns (uint newValue, uint realFee) {
        return subFee(value, total.bp(feeInBp));
    }

    function subFee(uint value, uint fee) internal pure returns (uint newValue, uint realFee) {
        if (value > fee) {
            newValue = value.sub(fee);
            realFee = fee;
        } else {
            newValue = 0;
            realFee = value;
        }
    }

    uint256[46] private __gap;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@rarible/exchange-interfaces/contracts/ITransferProxy.sol";
import "@rarible/exchange-interfaces/contracts/INftTransferProxy.sol";
import "@rarible/exchange-interfaces/contracts/IERC20TransferProxy.sol";
import "./interfaces/ITransferExecutor.sol";

import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

import "./lib/LibTransfer.sol";

abstract contract TransferExecutor is Initializable, OwnableUpgradeable, ITransferExecutor {
    using LibTransfer for address;

    mapping (bytes4 => address) internal proxies;

    event ProxyChange(bytes4 indexed assetType, address proxy);

    function __TransferExecutor_init_unchained(address transferProxy, address erc20TransferProxy) internal { 
        proxies[LibAsset.ERC20_ASSET_CLASS] = address(erc20TransferProxy);
        proxies[LibAsset.ERC721_ASSET_CLASS] = address(transferProxy);
        proxies[LibAsset.ERC1155_ASSET_CLASS] = address(transferProxy);
    }

    function setTransferProxy(bytes4 assetType, address proxy) external onlyOwner {
        proxies[assetType] = proxy;
        emit ProxyChange(assetType, proxy);
    }

    function transfer(
        LibAsset.Asset memory asset,
        address from,
        address to,
        address proxy
    ) internal override {
        if (asset.assetType.assetClass == LibAsset.ERC721_ASSET_CLASS) {
            //not using transfer proxy when transfering from this contract
            (address token, uint tokenId) = abi.decode(asset.assetType.data, (address, uint256));
            require(asset.value == 1, "erc721 value error");
            if (from == address(this)){
                IERC721Upgradeable(token).safeTransferFrom(address(this), to, tokenId);
            } else {
                INftTransferProxy(proxy).erc721safeTransferFrom(IERC721Upgradeable(token), from, to, tokenId);
            }
        } else if (asset.assetType.assetClass == LibAsset.ERC20_ASSET_CLASS) {
            //not using transfer proxy when transfering from this contract
            (address token) = abi.decode(asset.assetType.data, (address));
            if (from == address(this)){
                require(IERC20Upgradeable(token).transfer(to, asset.value), "erc20 transfer failed");
            } else {
                IERC20TransferProxy(proxy).erc20safeTransferFrom(IERC20Upgradeable(token), from, to, asset.value);
            }
        } else if (asset.assetType.assetClass == LibAsset.ERC1155_ASSET_CLASS) {
            //not using transfer proxy when transfering from this contract
            (address token, uint tokenId) = abi.decode(asset.assetType.data, (address, uint256));
            if (from == address(this)){
                IERC1155Upgradeable(token).safeTransferFrom(address(this), to, tokenId, asset.value, "");
            } else {
                INftTransferProxy(proxy).erc1155safeTransferFrom(IERC1155Upgradeable(token), from, to, tokenId, asset.value, "");  
            }
        } else if (asset.assetType.assetClass == LibAsset.ETH_ASSET_CLASS) {
            if (to != address(this)) {
                to.transferEth(asset.value);
            }
        } else {
            ITransferProxy(proxy).transfer(asset, from, to);
        }
    }
    
    uint256[49] private __gap;
}

File 156 of 182 : ITransferExecutor.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@rarible/lib-asset/contracts/LibAsset.sol";

abstract contract ITransferExecutor {
    function transfer(
        LibAsset.Asset memory asset,
        address from,
        address to,
        address proxy
    ) internal virtual;
}

File 157 of 182 : ITransferManager.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "../lib/LibDeal.sol";
import "./ITransferExecutor.sol";

abstract contract ITransferManager is ITransferExecutor {

    function doTransfers(
        LibDeal.DealSide memory left,
        LibDeal.DealSide memory right,
        LibFeeSide.FeeSide feeSide
    ) internal virtual returns (uint totalMakeValue, uint totalTakeValue);
}

File 158 of 182 : LibDeal.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import "@rarible/lib-part/contracts/LibPart.sol";
import "@rarible/lib-asset/contracts/LibAsset.sol";
import "./LibFeeSide.sol";

library LibDeal {
    struct DealSide {
        LibAsset.Asset asset;
        LibPart.Part[] payouts;
        LibPart.Part[] originFees;
        address proxy;
        address from;
        bool protocolFeeEnabled;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@rarible/lib-asset/contracts/LibAsset.sol";

library LibFeeSide {

    enum FeeSide {NONE, LEFT, RIGHT}

    function getFeeSide(bytes4 leftClass, bytes4 rightClass) internal pure returns (FeeSide) {
        if (leftClass == LibAsset.ETH_ASSET_CLASS) {
            return FeeSide.LEFT;
        }
        if (rightClass == LibAsset.ETH_ASSET_CLASS) {
            return FeeSide.RIGHT;
        }
        if (leftClass == LibAsset.ERC20_ASSET_CLASS) {
            return FeeSide.LEFT;
        }
        if (rightClass == LibAsset.ERC20_ASSET_CLASS) {
            return FeeSide.RIGHT;
        }
        if (leftClass == LibAsset.ERC1155_ASSET_CLASS) {
            return FeeSide.LEFT;
        }
        if (rightClass == LibAsset.ERC1155_ASSET_CLASS) {
            return FeeSide.RIGHT;
        }
        return FeeSide.NONE;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

library LibTransfer {
    function transferEth(address to, uint value) internal {
        (bool success,) = to.call{ value: value }("");
        require(success, "transfer failed");
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

import "@rarible/exchange-interfaces/contracts/ITransferProxy.sol";
import "@rarible/lazy-mint/contracts/erc-1155/LibERC1155LazyMint.sol";
import "@rarible/lazy-mint/contracts/erc-1155/IERC1155LazyMint.sol";
import "@rarible/role-operator/contracts/OperatorRole.sol";

contract ERC1155LazyMintTransferProxy is OperatorRole, ITransferProxy {
    function transfer(LibAsset.Asset memory asset, address from, address to) override onlyOperator external {
        (address token, LibERC1155LazyMint.Mint1155Data memory data) = abi.decode(asset.assetType.data, (address, LibERC1155LazyMint.Mint1155Data));
        IERC1155LazyMint(token).transferFromOrMint(data, from, to, asset.value);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

import "@rarible/exchange-interfaces/contracts/ITransferProxy.sol";
import "@rarible/lazy-mint/contracts/erc-721/LibERC721LazyMint.sol";
import "@rarible/lazy-mint/contracts/erc-721/IERC721LazyMint.sol";
import "@rarible/role-operator/contracts/OperatorRole.sol";

contract ERC721LazyMintTransferProxy is OperatorRole, ITransferProxy {
    function transfer(LibAsset.Asset memory asset, address from, address to) override onlyOperator external {
        require(asset.value == 1, "erc721 value error");
        (address token, LibERC721LazyMint.Mint721Data memory data) = abi.decode(asset.assetType.data, (address, LibERC721LazyMint.Mint721Data));
        IERC721LazyMint(token).transferFromOrMint(data, from, to);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;

import "@rarible/role-operator/contracts/OperatorRole.sol";
import "@rarible/exchange-interfaces/contracts/IERC20TransferProxy.sol";

contract ERC20TransferProxy is IERC20TransferProxy, Initializable, OperatorRole {

    function __ERC20TransferProxy_init() external initializer {
        __Ownable_init();
    }

    function erc20safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) override external onlyOperator {
        require(token.transferFrom(from, to, value), "failure while transferring");
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;

import "@rarible/role-operator/contracts/OperatorRole.sol";
import "@rarible/exchange-interfaces/contracts/INftTransferProxy.sol";

contract TransferProxy is INftTransferProxy, Initializable, OperatorRole {

    function __TransferProxy_init() external initializer {
        __Ownable_init();
    }

    function erc721safeTransferFrom(IERC721Upgradeable token, address from, address to, uint256 tokenId) override external onlyOperator {
        token.safeTransferFrom(from, to, tokenId);
    }

    function erc1155safeTransferFrom(IERC1155Upgradeable token, address from, address to, uint256 id, uint256 value, bytes calldata data) override external onlyOperator {
        token.safeTransferFrom(from, to, id, value, data);
    }
}

File 165 of 182 : AssetMatchersImport.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import { AssetMatcherCollection } from "@rarible/custom-matchers/contracts/AssetMatcherCollection.sol";

File 166 of 182 : ExchangeV2Import.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import {ExchangeV2} from "@rarible/exchange-v2/contracts/ExchangeV2.sol";

import {ExchangeMetaV2} from "@rarible/exchange-v2/contracts/ExchangeMetaV2.sol";

File 167 of 182 : ExchangeWrapperImport.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@rarible/exchange-wrapper/contracts/RaribleExchangeWrapper.sol";

File 168 of 182 : RaribleExchangeWrapper.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import {RaribleExchangeWrapper} from "@rarible/exchange-wrapper/contracts/RaribleExchangeWrapper.sol";

File 169 of 182 : RoyaltiesRegistryImport.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import {RoyaltiesRegistry} from "@rarible/royalties-registry/contracts/RoyaltiesRegistry.sol";
import {RoyaltiesProviderV2Legacy} from "@rarible/royalties-registry/contracts/providers/RoyaltiesProviderV2Legacy.sol";
import {RoyaltiesProviderArtBlocks} from "@rarible/royalties-registry/contracts/providers/RoyaltiesProviderArtBlocks.sol";
import {RoyaltiesProviderArtBlocksV2} from "@rarible/royalties-registry/contracts/providers/RoyaltiesProviderArtBlocksV2.sol";

File 170 of 182 : TokensImport.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

//tokens 721
import {ERC721Rarible} from "@rarible/tokens/contracts/erc-721/ERC721Rarible.sol";
import {ERC721RaribleMinimal} from "@rarible/tokens/contracts/erc-721-minimal/ERC721RaribleMinimal.sol";
import {ERC721RaribleFactoryC2} from "@rarible/tokens/contracts/create-2/ERC721RaribleFactoryC2.sol";

//tokens 1155
import {ERC1155Rarible} from "@rarible/tokens/contracts/erc-1155/ERC1155Rarible.sol";
import {ERC1155RaribleFactoryC2} from "@rarible/tokens/contracts/create-2/ERC1155RaribleFactoryC2.sol";

//meta tokens
import {ERC721RaribleMeta} from "@rarible/tokens/contracts/erc-721-minimal/erc-721-minimal-meta/ERC721RaribleMeta.sol";
import {ERC1155RaribleMeta} from "@rarible/tokens/contracts/erc-1155/erc-1155-meta/ERC1155RaribleMeta.sol";

//beacons
import {ERC1155RaribleBeacon} from "@rarible/tokens/contracts/beacons/ERC1155RaribleBeacon.sol";
import {ERC721RaribleMinimalBeacon} from "@rarible/tokens/contracts/beacons/ERC721RaribleMinimalBeacon.sol";
import {ERC721RaribleBeacon} from "@rarible/tokens/contracts/beacons/ERC721RaribleBeacon.sol";
import {ERC1155RaribleBeaconMeta} from "@rarible/tokens/contracts/beacons/ERC1155RaribleBeaconMeta.sol";
import {ERC721RaribleMinimalBeaconMeta} from "@rarible/tokens/contracts/beacons/ERC721RaribleMinimalBeaconMeta.sol";

import { TestERC20 } from "@rarible/test/contracts/TestERC20.sol";

File 171 of 182 : TransferProxiesImport.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import {ERC721LazyMintTransferProxy} from "@rarible/transfer-proxy/contracts/lazy-mint/erc721/ERC721LazyMintTransferProxy.sol";
import {ERC1155LazyMintTransferProxy} from "@rarible/transfer-proxy/contracts/lazy-mint/erc1155/ERC1155LazyMintTransferProxy.sol";
import {TransferProxy} from "@rarible/transfer-proxy/contracts/proxy/TransferProxy.sol";
import {ERC20TransferProxy} from "@rarible/transfer-proxy/contracts/proxy/ERC20TransferProxy.sol";

File 172 of 182 : TransparentUpgradeableProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "@openzeppelin/contracts/proxy/ProxyAdmin.sol";

File 173 of 182 : ERC721LazyMintTest.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.9 <0.8.0;
pragma abicoder v2;

import "@rarible/lazy-mint/test/contracts/ERC721LazyMintTest.sol";

File 174 of 182 : RaribleTestHelper.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import {RaribleTestHelper} from "@rarible/exchange-v2/test/contracts/RaribleTestHelper.sol";

File 175 of 182 : TestERC1155.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import { TestERC1155 } from "@rarible/test/contracts/TestERC1155.sol";

File 176 of 182 : TestERC1155RoyaltiesV2.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import { TestERC1155RoyaltiesV2 } from "@rarible/royalties/test/contracts/TestERC1155RoyaltiesV2.sol";

File 177 of 182 : TestERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import { TestERC20 } from "@rarible/test/contracts/TestERC20.sol";

File 178 of 182 : TestERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import { TestERC721 } from "@rarible/test/contracts/TestERC721.sol";

File 179 of 182 : TestERC721RoyaltiesV1.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import { TestERC721RoyaltiesV1 } from "@rarible/royalties/test/contracts/TestERC721RoyaltiesV1.sol";

File 180 of 182 : TestERC721RoyaltiesV2.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import { TestERC721RoyaltiesV2 } from "@rarible/royalties/test/contracts/TestERC721RoyaltiesV2.sol";

File 181 of 182 : WrapperHelper.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import { WrapperHelper } from "@rarible/exchange-wrapper/test/contracts/WrapperHelper.sol";

File 182 of 182 : RaribleTestHelper.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma abicoder v2;

import {RaribleTestHelper} from "@rarible/exchange-v2/test/contracts/RaribleTestHelper.sol";

Settings
{
  "libraries": {},
  "optimizer": {
    "enabled": true,
    "mode": "z"
  },
  "outputSelection": {
    "*": {
      "*": [
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"BuyerFeeAmountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"Cancel","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldValue","type":"address"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"FeeReceiverChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"leftHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"rightHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"newLeftFill","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRightFill","type":"uint256"}],"name":"Match","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"assetType","type":"bytes4"},{"indexed":false,"internalType":"address","name":"matcher","type":"address"}],"name":"MatcherChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","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":"bytes4","name":"assetType","type":"bytes4"},{"indexed":false,"internalType":"address","name":"proxy","type":"address"}],"name":"ProxyChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"SellerFeeAmountChanged","type":"event"},{"inputs":[{"internalType":"address","name":"_transferProxy","type":"address"},{"internalType":"address","name":"_erc20TransferProxy","type":"address"},{"internalType":"uint256","name":"newProtocolFee","type":"uint256"},{"internalType":"address","name":"newDefaultFeeReceiver","type":"address"},{"internalType":"contract IRoyaltiesProvider","name":"newRoyaltiesProvider","type":"address"}],"name":"__ExchangeV2_init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"maker","type":"address"},{"components":[{"components":[{"internalType":"bytes4","name":"assetClass","type":"bytes4"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct LibAsset.AssetType","name":"assetType","type":"tuple"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct LibAsset.Asset","name":"makeAsset","type":"tuple"},{"internalType":"address","name":"taker","type":"address"},{"components":[{"components":[{"internalType":"bytes4","name":"assetClass","type":"bytes4"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct LibAsset.AssetType","name":"assetType","type":"tuple"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct LibAsset.Asset","name":"takeAsset","type":"tuple"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"bytes4","name":"dataType","type":"bytes4"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct LibOrder.Order","name":"order","type":"tuple"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"bidMaker","type":"address"},{"internalType":"uint256","name":"bidNftAmount","type":"uint256"},{"internalType":"bytes4","name":"nftAssetClass","type":"bytes4"},{"internalType":"bytes","name":"nftData","type":"bytes"},{"internalType":"uint256","name":"bidPaymentAmount","type":"uint256"},{"internalType":"address","name":"paymentToken","type":"address"},{"internalType":"uint256","name":"bidSalt","type":"uint256"},{"internalType":"uint256","name":"bidStart","type":"uint256"},{"internalType":"uint256","name":"bidEnd","type":"uint256"},{"internalType":"bytes4","name":"bidDataType","type":"bytes4"},{"internalType":"bytes","name":"bidData","type":"bytes"},{"internalType":"bytes","name":"bidSignature","type":"bytes"},{"internalType":"uint256","name":"sellOrderPaymentAmount","type":"uint256"},{"internalType":"uint256","name":"sellOrderNftAmount","type":"uint256"},{"internalType":"bytes","name":"sellOrderData","type":"bytes"}],"internalType":"struct LibDirectTransfer.AcceptBid","name":"direct","type":"tuple"}],"name":"directAcceptBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sellOrderMaker","type":"address"},{"internalType":"uint256","name":"sellOrderNftAmount","type":"uint256"},{"internalType":"bytes4","name":"nftAssetClass","type":"bytes4"},{"internalType":"bytes","name":"nftData","type":"bytes"},{"internalType":"uint256","name":"sellOrderPaymentAmount","type":"uint256"},{"internalType":"address","name":"paymentToken","type":"address"},{"internalType":"uint256","name":"sellOrderSalt","type":"uint256"},{"internalType":"uint256","name":"sellOrderStart","type":"uint256"},{"internalType":"uint256","name":"sellOrderEnd","type":"uint256"},{"internalType":"bytes4","name":"sellOrderDataType","type":"bytes4"},{"internalType":"bytes","name":"sellOrderData","type":"bytes"},{"internalType":"bytes","name":"sellOrderSignature","type":"bytes"},{"internalType":"uint256","name":"buyOrderPaymentAmount","type":"uint256"},{"internalType":"uint256","name":"buyOrderNftAmount","type":"uint256"},{"internalType":"bytes","name":"buyOrderData","type":"bytes"}],"internalType":"struct LibDirectTransfer.Purchase","name":"direct","type":"tuple"}],"name":"directPurchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"fills","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"maker","type":"address"},{"components":[{"components":[{"internalType":"bytes4","name":"assetClass","type":"bytes4"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct LibAsset.AssetType","name":"assetType","type":"tuple"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct LibAsset.Asset","name":"makeAsset","type":"tuple"},{"internalType":"address","name":"taker","type":"address"},{"components":[{"components":[{"internalType":"bytes4","name":"assetClass","type":"bytes4"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct LibAsset.AssetType","name":"assetType","type":"tuple"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct LibAsset.Asset","name":"takeAsset","type":"tuple"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"bytes4","name":"dataType","type":"bytes4"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct LibOrder.Order","name":"orderLeft","type":"tuple"},{"internalType":"bytes","name":"signatureLeft","type":"bytes"},{"components":[{"internalType":"address","name":"maker","type":"address"},{"components":[{"components":[{"internalType":"bytes4","name":"assetClass","type":"bytes4"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct LibAsset.AssetType","name":"assetType","type":"tuple"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct LibAsset.Asset","name":"makeAsset","type":"tuple"},{"internalType":"address","name":"taker","type":"address"},{"components":[{"components":[{"internalType":"bytes4","name":"assetClass","type":"bytes4"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct LibAsset.AssetType","name":"assetType","type":"tuple"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct LibAsset.Asset","name":"takeAsset","type":"tuple"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"bytes4","name":"dataType","type":"bytes4"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct LibOrder.Order","name":"orderRight","type":"tuple"},{"internalType":"bytes","name":"signatureRight","type":"bytes"}],"name":"matchOrders","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFee","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint48","name":"buyerAmount","type":"uint48"},{"internalType":"uint48","name":"sellerAmount","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royaltiesRegistry","outputs":[{"internalType":"contract IRoyaltiesProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint48","name":"_buyerAmount","type":"uint48"},{"internalType":"uint48","name":"_sellerAmount","type":"uint48"}],"name":"setAllProtocolFeeData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"assetType","type":"bytes4"},{"internalType":"address","name":"matcher","type":"address"}],"name":"setAssetMatcher","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint48","name":"_buyerAmount","type":"uint48"}],"name":"setPrtocolFeeBuyerAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"setPrtocolFeeReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint48","name":"_sellerAmount","type":"uint48"}],"name":"setPrtocolFeeSellerAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IRoyaltiesProvider","name":"newRoyaltiesRegistry","type":"address"}],"name":"setRoyaltiesRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"assetType","type":"bytes4"},{"internalType":"address","name":"proxy","type":"address"}],"name":"setTransferProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

9c4d535b0000000000000000000000000000000000000000000000000000000000000000010013a36b64adf0648ee568670457aaf5893d386f15332d419b0394af175c9f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x000400000000000200000000030100190000006003300270000013000430019700030000004103550002000000010355000013000030019d00000001012001900000000b0000c13d00000000010000194bfc005b0000040f00000001010000394bfc005b0000040f0003000000000002000300000006001d000200000005001d0000130005000041000013000630009c00000000030580190000004003300210000013000640009c00000000040580190000006004400210000000000334019f000013000410009c0000000001058019000000c001100210000000000113019f4bfc44050000040f0000000209000029000000000301001900000060033002700000130003300197000000030430006c000000030500002900000000050340190000001f0450018f00000005055002720000002e0000613d000000000600001900000005076002100000000008790019000000000771034f0001002d0000003d000044a70000013d000000280000413d000000010220018f000000000604004b000000330000613d000100330000003d000047e30000013d00004ac70000013d0003000000000002000300000006001d000200000005001d0000130005000041000013000630009c00000000030580190000004003300210000013000640009c00000000040580190000006004400210000000000334019f000013000410009c0000000001058019000000c001100210000000000113019f4bfc440a0000040f0000000209000029000000000301001900000060033002700000130003300197000000030430006c000000030500002900000000050340190000001f0450018f0000000505500272000000550000613d000000000600001900000005076002100000000008790019000000000771034f000100540000003d000044a70000013d0000004f0000413d000000010220018f000000000604004b0000005a0000613d0001005a0000003d000047e30000013d00004ac70000013d009f0000000000020000008002000039000000400020043f000000000101004b000000680000613d0000000001000416000000000101004b0000006d0000c13d000000200100003900000100001004430000012000000443000013990100004100004bfd0001042e002500000002001d0000000001000031002600000001001d000000030110008c0000006f0000213d000000000100001900004bfe000104300000000209000367000000000709043b000000e008700270000013010170009c000000000f0004100000002601000029002400bf0010003d0000001f0a10018f000000050b100270000000a00e100039000000800d100039000000040510008a00000004049003700000003f0c100039000000240390037000000064019003700000004402900370000001730000813d000013440670009c000001820000813d0000134f0680009c0000008406900370000002290000c13d000000000b09034f00230000000f001d00001308080000410000009f0950008c000000000900001900000000090820190000130805500197000000000a05004b0000000008008019000013080550009c000000000809c019000000000508004b0000006d0000613d000000000504043b002513090050019b002400000005001d000013090450009c0000006d0000213d000000000403043b000013150340009c0000006d0000213d000000230340003900001308050000410000002609000029000000000893004b0000000008000019000000000805401900001308099001970000130803300197000000000a93004b000000000500a019000000000393013f000013080330009c000000000508c019000000000305004b0000006d0000613d000000040540003900000000035b034f000000000303043b000013160830009c00001b020000813d000000bf083000390022002000000092000000220880017f000000800980008a0000138e0990009c00001b020000813d000000400080043f000000800030043f00000000043400190000002404400039000000260440006c0000006d0000213d000000200450003900000000044b034f0000001f0530018f0000000508300272000000c90000613d0000000009000019000000050a900210000000000ba4034f000000000b0b043b000000a00aa000390000000000ba04350000000109900039000000000a89004b000000c10000413d000000000905004b000000d80000613d0000000508800210000000000484034f0000000305500210000000a008800039000000000908043300000000095901cf000000000959022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000494019f0000000000480435000000a0033000390000000000030435000000000101043b002100000001001d000000000102043b002600000001001d000000000106043b000001000210008c0000006d0000813d000000800200043d000000000202004b0000000002000019000000e60000613d000000a00200043d000000000272013f000000400300043d0000138f0220009c00000eac0000a13d001f00ff001001930000006001300039000000400010043f000000250100002900000000001004350000019301000039001b00000001001d000000200010043f00000040020000390000000001000019002000000003001d4bfc43d70000040f000000000101041a00000020020000290000000001120436001e00000001001d000000250300002900000000003104350000004002200039001d00000002001d00000080010000390000000000120435000000400100043d0000008002100039000000400020043f00001391020000410000006003100039000000000023043500001392020000410000004003100039000000000023043500000043020000390000000001210436000013930300004100000000003104354bfc43d70000040f0000001e020000290000000002020433001e00000002001d00000020020000290000000002020433001c00000002001d0000001d020000290000000002020433001d00000001001d00000000120204344bfc43d70000040f000000400400043d002000000004001d00000020024000390000001d03000029000000000032043500000040024000390000001c0300002900000000003204350000001e020000290000130902200197000000600340003900000000002304350000008002400039000101280000003d00004b850000013d000000a002400039000000400020043f00000000020304334bfc43d70000040f0000019402000039000000000202041a00001323030000410000002005000029000000c0045000390000000000340435000000c2035000390000000000230435000000e202500039000101370000003d00004b850000013d0000010202500039001e00000002001d000000400020043f00000000020304334bfc43d70000040f0000001e02000029000000000002043500000020050000290000012202500039000000400020043f00000182035000390000002104000029000000000043043500000162035000390000002604000029000000000043043500000142035000390000001f0400002900000000004304350000000000120435000000400300043d0000000001350049000001a2041000390000000001000414000101510000003d00004b570000013d002100000002001d002600000006001d4bfc00340000040f000000000101004b00000ecd0000c13d000000030100036700000001020000310000001f0420018f0000000503200272000001630000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000635004b0000015c0000413d000000000504004b000001710000613d00000003044002100000000503300210000000000503043300000000054501cf000000000545022f000000000131034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000013043500000000010000194bfc43c30000040f000013020670009c000001dd0000813d0000133d0180009c000002620000c13d0000000001000416000000000101004b0000006d0000c13d0000003301000039000000000101041a0000130901100197000000800010043f000000a0020000390000008001000039000000000212004900004b320000013d000013450180009c000002730000c13d0000000001000416000000000101004b0000006d0000c13d00001308010000410000003f0250008c000000000200001900000000020120190000130805500197000000000605004b0000000001008019000013080550009c000000000102c019000000000101004b0000006d0000613d000000000204043b00001317012001970000000005020019000000000112004b0000006d0000c13d000000000103043b002500000001001d0000130a0110009c0000006d0000813d000000000100041100000000021f004b000001af0000c13d000101a00000003d000047150000013d000001a50000613d0000000001000019000101a40000003d000046950000013d000001a20000413d00000000010a004b000001ac0000613d0000000501b00210000000000219034f0000000303a00210000101ac0000003d000044630000013d00000000000e043500000000010d043300001309011001970000003302000039000000000202041a000000000212013f0000134d030000410000009701000039000013090220019800000ad20000c13d002400000003001d002600000005001d0000000000500435000000200010043f000000400200003900000000010000194bfc43d70000040f000000000201041a0000130d0220019700000025040000290000130903400197000000000232019f000000000021041b000000400100043d0000000000410435000000400200043d00000000012100490000130003000041000013000420009c000000000203801900000040022002100000002001100039000013000410009c00000000010380190000006001100210000000000121019f0000000002000414000013000420009c000101d40000003d000048ac0000013d0000130b011001c70000800d020000390000000203000039000000240400002900000026050000294bfc44050000040f0000000101200190000002a90000c13d0000006d0000013d000013030680009c000002ab0000c13d0000000001000416000000000101004b0000006d0000c13d0000130801000041000101e50000003d000048840000013d0000130803500197000000000503004b0000000001008019000013080330009c000000000102c019000000000101004b0000006d0000613d000000000104043b002513110010019b000013120110009c0000006d0000813d000000000100041100000000021f004b000002040000c13d000101f50000003d000047150000013d000001fa0000613d0000000001000019000101f90000003d000046950000013d000001f70000413d00000000010a004b000002010000613d0000000501b00210000000000219034f0000000303a00210000102010000003d000044630000013d00000000000e043500000000010d043300001309011001970000003302000039000000000202041a000000000112013f000013090110019800000ad20000c13d0001020b0000003d000047f10000013d000000a00110027000001311011001970001020f0000003d00004a9b0000013d0000130003000041000013000410009c000102130000003d00004a5f0000013d000013000420009c000102160000003d000049450000013d0000000002000414000013000420009c0001021a0000003d000048ac0000013d0000130b011001c70000800d0200003900000001030000390000133b040000414bfc44050000040f00000001012001900000006d0000613d0000002501000029000000a0011002100000002603000029000000000203041a0000133c02200197000000000112019f000000000013041b000002a90000013d000013500280009c000004270000c13d00240000000c001d0001022e0000003d000049840000013d0000130801000041000102310000003d000048840000013d0000130803500197000000000503004b0000000001008019000013080330009c000000000102c019000000000101004b0000006d0000613d000000000304043b000013160130009c0000006d0000813d000000040130003900000026021000690000130804000041000001df0520008c000000000500001900000000050420190000130806200197000000000706004b0000000004008019000013080660009c000000000405c019000000000404004b0000006d0000613d000000a403300039000000220430035f000000000504043b00001309045001970000130a0550009c0000006d0000813d000000800000043f0000006005000039000000a00050043f000000e00050043f000000000504004b00000ae10000c13d0000134b04000041000000c00040043f002501000000003d001802000000003d001901e00000003d001e01c00000003d001f01a00000003d001d01800000003d001c01600000003d001b01400000003d001a01200000003d0000022004000039000000220500035f00000af30000013d0000133e0180009c000004900000c13d0000000001000416000000000101004b0000006d0000c13d0000016101000039000000000101041a0000130902100197000000800020043f000000a0021002700000131102200197000000a00020043f000000d001100270000000c00010043f0000008001000039000000600200003900004b320000013d000013460180009c000004c30000c13d0000000001000416000000000101004b0000006d0000c13d00001308010000410001027b0000003d000048840000013d0000130803500197000000000503004b0000000001008019000013080330009c000000000102c019000000000101004b0000006d0000613d000000000204043b00001309012001970000130a0220009c0000006d0000813d000000000200041100000000032f004b0000029f0000c13d000000200200008a000000240220017f000000400020043f0000002602000029000000800020043f00000000020b004b000002950000613d0000000002000019000102930000003d00004afb0000013d0000000003b2004b000002910000413d00000000020a004b0000029c0000613d0000000502b00210000000000329034f0000000304a002100001029c0000003d000048ff0000013d00000000000e043500000000020d043300001309022001970000003303000039000000000303041a000000000223013f000013090220019800000ad20000c13d0000016202000039000000000302041a0000130d03300197000000000113019f000000000012041b000000000100001900004bfd0001042e000013040680009c000004fc0000c13d00240000000c001d00210000000b001d00200000000a001d00220000000903530000000001000416000000000101004b0000006d0000c13d0000130801000041000102b70000003d000048840000013d0000130803500197000000000503004b0000000001008019000013080330009c000000000102c019000000000101004b0000006d0000613d000000000204043b000013150120009c0000006d0000213d0000000401200039000000260310006900001308040000410000011f0530008c000000000500001900000000050420190000130803300197000000000603004b0000000004008019000013080330009c000000000405c019000000000304004b0000006d0000613d000001a004000039000000400040043f000000220310035f000000000303043b0000130a0530009c0000006d0000813d000000800030043f0000002003100039000000220330035f000000000303043b000013160530009c0000006d0000813d0000000005130019000000260350006900001308060000410000003f0730008c000000000700001900000000070620190000130803300197000000000803004b0000000006008019000013080330009c000000000607c019000000000306004b0000006d0000613d000001e006000039000000400060043f000000220350035f000000000303043b000013160730009c0000006d0000813d0000000003530019000000260730006900001308080000410000003f0970008c000000000900001900000000090820190000130807700197000000000a07004b0000000008008019000013080770009c000000000809c019000000000708004b0000006d0000613d0000022007000039000000400070043f000000220830035f000000000808043b0000131709800197000000000998004b0000006d0000c13d000001e00080043f0000002008300039000000220880035f000000000808043b000013160980009c0000006d0000813d00000000093800190000001f039000390000130808000041000000260b000029000000000ab3004b000000000a000019000000000a0840190000130803300197000013080bb00197000000000cb3004b000000000800a0190000000003b3013f000013080330009c00000000080ac019000000000308004b0000006d0000613d000000220390035f000000000803043b000013160380009c00001b020000813d0000025f0a800039000000200300008a000000000a3a016f000002200ba0008a000013180bb0009c00001b020000813d0000004000a0043f000002200080043f0000002009900039000000000a890019000000260aa0006c0000006d0000213d000000220990035f0000001f0a80018f000000050b800272000003340000613d000000000c000019000000050dc00210000000000ed9034f000000000e0e043b000002400dd000390000000000ed0435000000010cc00039000000000dbc004b0000032c0000413d000000000c0a004b000003430000613d000000050bb002100000000009b9034f000000030aa00210000002400bb00039000000000c0b0433000000000cac01cf000000000cac022f000000000909043b000001000aa000890000000009a9022f0000000009a901cf0000000009c9019f00000000009b043500000240088000390000000000080435000002000070043f000001a00060043f0000002005500039000000220550035f000000000505043b000001c00050043f000000a00040043f0000004404200039000000220540035f000000000505043b0000130a0650009c0000006d0000813d000000c00050043f0000002004400039000000220440035f000000000404043b000013160540009c0000006d0000813d0000000004140019000000260540006900001308060000410000003f0750008c000000000700001900000000070620190000130805500197000000000805004b0000000006008019000013080550009c000000000607c019000000000506004b0000006d0000613d000000400500043d000013190650009c00001b020000813d000103690000003d00004bc00000013d000013160870009c0000006d0000813d0000000007470019000000260870006900001308090000410000003f0a80008c000000000a000019000000000a0920190000130808800197000000000b08004b0000000009008019000013080880009c00000000090ac019000000000809004b0000006d0000613d0000131a0850009c00001b020000213d0000008008500039000000000968004b00001b020000413d000000400080043f000000220870035f000000000808043b0000131709800197000000000998004b0000006d0000c13d000103850000003d00004baf0000013d000013160980009c0000006d0000813d000000000a7800190000001f07a0003900001308080000410001038c0000003d00004af60000013d0000130807700197000013080bb00197000000000cb7004b000000000800a0190000000007b7013f000013080770009c000000000809c019000000000708004b0000006d0000613d0000002207a0035f000000000707043b000013160870009c00001b020000813d0000003f08700039000000000938016f000000400800043d0000000009980019000000000b89004b00001b020000413d000013160b90009c00001b020000813d000103a30000003d00004a0a0000013d0000006d0000213d000000220ba0035f0025001f00700193000000050c700272000003b10000613d000000000d000019000000050ed00210000000000ae90019000000000eeb034f000000000e0e043b0000000000ea0435000000010dd00039000000000ecd004b000003a90000413d000000250d00006b000003b90000613d000000050cc00210000000000bcb034f000000000cc90019000000250a000029000103b90000003d000046820000013d000103bb0000003d000046f20000013d000000e00050043f0000008404200039000000220440035f000000000404043b000001000040043f000000a404200039000000220440035f000000000404043b000001200040043f000000c404200039000000220440035f000000000404043b000001400040043f000000e402200039000000220420035f000000000404043b0000131705400197000000000554004b0000006d0000c13d000001600040043f0000002002200039000000220220035f000000000202043b000013160420009c0000006d0000813d00000000051200190000001f0150003900001308020000410000002606000029000000000461004b0000000004000019000000000402401900001308011001970000130806600197000000000761004b000000000200a019000000000161013f000013080110009c000000000204c019000000000102004b0000006d0000613d000000220150035f000000000101043b000013160210009c00001b020000813d0000003f02100039000000000432016f000000400200043d0000000004420019000000000624004b00001b020000413d000013160640009c00001b020000813d000000400040043f000000000412043600000020055000390000000006150019000000260660006c0000006d0000213d000000220650035f0000001f0510018f0000000507100272000003fe0000613d0000000008000019000103fd0000003d000045760000013d000003fb0000413d000000000805004b000004020000613d000104020000003d000044790000013d00000000011400190000000000010435000001800020043f000000800100043d000000000200041100000000042f004b000004170000c13d0001040b0000003d0000481e0000013d000004100000613d00000000040000190001040f0000003d000048160000013d0000040d0000413d000000200400006b000004140000613d000104140000003d000044330000013d000104160000003d000046ed0000013d0000130902200197000000000312013f00001336020000410000000b010000390000130903300198000004210000c13d00001337020000410000001401000039000001000300043d000000000303004b00001a0b0000c13d000000400300043d000000440430003900000000002404350000002402300039000000000012043500000eb20000013d000013510280009c000008850000c13d0001042b0000003d000049840000013d0000000002000416000000000202004b0000006d0000c13d00001308020000410000009f0750008c000000000700001900000000070220190000130805500197000000000805004b0000000002008019000013080550009c000000000207c019000000000202004b0000006d0000613d000000000204043b002513090020019b000013090220009c0000006d0000213d000000000203043b001f13090020019b000013090220009c0000006d0000213d000000000101043b000013090110009c0000006d0000213d000000000106043b001d13090010019b0000130a0110009c0000006d0000813d001b0000000e001d001c0000000d001d000000000200041a001aff000020019400000000010000190000000101006039000004600000c13d009e00230000002d000104520000003d0000441d0000013d0000009e0440008a00000020044000c9001e00000002001d00001320020000414bfc43ed0000040f0000001e02000029000000000101004b0000045c0000613d000000ff01200190000004830000c13d000013540120019700000101021001bf000000000020041b000000000100001900000001011001900000002303000029000004740000613d009d00000003001d000104660000003d0000441d0000013d0000009d0440008a00000020044000c9001e00000002001d00001320020000414bfc43ed0000040f0000001e02000029000000000101004b000004700000613d000000ff01200190000004830000c13d000013540120019700000001021001bf000000000020041b0000002303000029001e00000002001d0019ff000020019400000ee70000c13d009c00000003001d0001047a0000003d0000441d0000013d0000009c0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000001e0200002900000ee30000613d000000ff0120019000000ee30000613d0000131001000041000000800010043f0000002001000039000000840010043f0000002e01000039000000a40010043f0000135501000041000000c40010043f0000135601000041000000e40010043f000000800100003900000084020000394bfc43c30000040f0000133f0180009c0000089b0000c13d0000000001000416000000000101004b0000006d0000c13d00001308010000410000003f0250008c000000000200001900000000020120190000130805500197000000000605004b0000000001008019000013080550009c000000000102c019000000000101004b0000006d0000613d000000000204043b00001317012001970000000005020019000000000112004b0000006d0000c13d000000000103043b002500000001001d0000130a0110009c0000006d0000813d000000000100041100000000021f004b000004bd0000c13d000104ae0000003d000047150000013d000004b30000613d0000000001000019000104b20000003d000046950000013d000004b00000413d00000000010a004b000004ba0000613d0000000501b00210000000000219034f0000000303a00210000104ba0000003d000044630000013d00000000000e043500000000010d043300001309011001970000003302000039000000000202041a000000000212013f00001343030000410000006501000039000001b40000013d000013470180009c000009910000c13d00240000000c001d000104c80000003d000049840000013d0000130801000041000104cb0000003d000048840000013d0000130803500197000000000503004b0000000001008019000013080330009c000000000102c019000000000101004b0000006d0000613d000000000204043b000013160120009c0000006d0000813d000000040120003900000026031000690000130804000041000001df0530008c000000000500001900000000050420190000130806300197000000000706004b0000000004008019000013080660009c000000000405c019000000000404004b0000006d0000613d000000a404200039000000220540035f000000000605043b00001309056001970000130a0660009c0000006d0000813d000000800000043f0000006006000039000000a00060043f000000e00060043f000000000605004b00000cc10000c13d0000134b05000041000000c00050043f001701000000003d001902000000003d001a01e00000003d001c01c00000003d001d01a00000003d001b01800000003d001601600000003d001f01400000003d001e01200000003d0000022005000039000000220600035f00000cd30000013d000013050680009c0000099d0000c13d00240000000c001d000105010000003d000049840000013d00001308060000410000007f0750008c000000000700001900000000070620190000130805500197000000000805004b0000000006008019000013080550009c000000000607c019000000000506004b0000006d0000613d000000000504043b000013150450009c0000006d0000213d0000000404500039000000260640006900001308070000410000011f0860008c000000000800001900000000080720190000130806600197000000000906004b0000000007008019000013080660009c000000000708c019000000000607004b0000006d0000613d000001a006000039000000400060043f000000220740035f000000000707043b0000130a0870009c0000006d0000813d000000800070043f0000002007400039000000220770035f000000000707043b000013160870009c0000006d0000813d0000000007470019000000260870006900001308090000410000003f0a80008c000000000a000019000000000a0920190000130808800197000000000b08004b0000000009008019000013080880009c00000000090ac019000000000809004b0000006d0000613d000001e008000039000000400080043f000000220970035f000000000909043b000013160a90009c0000006d0000813d000000000a7900190000002609a00069000013080b0000410000003f0c90008c000000000c000019000000000c0b20190000130809900197000000000d09004b000000000b008019000013080990009c000000000b0cc01900000000090b004b0000006d0000613d0000022009000039000000400090043f000000220ba0035f000000000b0b043b000013170cb00197000000000ccb004b0000006d0000c13d000001e000b0043f000000200ba00039000000220bb0035f000000000b0b043b000013160cb0009c0000006d0000813d000000000bab00190000001f0ab00039000013080c000041000000260e000029000000000dea004b000000000d000019000000000d0c4019000013080aa00197000013080ee00197000000000fea004b000000000c00a019000000000aea013f000013080aa0009c000000000c0dc019000000000a0c004b0000006d0000613d000000220ab0035f000000000a0a043b000013160ca0009c00001b020000813d0000025f0ca00039001f0020000000920000001f0cc0017f000002200dc0008a000013180dd0009c00001b020000813d0000004000c0043f0000022000a0043f000000200bb00039000000000cab0019000000260cc0006c0000006d0000213d000000220bb0035f001e001f00a00193000000050da00272000005820000613d000000000e000019000000050fe00210000000000cfb034f000000000c0c043b000002400ff000390000000000cf0435000000010ee00039000000000cde004b0000057a0000413d0000001e0c00006b000005920000613d000000050cd00210000000000bcb034f0000001e0d000029000000030dd00210000002400cc00039000000000e0c0433000000000ede01cf000000000ede022f000000000b0b043b000001000dd00089000000000bdb022f000000000bdb01cf000000000beb019f0000000000bc0435000002400aa0003900000000000a0435000002000090043f000001a00080043f0000002007700039000000220770035f000000000707043b000001c00070043f000000a00060043f0000004406500039000000220760035f000000000707043b0000130a0870009c0000006d0000813d000000c00070043f0000002006600039000000220660035f000000000606043b000013160760009c0000006d0000813d0000000006460019000000260760006900001308080000410000003f0970008c000000000900001900000000090820190000130807700197000000000a07004b0000000008008019000013080770009c000000000809c019000000000708004b0000006d0000613d000000400700043d000013190870009c00001b020000813d0000004008700039000000400080043f000000220960035f000000000909043b000013160a90009c0000006d0000813d0000000009690019000000260a900069000013080b0000410000003f0ca0008c000000000c000019000000000c0b2019000013080aa00197000000000d0a004b000000000b008019000013080aa0009c000000000b0cc019000000000a0b004b0000006d0000613d0000131a0a70009c00001b020000213d000000800a700039000000000b8a004b00001b020000413d0000004000a0043f000000220a90035f000000000a0a043b000013170ba00197000000000bba004b0000006d0000c13d0000000000a80435000000200a900039000000220aa0035f000000000a0a043b000013160ba0009c0000006d0000813d000000000c9a00190000001f09c00039000013080a000041000000260d000029000000000bd9004b000000000b000019000000000b0a40190000130809900197000013080dd00197000000000ed9004b000000000a00a0190000000009d9013f000013080990009c000000000a0bc01900000000090a004b0000006d0000613d0000002209c0035f000000000909043b000013160a90009c00001b020000813d0000003f0a9000390000001f0aa0017f000000400d00043d000000000bad0019001e0000000d001d000000000adb004b00001b020000413d000013160ab0009c00001b020000813d0000004000b0043f0000001e0a000029000000000b9a0436000000200cc00039000000000a9c0019000000260aa0006c0000006d0000213d000000220dc0035f001d001f00900193000000050e9002720000060b0000613d000000000f000019000000050cf00210000000000acb0019000000000ccd034f000000000c0c043b0000000000ca0435000000010ff00039000000000aef004b000006030000413d0000001d0a00006b0000061b0000613d000000050ae00210000000000cad034f000000000aab00190000001d0d000029000000030dd00210000000000e0a0433000000000ede01cf000000000ede022f000000000c0c043b000001000dd00089000000000cdc022f000000000cdc01cf000000000cec019f0000000000ca043500000000099b0019000000000009043500000060097000390000001e0a0000290000000000a9043500000000088704360000002006600039000000220660035f000000000606043b0000000000680435000000e00070043f0000008406500039000000220660035f000000000606043b000001000060043f000000a406500039000000220660035f000000000606043b000001200060043f000000c406500039000000220660035f000000000606043b000001400060043f000000e405500039000000220650035f000000000606043b0000131707600197000000000776004b0000006d0000c13d000001600060043f0000002005500039000000220550035f000000000505043b000013160650009c0000006d0000813d00000000074500190000001f0470003900001308050000410000002608000029000000000684004b0000000006000019000000000605401900001308044001970000130808800197000000000984004b000000000500a019000000000484013f000013080440009c000000000506c019000000000405004b0000006d0000613d000000220470035f000000000404043b000013160540009c00001b020000813d0000003f054000390000001f0650017f000000400500043d0000000006650019000000000856004b00001b020000413d000013160860009c00001b020000813d000000400060043f000000000645043600000020077000390000000008470019000000260880006c0000006d0000213d000000220870035f0000001f0740018f00000005094002720000066d0000613d000000000a000019000000050ba00210000000000cb60019000000000bb8034f000000000b0b043b0000000000bc0435000000010aa00039000000000b9a004b000006650000413d000000000a07004b0000067c0000613d0000000509900210000000000898034f00000000099600190000000307700210000000000a090433000000000a7a01cf000000000a7a022f000000000808043b0000010007700089000000000878022f00000000077801cf0000000007a7019f000000000079043500000000044600190000000000040435000001800050043f000000000303043b000013160430009c0000006d0000813d000000230430003900001308050000410000002607000029000000000674004b0000000006000019000000000605401900001308077001970000130804400197000000000874004b000000000500a019000000000474013f000013080440009c000000000506c019000000000405004b0000006d0000613d0000000405300039000000220350035f000000000403043b000013160340009c00001b020000813d0000003f034000390000001f0330017f000000400600043d0000000003360019001d00000006001d000000000663004b00001b020000413d000013160630009c00001b020000813d000000400030043f0000001d030000290000000003430436001e00000003001d00000020034000390000000006530019000000260660006c0000006d0000213d0000002005500039000000220650035f0000001f0540018f0000000504400272000006b50000613d000000000700001900000005087002100000001e09800029000000000886034f000000000808043b00000000008904350000000107700039000000000847004b000006ad0000413d000000000705004b000006c40000613d0000000504400210000000000646034f0000001e044000290000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f00000000005404350000001d033000290000000000030435000000000302043b000013160230009c0000006d0000813d0000000402300039000000260420006900001308050000410000011f0640008c000000000600001900000000060520190000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d000000400400043d001700000004001d0000131b0440009c00001b020000813d00000017040000290000012004400039000000400040043f000000220420035f000000000404043b0000130a0540009c0000006d0000813d00000017050000290000000004450436001b00000004001d0000002004200039000000220440035f000000000404043b000013160540009c0000006d0000813d0000000004240019000000260540006900001308060000410000003f0750008c000000000700001900000000070620190000130805500197000000000805004b0000000006008019000013080550009c000000000607c019000000000506004b0000006d0000613d000000400500043d000013190650009c00001b020000813d000106fb0000003d00004bc00000013d000013160870009c0000006d0000813d0000000007470019000000260870006900001308090000410000003f0a80008c000000000a000019000000000a0920190000130808800197000000000b08004b0000000009008019000013080880009c00000000090ac019000000000809004b0000006d0000613d0000131a0850009c00001b020000213d0000008008500039000000000968004b00001b020000413d000000400080043f000000220870035f000000000808043b0000131709800197000000000998004b0000006d0000c13d000107170000003d00004baf0000013d000013160980009c0000006d0000813d000000000a7800190000001f07a0003900001308080000410001071e0000003d00004af60000013d0000130807700197000013080bb00197000000000cb7004b000000000800a0190000000007b7013f000013080770009c000000000809c019000000000708004b0000006d0000613d0000002207a0035f000000000707043b000013160870009c00001b020000813d0000003f087000390000001f0980017f000000400800043d0000000009980019000000000b89004b00001b020000413d000013160b90009c00001b020000813d000107350000003d00004a0a0000013d0000006d0000213d000000220ba0035f0000001f0a70018f000000050c7002720000073e0000613d000000000d0000190001073d0000003d00004aab0000013d0000073b0000413d000000000d0a004b000007450000613d000000050cc00210000000000bcb034f000000000cc90019000107450000003d000046820000013d000107470000003d000046f20000013d0000001b0400002900000000005404350000004404300039000000220540035f000000000505043b0000130a0650009c0000006d0000813d00000017060000290000004006600039001900000006001d00000000005604350000002004400039000000220440035f000000000404043b000013160540009c0000006d0000813d0000000004240019000000260540006900001308060000410000003f0750008c000000000700001900000000070620190000130805500197000000000805004b0000000006008019000013080550009c000000000607c019000000000506004b0000006d0000613d000000400500043d000013190650009c00001b020000813d000107690000003d00004bc00000013d000013160870009c0000006d0000813d0000000007470019000000260870006900001308090000410000003f0a80008c000000000a000019000000000a0920190000130808800197000000000b08004b0000000009008019000013080880009c00000000090ac019000000000809004b0000006d0000613d0000131a0850009c00001b020000213d0000008008500039000000000968004b00001b020000413d000000400080043f000000220870035f000000000808043b0000131709800197000000000998004b0000006d0000c13d000107850000003d00004baf0000013d000013160980009c0000006d0000813d000000000a7800190000001f07a0003900001308080000410001078c0000003d00004af60000013d0000130807700197000013080bb00197000000000cb7004b000000000800a0190000000007b7013f000013080770009c000000000809c019000000000708004b0000006d0000613d0000002207a0035f000000000707043b000013160870009c00001b020000813d0000003f087000390000001f0980017f000000400800043d0000000009980019000000000b89004b00001b020000413d000013160b90009c00001b020000813d000107a30000003d00004a0a0000013d0000006d0000213d000000220ba0035f0000001f0a70018f000000050c700272000007ac0000613d000000000d000019000107ab0000003d00004aab0000013d000007a90000413d000000000d0a004b000007b30000613d000000050cc00210000000000bcb034f000000000cc90019000107b30000003d000046820000013d000107b50000003d000046f20000013d00000017060000290000006004600039001600000004001d00000000005404350000008404300039000000220440035f000000000404043b0000008005600039001800000005001d0000000000450435000000a404300039000000220440035f000000000404043b000000a005600039001500000005001d0000000000450435000000c404300039000000220440035f000000c005600039000000000404043b001400000005001d0000000000450435000000e403300039000000220430035f000000000404043b0000131705400197000000000554004b0000006d0000c13d0000001705000029000000e005500039001300000005001d00000000004504350000002003300039000000220330035f000000000303043b000013160430009c0000006d0000813d00000000052300190000001f0250003900001308030000410000002606000029000000000462004b0000000004000019000000000403401900001308022001970000130806600197000000000762004b000000000300a019000000000262013f000013080220009c000000000304c019000000000203004b0000006d0000613d000000220250035f000000000202043b000013160320009c00001b020000813d0000003f032000390000001f0430017f000000400300043d0000000004430019000000000634004b00001b020000413d000013160640009c00001b020000813d000000400040043f000000000423043600000020055000390000000006250019000000260660006c0000006d0000213d000000220650035f0000001f0520018f0000000507200272000008040000613d0000000008000019000108030000003d000045760000013d000008010000413d000000000805004b000008080000613d000108080000003d000044790000013d0000000002240019000000000002043500000017020000290000010002200039001200000002001d0000000000320435000000000101043b000013160210009c0000006d0000813d000000230210003900001308030000410000002605000029000000000452004b0000000004000019000000000403401900001308055001970000130802200197000000000652004b000000000300a019000000000252013f000013080220009c000000000304c019000000000203004b0000006d0000613d0000000403100039000000220130035f000000000201043b000013160120009c00001b020000813d0000003f012000390000001f0110017f000000400400043d0000000001140019001a00000004001d000000000441004b00001b020000413d000013160410009c00001b020000813d000000400010043f0000001a010000290000000001210436001c00000001001d00000020012000390000000004310019000000260440006c0000006d0000213d0000002003300039000000220430035f0000001f0320018f0000000502200272000008440000613d000000000500001900000005065002100000001c07600029000000000664034f000000000606043b00000000006704350000000105500039000000000625004b0000083c0000413d000000000503004b000008530000613d0000000502200210000000000424034f0000001c022000290000000303300210000000000502043300000000053501cf000000000535022f000000000404043b0000010003300089000000000434022f00000000033401cf000000000353019f00000000003204350000001a011000290000000000010435000001200100043d001100000001001d000000000101004b0000085f0000613d0001085b0000003d000045110000013d0000131c020000414bfc43ed0000040f000000110110006b000025740000813d000001400100043d001100000001001d000000000101004b000008690000613d000108650000003d000045110000013d0000131c020000414bfc43ed0000040f000000110110006b0000257b0000a13d000000800100043d000001000200043d000000000202004b000021bc0000c13d00001309011001980000253e0000613d0000000002000411000000230320006b000008810000c13d0000001f03000029000108750000003d0000481e0000013d0000087a0000613d0000000004000019000108790000003d000048160000013d000008770000413d000000200400006b0000087e0000613d0001087e0000003d000044330000013d000108800000003d000046ed0000013d00001309022001970000130902200197000000000112004b0000253e0000613d00000ea50000013d000013520180009c000009f30000c13d0000000001000416000000000101004b0000006d0000c13d00001308010000410001088d0000003d000048840000013d0000130803500197000000000503004b0000000001008019000013080330009c000000000102c019000000000101004b0000006d0000613d000000000104043b0000012f02000039000000200020043f00000000001004350001089a0000003d000049eb0000013d000009990000013d00230000000f001d000013400180009c00000a0b0000c13d0000000001000416000000000101004b0000006d0000c13d00001308010000410000005f0650008c000000000600001900000000060120190000130805500197000000000705004b0000000001008019000013080550009c000000000106c019000000000101004b0000006d0000613d000000000104043b002513090010019b000013090110009c0000006d0000213d000000000103043b002213110010019b000013120110009c0000006d0000813d000000000102043b002113110010019b002000000001001d000013110110009c0000006d0000213d00000000020004110000002303000029000000000123004b001f00000002001d000000000709034f00000000080b0019000008d90000c13d000108c20000003d000048b00000013d000000000108004b000008cd0000613d00000000010000190000000502100210000000000327034f000000000303043b000000a00220003900000000003204350000000101100039000000000281004b000008c50000413d00000000030a0019000000000103004b000008d50000613d0000000501800210000000000217034f0000000303300210000108d50000003d000044630000013d00000000000e043500000000010d043300001309021001970000002303000029000000330d00003900000000010d041a000000000221013f000013090220019800000ad20000c13d0000001f0230006c0000001f02000029000009000000c13d000000200200008a00000000032c016f000000400200043d0000000003230019000000400030043f00000026030000290000000003320436000000000408004b000008ee0000613d0000000004000019000108ed0000003d000045fb0000013d000008eb0000413d00000000040a004b000008fd0000613d0000000504b00210000000000549034f00000000044300190000000306a00210000000000704043300000000076701cf000000000767022f000000000505043b0000010006600089000000000565022f00000000056501cf000000000575019f0000000000540435000108ff0000003d000046ed0000013d0000130902200197000000000121013f000013090110019800000ad20000c13d00240000000d001d000109060000003d000047f10000013d0000130901100197000109090000003d00004a9b0000013d0000130003000041000013000410009c0001090d0000003d00004a5f0000013d000013000420009c000109100000003d000049450000013d0000000002000414000013000420009c000109140000003d000048ac0000013d0000130b011001c70000800d02000039000000010300003900001342040000414bfc44050000040f00000001012001900000006d0000613d0000002603000029000000000103041a0000130d0210019700000025022001af000000000023041b0000001f03000029000000230230006b0000000002030019000009360000c13d00000000020000310000003f03200039000000200400008a000000000443016f0001092a0000003d000046cd0000013d0000092f0000613d00000000080000190001092e0000003d000045760000013d0000092c0000413d000000000805004b000009330000613d000109330000003d000044790000013d000109350000003d00004a190000013d00001309022001970000002403000029000000000303041a000000000223013f000013090220019800000ad20000c13d000000400200043d000000200320003900000022040000290000000000430435000000a0011002700000131101100197000109430000003d00004a9b0000013d0000130003000041000013000410009c000109470000003d00004a5f0000013d000013000420009c0001094a0000003d000049450000013d0000000002000414000013000420009c0001094e0000003d000048ac0000013d0000130b011001c70000800d0200003900000001030000390000133b040000414bfc44050000040f00000001012001900000006d0000613d0000002201000029000000a0021002100000002604000029000000000104041a0000133c03100197000000000223019f000000000024041b0000001f03000029000000230230006b000009710000c13d00000000020000310000003f03200039000000200400008a000000000443016f000109650000003d000046cd0000013d0000096a0000613d0000000008000019000109690000003d000045760000013d000009670000413d000000000805004b0000096e0000613d0001096e0000003d000044790000013d000109700000003d00004a190000013d001f13090020019b0000002402000029000000000202041a0000001f0220014f000013090220019800000ad20000c13d000000400200043d000000200320003900000021040000290000000000430435000000d0011002700001097d0000003d00004a9b0000013d0000130003000041000013000410009c000109810000003d00004a5f0000013d000013000420009c000109840000003d000049450000013d0000000002000414000013000420009c000109880000003d000048ac0000013d0000130b011001c70000800d02000039000000010300003900001313040000414bfc44050000040f00000001012001900000006d0000613d0000002001000029000009ee0000013d000013480180009c00000a4f0000c13d0000000001000416000000000101004b0000006d0000c13d0000016201000039000000000101041a0000130901100197000000800010043f0000008001000039000000200200003900004b320000013d00000000070b001900000000060a0019000013060180009c00000a890000c13d0000000001000416000000000101004b0000006d0000c13d0000130801000041000109a70000003d000048840000013d0000130803500197000000000503004b0000000001008019000013080330009c000000000102c019000000000101004b0000006d0000613d000000000204043b0000131101200197002500000002001d000013120220009c0000006d0000813d000000000200041100000000032f004b000009cc0000c13d000000200200008a000000240220017f000000400020043f0000002602000029000000800020043f000000000207004b000009c20000613d0000000002000019000109c00000003d00004afb0000013d000000000372004b000009be0000413d000000000206004b000009c90000613d0000000502700210000000000329034f0000000304600210000109c90000003d000048ff0000013d00000000000e043500000000020d043300001309022001970000003303000039000000000303041a000000000223013f000013090220019800000ad20000c13d0000016102000039002600000002001d000000000202041a000000400300043d00000020043000390000000000140435000000d0012002700000000000130435000000400100043d00000000021300490000130003000041000013000410009c000109df0000003d00004a5f0000013d000013000420009c000109e20000003d000049450000013d0000000002000414000013000420009c000109e60000003d000048ac0000013d0000130b011001c70000800d02000039000000010300003900001313040000414bfc44050000040f00000001012001900000006d0000613d0000002501000029000000d0011002100000002603000029000000000203041a0000131402200197000002260000013d000013530180009c0000006d0000c13d0000000001000416000000000101004b0000006d0000c13d0000130801000041000109fb0000003d000048840000013d0000130803500197000000000503004b0000000001008019000013080330009c000000000102c019000000000101004b0000006d0000613d000000000104043b0000130a0210009c0000006d0000813d00000000001004350000019301000039000000200010043f00010a0a0000003d000049eb0000013d0000017d0000013d000013410180009c0000006d0000c13d0000000001000416000000000101004b0000006d0000c13d000013080100004100010a130000003d000048840000013d0000130803500197000000000503004b0000000001008019000013080330009c000000000102c019000000000101004b0000006d0000613d000000000104043b002513090010019b0000130a0110009c0000006d0000813d0000000001000411000000230210006b00000a320000c13d00010a230000003d000047150000013d00000a280000613d000000000100001900010a270000003d000046950000013d00000a250000413d00000000010a004b00000a2f0000613d0000000501b00210000000000219034f0000000303a0021000010a2f0000003d000044630000013d00000000000e043500000000010d043300001309011001970000003302000039000000000202041a000000000112013f000013090110019800000ad20000c13d00010a390000003d000047f10000013d000013090110019700010a3c0000003d00004a9b0000013d0000130003000041000013000410009c00010a400000003d00004a5f0000013d000013000420009c00010a430000003d000049450000013d0000000002000414000013000420009c00010a470000003d000048ac0000013d0000130b011001c70000800d02000039000000010300003900001342040000414bfc44050000040f000000010120019000000ec70000c13d0000006d0000013d000013490180009c0000006d0000c13d0000000001000416000000000101004b0000006d0000c13d000000000100041100000000021f004b00000a6b0000c13d00010a590000003d000048b00000013d00000000050b0019000000000105004b000000000409034f00000a610000613d000000000100001900010a600000003d00004a6f0000013d00000a5e0000413d00000000010a004b00000a680000613d0000000501500210000000000214034f0000000303a0021000010a680000003d000044630000013d00000000000e043500000000010d043300001309011001970000003303000039000000000203041a00001309052001970000130901100197000000000115004b00000ad20000c13d002600000003001d000000400100043d00001300020000410000000003000414000013000430009c0000000003028019000013000410009c00000000010280190000004001100210000000c002300210000000000112019f0000130b011001c70000800d0200003900000003030000390000130c0400004100000000060000194bfc44050000040f00000001012001900000006d0000613d0000002602000029000000000102041a0000130d01100197000000000012041b000002a90000013d000013070180009c0000006d0000c13d0000000001000416000000000101004b0000006d0000c13d000013080100004100010a910000003d000048840000013d0000130803500197000000000503004b0000000001008019000013080330009c000000000102c019000000000101004b0000006d0000613d000000000104043b002513090010019b0000130a0110009c0000006d0000813d000000000100041100000000021f004b00000ab60000c13d00010aa10000003d000048b00000013d000000000107004b00000aac0000613d00000000010000190000000502100210000000000329034f000000000303043b000000a00220003900000000003204350000000101100039000000000271004b00000aa40000413d000000000106004b00000ab30000613d0000000501700210000000000219034f000000030360021000010ab30000003d000044630000013d00000000000e043500000000010d0433000013090110019700001309051001970000003302000039000000000102041a0000130901100197000000000151004b00000ad20000c13d002600000002001d000000400200043d0000002506000029000000000106004b00000eb70000c13d00000064012000390000130e03000041000000000031043500000044012000390000130f03000041000000000031043500000024012000390000002603000039000000000031043500001310010000410000000000120435000000040120003900000020030000390000000000310435000000400100043d000000000212004900004b550000013d000000400200043d00000044012000390000134e0300004100000000003104350000131001000041000000000012043500000024012000390000002003000039000000000031043500000004012000390000000000310435000000400100043d000000000212004900000064022000394bfc43c30000040f0000134a05000041000000c00050043f000001200040043f0000002004000039000001000040043f0000010004000039000000e00040043f002501400000003d001802400000003d001902200000003d001e02000000003d001f01e00000003d001d01c00000003d001c01a00000003d001b01800000003d001a01600000003d0000026004000039000000220500035f000000400040043f000000a00330008a000000000435034f000000000404043b0000130a0540009c0000006d0000813d00000025050000290000000000450435000000400c00043d0000008004c00039000000400040043f0000004003300039000000220430035f000000000404043b0000131705400197000000000554004b0000006d0000c13d000000400dc0003900000000004d0435000000200b3000390000002203b0035f000000000303043b0000001f0220008a000013080530019700001308062001970000130807000041000000000865004b00000000080000190000000008072019000000000565013f000000000623004b0000000007008019000013080550009c000000000807c019000000000508004b0000006d0000613d0000000005130019000000220350035f000000000303043b000013160630009c0000006d0000813d000000260630006900000020055000390000130807000041000000000865004b0000000008000019000000000807201900001308066001970000130809500197000000000a69004b0000000007008019000000000669013f000013080660009c000000000708c019000000000607004b0000006d0000c13d0000001f063000390000134c06600197001600200060003d000000400e00043d0000001606e00029000000400060043f000000220550035f0015001f00300193000000000f3e0436000000050730027200000b3f0000613d00000000080000190000000509800210000000000a9f0019000000000995034f000000000909043b00000000009a04350000000108800039000000000978004b00000b370000413d0017006000c0003d0000001509000029000000000609004b0013000500700218001400030090021800000b510000613d0000001309500360000000130af0002900000000060a0433000000140800002900000000068601cf0012000000860237000000000609043b0000010009800089000000000696022f00000000069601cf00000012066001af00000000006a043500000000063f0019000000000006043500000017060000290000000000e604350000000006dc04360000004008b0008a000000220880035f000000000808043b00000000008604350000001a060000290000000000c604350000001b060000290000000000060435000000400600043d0000004008600039000000400080043f000000c00c0000390000000008c604360000002009b00039000000220990035f000000000909043b00000000009804350000001c0800002900000000006804350000006006b00039000000220660035f000000000606043b0000001d0800002900000000006804350000008006b00039000000220660035f000000000606043b0000001f080000290000000000680435000000a006b00039000000220660035f000000000606043b0000001e080000290000000000680435000000c009b00039000000220690035f000000000b06043b0000131706b0019700000000066b004b0000006d0000c13d00000019060000290000000000b604350000002008900039001700000008001d000000220980035f000000000909043b000013080a000041000000000d29004b000000000d000019000000000d0a4019000013080e200197000013080f9001970000000008ef004b000000000a00a0190000000008ef013f000013080880009c000000000a0dc01900000000080a004b0000006d0000613d0000000009190019000000220690035f000000000606043b001200000006001d000013160660009c0000006d0000813d0000001208000029000000260680006900000020099000390000130808000041000000000a69004b000000000a000019000000000a0820190000130806600197000013080d900197000000000e6d004b000000000800801900000000066d013f000013080660009c00000000080ac019000000000608004b0000006d0000c13d000000120a0000290000001f08a000390000134c08800197000000400e00043d000000200fe0003900000000088f0019000000400080043f000000220d90035f00100000000e001d0000000000ae04350011001f00a001930000000509a0027200000bbd0000613d000000000a0000190000000508a00210000000000e8f001900000000088d034f000000000808043b00000000008e0435000000010aa0003900000000089a004b00000bb50000413d000000110600006b00000bcd0000613d000000050890021000000000098d034f00000000088f00190000001106000029000000030a600210000000000d080433000000000dad01cf000000000dad022f000000000909043b000001000aa000890000000009a9022f0000000009a901cf0000000009d9019f00000000009804350000001208f000290000000000080435000000180600002900000010080000290000000000860435000000400600043d0000012008600039000000400080043f0000000008060436000000400900043d000000400a9000390000004000a0043f000000000ac90436000000170c000029000000400cc00039000000220dc0035f000000000d0d043b0000000000da04350000000000980435001700000006001d00000040086000390000000000080435000000400d00043d0000008008d00039000000400080043f000000400ed0003900000000004e0435000000400400043d0000001608400029000000400080043f000000000a340436000000000807004b00000bf70000613d00000000090000190000000508900210000000000f8a0019000000000885034f000000000808043b00000000008f04350000000109900039000000000879004b00000bef0000413d0000001706000029001600600060003d0000006007d00039000000150600006b00000c080000613d00000013055003600000001306a000290000000008060433000000140900002900000000089801cf000000000898022f000000000505043b0000010009900089000000000595022f00000000059501cf000000000585019f000000000056043500000000033a0019000000000003043500000000004704350000000003ed04360000002004c00039000000220440035f000000000404043b000000000043043500000016030000290000000000d304350000001704000029000000e0034000390000000000b30435000000c0034000390000000000030435000000a0034000390000000000030435000000800340003900000000000304350000004003c00039000000220430035f000000000404043b00001308052001970000130806000041000000000724004b000000000700001900000000070640190000130808400197000000000958004b000000000600a019000000000558013f000013080550009c000000000607c019000000000506004b0000006d0000613d0000000005140019000000220450035f000000000404043b000013160640009c0000006d0000813d000000260640006900000020075000390000130805000041000000000867004b0000000008000019000000000805201900001308066001970000130809700197000000000a69004b0000000005008019000000000669013f000013080660009c000000000508c019000000000505004b0000006d0000c13d0000001f054000390000134c0850019700010c430000003d00004a100000013d00000c480000613d000000000a00001900010c470000003d00004a3b0000013d00000c450000413d000000170a000029000001000aa00039000000000b08004b00000c4e0000613d00010c4e0000003d000047530000013d0000000004460019000000000004043500000000005a0435000000600330008a000000220330035f000000000303043b0000130804000041000000000523004b0000000005000019000000000504401900001308022001970000130806300197000000000726004b000000000400a019000000000226013f000013080220009c000000000405c019000000000204004b0000006d0000613d0000000002130019000000220120035f000000000101043b000013160310009c0000006d0000813d000000260310006900000020022000390000130804000041000000000532004b0000000005000019000000000504201900001308033001970000130806200197000000000736004b0000000004008019000000000336013f000013080330009c000000000405c019000000000304004b0000006d0000c13d0000001f031000390000134c03300197000000400400043d00000020084000390000000003380019000000400030043f000000220220035f001300000004001d00000000001404350000001f0310018f000000050410027200000c870000613d00000000050000190000000506500210000000000768001900010c860000003d000045be0000013d00000c820000413d001500000008001d000000000503004b00000c8f0000613d0000000504400210000000000242034f000000150440002900010c8f0000003d0000446e0000013d000000150110002900000000000104350000001f010000290000000001010433001400000001001d000000000101004b00000c9c0000613d00010c980000003d000045110000013d0000131c020000414bfc43ed0000040f000000140110006b000025740000813d0000001e010000290000000001010433001400000001001d000000000101004b00000ca70000613d00010ca30000003d000045110000013d0000131c020000414bfc43ed0000040f000000140110006b0000257b0000a13d000000250100002900000000010104330000001d020000290000000002020433000000000202004b000010e70000c13d0000130901100198000011910000613d0000000002000411000000230320006b00000ea20000c13d00010cb40000003d0000457e0000013d00000cb90000613d000000000400001900010cb80000003d000045fb0000013d00000cb60000413d000000200400006b00000cbd0000613d00010cbd0000003d000044330000013d00010cbf0000003d000046ed0000013d000013090220019700000ea20000013d0000134a06000041000000c00060043f000001200050043f0000002005000039000001000050043f0000010005000039000000e00050043f001701400000003d001902400000003d001a02200000003d001c02000000003d001d01e00000003d001b01c00000003d001601a00000003d001f01800000003d001e01600000003d0000026005000039000000220600035f000000400050043f000000a00540008a000000000456034f000000000404043b0000130a0640009c0000006d0000813d00000017060000290000000000460435000000400600043d0000004004600039000000400040043f000000c00400003900000000074604360000008008500039000000220880035f000000000808043b00000000008704350000001e0700002900000000006704350000001f060000290000000000060435000000400d00043d0000008006d00039000000400060043f0000004005500039000000220650035f000000000606043b0000131707600197000000000776004b0000006d0000c13d000000400fd0003900000000006f0435000000200e5000390000002205e0035f000000000505043b0000001f0330008a000013080750019700001308083001970000130809000041000000000a87004b000000000a000019000000000a092019000000000787013f000000000835004b0000000009008019000013080770009c000000000a09c01900000000070a004b0000006d0000613d0000000007150019000000220570035f000000000505043b000013160850009c0000006d0000813d000000260850006900000020077000390000130809000041000000000a87004b000000000a000019000000000a0920190000130808800197000013080b700197000000000c8b004b000000000900801900000000088b013f000013080880009c00000000090ac019000000000809004b0000006d0000c13d0000001f085000390000134c08800197001200200080003d000000400900043d0000001208900029000000400080043f000000220770035f0018001f00500193002500000009001d000000000c590436000000050950027200000d2d0000613d000000000a0000190000000508a00210000000000b8c0019000000000887034f000000000808043b00000000008b0435000000010aa0003900000000089a004b00000d250000413d0015006000d0003d000000180a00002900000000080a004b00130005009002180014000300a0021800000d410000613d0011001300700364000000130bc0002900000000080b0433000000140a0000290000000008a801cf0010000000a80237000000110800035f000000000808043b001100000008001d0000010008a00089000000110a80024f00000000088a01cf00000010088001af00000000008b043500000000085c001900000000000804350000002508000029000000150a00002900000000008a04350000000008fd0436000000400ae0008a000000220aa0035f000000000a0a043b0000000000a8043500000016080000290000000000d804350000006008e00039000000220880035f000000000808043b0000001b0a00002900000000008a04350000008008e00039000000220880035f000000000808043b0000001d0a00002900000000008a0435000000a008e00039000000220880035f000000000808043b0000001c0a00002900000000008a0435000000c00ae000390000002208a0035f000000000d08043b0000131708d0019700000000088d004b0000006d0000c13d0000001a080000290000000000d80435000000200aa00039000000220aa0035f000000000a0a043b000013080b000041000000000c3a004b000000000c000019000000000c0b4019000013080e300197000013080fa001970000000008ef004b000000000b00a0190000000008ef013f000013080880009c000000000b0cc01900000000080b004b0000006d0000613d000000000a1a00190000002208a0035f000000000808043b002500000008001d000013160880009c0000006d0000813d000000250b0000290000002608b00069000000200ca00039000013080a000041000000000b8c004b000000000b000019000000000b0a20190000130808800197000013080ec00197000000000f8e004b000000000a00801900000000088e013f000013080880009c000000000a0bc01900000000080a004b0000006d0000c13d000000250a0000290000001f08a000390000134c08800197000000400e00043d000000200be0003900000000088b0019000000400080043f000000220cc0035f00110000000e001d0000000000ae04350015001f00a00193000000050fa0027200000da00000613d000000000a0000190000000508a00210000000000e8b001900000000088c034f000000000808043b00000000008e0435000000010aa000390000000008fa004b00000d980000413d000000150800006b00000db00000613d0000000508f00210000000000a8c034f00000000088b0019000000150c000029000000030cc00210000000000e080433000000000ece01cf000000000ece022f000000000a0a043b000001000cc00089000000000aca022f000000000aca01cf000000000aea019f0000000000a804350000002508b0002900000000000804350000001908000029000000110a0000290000000000a80435000000400a00043d0000012008a00039000000400080043f00250000000a001d00000000080a0436001500000008001d000000400f00043d0000008008f00039000000400080043f000000400bf0003900000000006b0435000000400600043d0000001208600029000000400080043f000000000c560436000000000809004b00000dcf0000613d000000000a0000190000000508a00210000000000e8c0019000000000887034f000000000808043b00000000008e0435000000010aa0003900000000089a004b00000dc70000413d0000006009f00039000000180800006b00000dde0000613d00000013077003600000001308c00029000000000a080433000000140e000029000000000aea01cf000000000aea022f000000000707043b000001000ee000890000000007e7022f0000000007e701cf0000000007a7019f000000000078043500000000055c0019000000000005043500000000006904350000000005bf0436000001a406200039000000220660035f000000000606043b000000000065043500000015050000290000000000f50435000000250700002900000040057000390000000000050435000000400500043d0000004006500039000000400060043f00000000044504360000018406200039000000220660035f000000000606043b0000000000640435000000e0047000390000000000d4043500000060047000390000000000540435000000c0047000390000000000040435000000a004700039000000000004043500000080047000390000000000040435000001c402200039000000220420035f000000000404043b00001308053001970000130806000041000000000734004b000000000700001900000000070640190000130808400197000000000958004b000000000600a019000000000558013f000013080550009c000000000607c019000000000506004b0000006d0000613d0000000005140019000000220450035f000000000404043b000013160640009c0000006d0000813d000000260640006900000020075000390000130805000041000000000867004b0000000008000019000000000805201900001308066001970000130809700197000000000a69004b0000000005008019000000000669013f000013080660009c000000000508c019000000000505004b0000006d0000c13d0000001f054000390000134c0850019700010e250000003d00004a100000013d00000e2a0000613d000000000a00001900010e290000003d00004a3b0000013d00000e270000413d000000250a000029000001000aa00039000000000b08004b00000e300000613d00010e300000003d000047530000013d0000000004460019000000000004043500000000005a0435000000600220008a000000220220035f000000000202043b0000130804000041000000000532004b0000000005000019000000000504401900001308033001970000130806200197000000000736004b000000000400a019000000000336013f000013080330009c000000000405c019000000000304004b0000006d0000613d0000000002120019000000220120035f000000000101043b000013160310009c0000006d0000813d000000260310006900000020022000390000130804000041000000000532004b0000000005000019000000000504201900001308033001970000130806200197000000000736004b0000000004008019000000000336013f000013080330009c000000000405c019000000000304004b0000006d0000c13d0000001f031000390000134c03300197000000400400043d00000020084000390000000003380019000000400030043f000000220220035f001400000004001d00000000001404350000001f0310018f000000050410027200000e690000613d00000000050000190000000506500210000000000768001900010e680000003d000045be0000013d00000e640000413d001800000008001d000000000503004b00000e710000613d0000000504400210000000000242034f000000180440002900010e710000003d0000446e0000013d000000180110002900000000000104350000001d010000290000000001010433001500000001001d000000000101004b00000e7e0000613d00010e7a0000003d000045110000013d0000131c020000414bfc43ed0000040f000000150110006b000025740000813d0000001c010000290000000001010433001500000001001d000000000101004b00000e890000613d00010e850000003d000045110000013d0000131c020000414bfc43ed0000040f000000150110006b0000257b0000a13d000000170100002900000000010104330000001b020000290000000002020433000000000202004b0000117d0000c13d0000130901100198000011910000613d0000000002000411000000230320006b00000ea20000c13d00010e960000003d0000457e0000013d00000e9b0000613d000000000400001900010e9a0000003d000045fb0000013d00000e980000413d000000200400006b00000e9f0000613d00010e9f0000003d000044330000013d00010ea10000003d000046ed0000013d00001309022001970000130902200197000000000112004b000011910000613d000000400200043d00000044012000390000136303000041000000000031043500000024012000390000001603000039000025810000013d000000440130003900001390020000410000000000210435000000240130003900000017020000390000000000210435000013100100004100000000001304350000000401300039000000200200003900000ede0000013d00001300010000410000000003000414000013000430009c0000000003018019000013000420009c00000000020180190000004001200210000000c002300210000000000112019f0000130b011001c70000800d0200003900000003030000390000130c040000414bfc44050000040f00000001012001900000006d0000613d0000002603000029000000000103041a0000130d0110019700000025011001af000000000013041b000002a90000013d000000400100043d002000000001001d000000200110008a0000000001010433000013090110019800000f650000c13d000000200300002900000044013000390000139802000041000000000021043500000024013000390000001102000039000000000021043500001310010000410000000000130435000000040130003900000026020000290000000000210435000000400100043d000000000213004900000064022000394bfc43c30000040f000013540120019700000101011001bf000000000010041b000000230300002900000080010000390000000002000411000000000323004b00000f040000c13d00010eed0000003d000048b00000013d0000002105000029000000000105004b000000220400035f00000ef50000613d000000000100001900010ef40000003d00004a6f0000013d00000ef20000413d000000200100006b00000efe0000613d00000021010000290000000501100210000000220210035f0000002003000029000000030330021000010efe0000003d000044630000013d0000001b010000290000000000010435000000400100043d0000001c020000290000000002020433000013090220019700001309062001970000003302000039000000000302041a0000130d03300197000000000363019f000000000032041b00001300020000410000000003000414000013000430009c0000000003028019000013000410009c00000000010280190000004001100210000000c002300210000000000112019f0000130b011001c70000800d0200003900000003030000390000130c0400004100000000050000194bfc44050000040f00000001012001900000006d0000613d000000000200041a000000190100006b00000f210000c13d0000135701000041000000000212016f000000000020041b002600000002001d0024ff00002001940000000001000019000000010100603900000f380000c13d009b00230000002d00010f290000003d0000441d0000013d0000009b0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b00000f320000613d0000002601000029000000ff0110019000000f5b0000c13d0000002601000029000013540110019700000101011001bf002600000001001d000000000010041b0000000001000019000000400400043d0000004002400039000000400020043f00000020034000390000135802000041001e00000003001d00000000002304350000000802000039001c00000004001d0000000000240435000000400400043d0000004002400039000000400020043f00000020034000390000135902000041002100000003001d00000000002304350000000102000039002200000002001d002000000004001d0000000000240435000000010110019000000f790000613d009500230000002d00010f520000003d0000441d0000013d000000950440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b00000f8e0000613d0000002601000029000000ff0110019000000f8e0000613d000000400200043d00000064012000390000135603000041000000000031043500000044012000390000135503000041000000000031043500000024012000390000002e0300003900000ac90000013d000000250110006c00000f7c0000c13d000000250100002900000000001004350000001b01000029000000200010043f000000400200003900000000010000194bfc43d70000040f000000000201041a000000010300008a000000000332004b0000100e0000c13d000000200300002900000044013000390000138702000041000000000021043500000024013000390000001b0200003900000ed90000013d00010f7b0000003d000047290000013d00000f950000013d000000200300002900000064013000390000139402000041000000000021043500000044013000390000139502000041000000000021043500000024013000390000002102000039000000000021043500001310010000410000000000130435000000040130003900000026020000290000000000210435000000400100043d000000000213004900004b550000013d00010f900000003d000047290000013d0000002601000029000013540110019700000001011001bf002600000001001d000000000010041b000000240100006b00000f9b0000c13d0000135701000041000000260210017f002600000002001d000000000020041b000000400200043d0000004001200039000000400010043f00000020012000390000135a0300004100000000003104350000000e030000390000000000320435000000400400043d002400000004001d0000004003400039000000400030043f0000002005400039002100000005001d0000135b0300004100000000003504350000002203000029000000000034043500000000020204334bfc43d70000040f00000024020000290000000002020433002400000001001d00000021010000294bfc43d70000040f002200000001001d00010fb70000003d000045110000013d00001321020000414bfc43ed0000040f0000135c02000041000000400400043d000000200340003900000000002304350000004002400039000000240300002900000000003204350000006002400039000000220300002900000000003204350000002302000029000013090220019700000080034000390000000000230435000000a00240003900010fca0000003d00004b850000013d002400000004001d000000c002400039002200000002001d000000400020043f00000000020304334bfc43d70000040f0000019402000039000000000012041b0000009701000039000000200010043f0000135d01000041000000000201041a0000130d022001970000001f022001af000000000021041b0000135e01000041000000000201041a0000130d0220019700000025022001af000000000021041b0000135f0100004100000000001004350000136001000041000000000201041a0000130d0220019700000025022001af000000000021041b00000026010000290000ff0001100190000010080000c13d009a00230000002d00010feb0000003d0000441d0000013d0000009a0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b000010880000613d0000002601000029000000ff01100190000010880000613d0000131001000041000000220200002900000000001204350000002403000029000001240130003900001356020000410000000000210435000001040130003900001355020000410000000000210435000000e4013000390000002e020000390000000000210435000000c40130003900000020020000390000000000210435000000400100043d000000000213004900000144022000394bfc43c30000040f0000016201000039000000000201041a0000130d022001970000001d022001af000000000021041b000010920000013d0000000102200039000000000021041b000000a00500003900000020010000290000002001100039000000800200043d0000000004020019000000000301001900000000560504340000001f0740008c0000101c0000a13d0000000003630436000000200440008a000010160000013d00000003054002100000010005500089000000010550020f000000000404004b00000000050060190000000004500049000000000446016f000000010550008a0000000006030433000000000556016f000000000445019f00000000004304350000000001120019000000240200002900000060022002100000000000210435000000400200043d00000000032100490000000c0330008a00000000003204350000001404100039000000400040043f000000000502043300000000030500190000000001040019000000200220003900000000060204330000001f0730008c0000103c0000a13d0000000001610436000000200330008a000010350000013d00000003023002100000010002200089000000010220020f000000000303004b00000000020060190000000003200049000000000336016f000000010220008a0000000006010433000000000226016f000000000232019f0000000000210435000000400300043d000000000100041400000023020000290000130902200197000000040620008c000010540000613d00000000044500190000000004340049000000000503001900000000060000194bfc000d0000040f002100000001001d002400600000003d00000001040000320000107a0000613d0000003f01400039000000220110017f000000400200043d0000000001120019000000400010043f0000001f0140018f002400000002001d0000000002420436000000030300036700000005044002720000106b0000613d000000000500001900000005065002100000000007620019000000000663034f000000000606043b00000000006704350000000105500039000000000645004b000010630000413d000000000501004b0000107a0000613d0000000504400210000000000343034f00000000024200190000000301100210000000000402043300000000041401cf000000000414022f000000000303043b0000010001100089000000000313022f00000000011301cf000000000141019f0000000000120435000000400200043d000000210100006b000010980000c13d00000044012000390000139703000041000000000031043500000024012000390000001c030000390000000000310435000013100100004100000000001204350000000401200039000000260300002900000adc0000013d0000016201000039000000000201041a0000130d022001970000001d022001af000000000021041b0000002601000029000013540110019700000001011001bf002600000001001d000000000010041b0000001a0100006b000002a90000c13d0000135701000041000000260110017f000000000010041b000002a90000013d0000004001200039000000600300003900000000003104350000000001000411000013090110019700000020032000390000000000130435000000250100002900000000001204350000006001200039000000800300043d00000000003104350000008001200039000000800200043d0000000003000019000000000423004b000010af0000813d0000000004130019000000a005300039000000000505043300000000005404350000002003300039000010a70000013d00000000011200190000001f02200190000010b90000613d0000000003210049000000030120021000000100021000890000000014030434000000000424022f00000000022401cf0000000000230435000000400200043d00000000012100490000130003000041000013000420009c00000000020380190000004002200210000013000410009c00000000010380190000006001100210000000000121019f0000000002000414000013000420009c000110c70000003d000048ac0000013d0000130b011001c70000800d02000039000000010300003900001396040000414bfc44050000040f00000001012001900000006d0000613d000000400200043d0000002601000029000000000312043600000024060000290000000001060433000000000013043500000040022000390000000003000019000000000413004b000010de0000813d00000000042300190000002003300039000000000563001900000000050504330000000000540435000010d60000013d000000000313004b000010e20000a13d000000000321001900000000000304350000001f01100039000000220110017f0000000002120019000000400100043d000001800000013d0000000002000411000000230320006b000010f80000c13d000110ec0000003d0000457e0000013d000010f10000613d0000000004000019000110f00000003d000045fb0000013d000010ee0000413d000000200400006b000010f50000613d000110f50000003d000044330000013d000110f70000003d000046ed0000013d0000130902200197000000000112013f0000130901100198000011910000613d0000001a0100002900000000010104330000000021010434002200000002001d0000000012010434002600000002001d00000000010104330000002502000029002500000002001d000111060000003d000049d60000013d0000131702200197000111090000003d000049110000013d0000131d030000410001110c0000003d0000448d0000013d0000131e030000410001110f0000003d000045d80000013d0000001b020000290000000002020433002200000002001d0000001c0200002900000000020204330000000032020434002000000003001d0000000023020434001c00000003001d0000000002020433002100000001001d00000000120204344bfc43d70000040f0000001c020000290000131702200197000111200000003d000049ae0000013d0000131d03000041000111230000003d000045020000013d0000131e05000041000111260000003d0000453e0000013d0000001d020000290000000002020433002000000002001d0000001f020000290000000002020433001f00000002001d0000001e020000290000000002020433001d00000002001d00000019020000290000000002020433001c00000002001d00000018020000290000000002020433001e00000001001d00000000120204344bfc43d70000040f0000001c0200002900001317022001970001113b0000003d000045650000013d00001309022001970001113e0000003d000048f80000013d0000130902200197000002400340003900000000002304350000131f02000041000111440000003d000048740000013d00000025020000290000000002020433002400000002001d003e13090020019b002200000001001d0001114b0000003d0000441d0000013d0000003e0440008a00000020044000c90000132002000041000111500000003d00004bcc0000013d000111520000003d000045110000013d0000132102000041000111550000003d0000471c0000013d0000132202000041000111580000003d0000486e0000013d00001309011001970001115b0000003d000045c40000013d00001323020000410001115e0000003d000046a90000013d002413090020019b000111610000003d0000468d0000013d000011c50000c13d00000013060000290000000006060433000000410660008c0000126f0000c13d00000015060000290000000006060433002100000006001d00000013070000290001116c0000003d000048680000013d000013280770009c0000130e0000813d000000f8076002700000132b0660009c000004a206900039000017db0000813d0000001b0870008a000000020880008c000017f50000813d0000002202000029000111780000003d000044f30000013d0000000001000414000000200530008a00000001020000390000002006000039000017e60000013d0000000002000411000000230320006b0000118e0000c13d000111820000003d0000457e0000013d000011870000613d0000000004000019000111860000003d000045fb0000013d000011840000413d000000200400006b0000118b0000613d0001118b0000003d000044330000013d0001118d0000003d000046ed0000013d0000130902200197000000000112013f0000130901100198000011d50000c13d000111930000003d000049dc0000013d00000000003204350000000000010435000111970000003d0000491d0000013d00000025010000290000002001100039001f00000001001d00000000010104330000000005010433000000160100002900000000010104330000000004010433000111a10000003d0000491d0000013d000111a30000003d00004b800000013d002200000003001d00000000003204350000000000010435002000000004001d0000000012040434002400000002001d001d00000001001d002600000005001d0000000021050434001e00000002001d0000131701100197002100000001001d0000134b0110009c000011b50000c13d000000240100002900001317011001970000134b0110009c000012d40000013d00000021010000290000134a0110009c000011bd0000c13d000000240100002900001317011001970000134a0110009c000012d60000c13d000012c80000013d0000002101000029000013640110009c000012670000c13d00000024010000290000131701100197000013640110009c000012d60000c13d000012c80000013d00001324060000410000002207000029000111c90000003d000049ff0000013d0000001302000029000111cc0000003d000049610000013d0000001506000029000000000412004b000012450000813d00000000043200190000000005620019000000000505043300000000005404350000002002200039000011cd0000013d0000001e01000029000111d80000003d00004adf0000013d001700000002001d000111db0000003d000049d60000013d0000131702200197000111de0000003d000049110000013d0000131d03000041000111e10000003d0000448d0000013d0000131e03000041000111e40000003d000045d80000013d0000001f02000029000111e70000003d000047c70000013d0000131702200197000111ea0000003d000049ae0000013d0000131d03000041000111ed0000003d000045020000013d0000131e05000041000111f00000003d0000453e0000013d0000001b020000290000000002020433002000000002001d0000001d020000290000000002020433001f00000002001d0000001c020000290000000002020433001d00000002001d0000001a020000290000000002020433001c00000002001d00000019020000290000000002020433001e00000001001d00000000120204344bfc43d70000040f0000001c020000290000131702200197000112050000003d000045650000013d0000130902200197000112080000003d000048f80000013d0000130902200197000002400340003900000000002304350000131f020000410001120e0000003d000047610000013d002400000002001d003d13090020019b002200000001001d000112130000003d0000441d0000013d0000003d0440008a00000020044000c90000132002000041000112180000003d00004bcc0000013d0001121a0000003d000045110000013d00001321020000410001121d0000003d0000471c0000013d0000132202000041000112200000003d0000486e0000013d0000130901100197000112230000003d000045c40000013d0000132302000041000112260000003d000046a90000013d002413090020019b000112290000003d0000468d0000013d0000127c0000c13d00000014060000290000000006060433000000410660008c0000126f0000c13d00000018060000290000000006060433002100000006001d0000001407000029000112340000003d000048680000013d000013280770009c0000130e0000813d000000f8076002700000132b0660009c000004a2069000390000194c0000813d0000001b0870008a000000020880008c000019650000813d0000002202000029000112400000003d000044f30000013d0000000001000414000000200530008a00000001020000390000002006000039000019570000013d002600000031001d0000001f011001900000124a0000613d0001124a0000003d000047050000013d000000400100043d002200000001001d009900240000002d0001124f0000003d0000441d0000013d000000990440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002402000029000000040220008c0000125e0000613d0001125b0000003d00004a770000013d000001560000613d000000400100043d002200000001001d00000001010000310000001f0110008c0000006d0000a13d000000220100002900000000010104330000131701100197000013240110009c000011910000613d000012ad0000013d00000021010000290000135f0110009c000012bc0000c13d000000240100002900001317011001970000135f0110009c000012d60000c13d000012c80000013d000013100100004100000022030000290000000000130435000013270100004100000000001504350000001f01000039000000000014043500000020010000390000000000120435000000400100043d0000000002190049000004e6022000394bfc43c30000040f00001324060000410000002207000029000112800000003d000049ff0000013d0000001402000029000112830000003d000049610000013d0000001806000029000000000412004b0000128c0000813d00000000043200190000000005620019000000000505043300000000005404350000002002200039000012840000013d002600000031001d0000001f01100190000012910000613d000112910000003d000047050000013d000000400100043d002200000001001d009800240000002d000112960000003d0000441d0000013d000000980440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002402000029000000040220008c000012a50000613d000112a20000003d00004a770000013d000001560000613d000000400100043d002200000001001d00000001010000310000001f0110008c0000006d0000a13d000000220100002900000000010104330000131701100197000013240110009c000011910000613d000000220300002900000064013000390000132502000041000000000021043500000044013000390000132602000041000000000021043500000024013000390000002b020000390000000000210435000013100100004100000000001304350000000401300039000000200200003900000f8a0000013d0000002101000029000112bf0000003d000048bc0000013d001c00000002001d4bfc43d70000040f000000000101041a001b13090010019c000013150000c13d00000024010000290000131701100197000000210110006c000017d40000c13d000112ca0000003d000048010000013d0000001e01000029000000000101043300000000120104344bfc43d70000040f0000001d020000290000000002020433002400000001001d00000000120204344bfc43d70000040f000000240110006b002400260000002d000012e00000613d000000400200043d0000004001200039000000400010043f002400000002001d000112dc0000003d000048b60000013d000000000001043500000024010000290000002001100039000000000021043500000024010000290000000001010433000013660110009c000013f10000813d000112e60000003d000049dc0000013d001c00000003001d0000000000320435000000000001043500000026010000290000000001010433002400000001001d000000200100002900000000010104330000131701100197002100000001001d0000134b0110009c000012f60000c13d000000240100002900001317011001970000134b0110009c000013e10000013d00000021010000290000134a0110009c000012fe0000c13d000000240100002900001317011001970000134a0110009c000013e30000c13d000013d20000013d0000002101000029000013640110009c000013060000c13d00000024010000290000131701100197000013640110009c000013e30000c13d000013d20000013d00000021010000290000135f0110009c000013c60000c13d000000240100002900001317011001970000135f0110009c000013e30000c13d000013d20000013d000013100100004100000022060000290000000000160435000013290100004100000000001304350000132a010000410000196b0000013d000000400100043d0000136502000041000000000021043500000004021000390000001c050000290000000000520435000000260300002900000000030304330000131703300197000000440410003900000000003404350000001e03000029000113230000003d000046360000013d000000000847004b000013280000813d000113270000003d000048ec0000013d000013230000013d000000000647004b0000132c0000a13d000000000554001900000000000504350000001f04400039001a0020000000920000001a0440017f0000000003340019000000200430003900000000022400490000002401100039000000000021043500000020010000290000000001010433000013170110019700000000001404350000001d01000029000000000101043300000040023000390000001c040000290001133e0000003d000047460000013d000000000352004b000013430000813d000113420000003d000048da0000013d0000133e0000013d001c00000006001d002400000005001d000000000152004b0000134a0000a13d0000001c0200002900000024012000290000000000010435000000400100043d002100000001001d003f001b0000002d0001134f0000003d0000441d0000013d0000003f0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001b02000029000000040220008c000013650000613d00000024020000290000001f022000390000001a0220017f0000001c02200029000000210300002900000000043200490000001b02000029000113620000003d000049890000013d000001560000613d000000400100043d002100000001001d000113670000003d000048260000013d00000021080000290000136f0000613d0000000005000019000000050650021000000000076800190001136e0000003d000045be0000013d0000136a0000413d000000000503004b000013760000613d0000000504400210000000000242034f0000002104400029000113760000003d0000446e0000013d0000130802000041000113790000003d00004ac30000013d0000130804100197000000000504004b0000000002008019000013080440009c000000000203c0190000001f031000390000001a0330017f0000002103300029002400000003001d000000400030043f000000000202004b0000006d0000613d00000021020000290000000002020433000013160320009c0000006d0000813d00000021011000290000002102200029000000000321004900001308040000410001138f0000003d00004abf0000013d0000130803300197000000000603004b0000000004008019000013080330009c000000000405c019000000000304004b0000006d0000613d0000002403000029000013190330009c00001b020000813d00000024030000290000004003300039000000400030043f00000000340204340000131705400197000000000554004b0000006d0000c13d000000240500002900000000004504350000000003030433000013160430009c0000006d0000813d00000000022300190000001f032000390000130804000041000113aa0000003d00004abb0000013d00001308033001970000130806100197000113ae0000003d00004ab70000013d000013080330009c000000000405c019000000000304004b0000006d0000613d0000000043020434000013160230009c00001b020000813d0000003f023000390000001a0520017f000000400200043d0000000005520019000000000625004b00001b020000413d000013160650009c00001b020000813d000113bf0000003d00004a1e0000013d0000006d0000213d0000000001000019000000000631004b00001ad20000813d000113c50000003d000048d40000013d000013c10000013d0000002101000029000113c90000003d000048bc0000013d001b00000002001d4bfc43d70000040f000000000101041a001a13090010019c000017f60000c13d00000024010000290000131701100197000000210110006c000017d40000c13d000113d40000003d00004b800000013d0000001c03000029000000000032043500000000000104350000001d01000029000000000101043300000000120104344bfc43d70000040f0000001e020000290000000002020433002600000001001d00000000120204344bfc43d70000040f000000260110006b002400200000002d000013ed0000613d000000400200043d0000004001200039000000400010043f002400000002001d000113e90000003d000048b60000013d000000000001043500000024010000290000002001100039000000000021043500000024010000290000000001010433000013660110009c000015540000413d00000025010000290000006001100039001d00000001001d0000000001010433000000000501043300000017010000290000002001100039001c00000001001d00000000010104330000000004010433000113fd0000003d000048010000013d000113ff0000003d0000491d0000013d001e00000004001d0000000012040434002100000002001d001a00000001001d002600000005001d0000000021050434001b00000002001d0000131701100197002000000001001d0000134b0110009c0000140e0000c13d000000210100002900001317011001970000134b0110009c0000143e0000013d00000020010000290000134a0110009c000014160000c13d000000210100002900001317011001970000134a0110009c000014400000c13d000014320000013d0000002001000029000013640110009c0000141e0000c13d00000021010000290000131701100197000013640110009c000014400000c13d000014320000013d00000020010000290000135f0110009c000014260000c13d000000210100002900001317011001970000135f0110009c000014400000c13d000014320000013d0000002001000029000114290000003d000048bc0000013d001900000002001d4bfc43d70000040f000000000101041a001813090010019c000014780000c13d00000021010000290000131701100197000000200110006c000017d40000c13d000114340000003d000048010000013d0000001b01000029000000000101043300000000120104344bfc43d70000040f0000001a020000290000000002020433002100000001001d00000000120204344bfc43d70000040f000000210110006b002100260000002d0000144a0000613d000000400200043d0000004001200039000000400010043f002100000002001d000114460000003d000048b60000013d000000000001043500000021010000290000002001100039000000000021043500000021010000290000000001010433000013660110009c0000155b0000813d000114500000003d000049dc0000013d001900000003001d0000000000320435000000000001043500000026010000290000000001010433002100000001001d0000001e0100002900000000010104330000131701100197002000000001001d0000134b0110009c000014600000c13d000000210100002900001317011001970000134b0110009c000015440000013d00000020010000290000134a0110009c000014680000c13d000000210100002900001317011001970000134a0110009c000015460000c13d000015350000013d0000002001000029000013640110009c000014700000c13d00000021010000290000131701100197000013640110009c000015460000c13d000015350000013d00000020010000290000135f0110009c000015290000c13d000000210100002900001317011001970000135f0110009c000015460000c13d000015350000013d000000400100043d00001365020000410000000000210435000000040210003900000019050000290000000000520435000000260300002900000000030304330000131703300197000000440410003900000000003404350000001b03000029000114860000003d000046360000013d000000000847004b0000148b0000813d0001148a0000003d000048ec0000013d000014860000013d000000000647004b0000148f0000a13d000000000554001900000000000504350000001f044000390015002000000092000000150440017f000000000334001900000020043000390000000002240049000000240110003900000000002104350000001e010000290000000001010433000013170110019700000000001404350000001a01000029000000000101043300000040023000390000001904000029000114a10000003d000047460000013d000000000352004b000014a60000813d000114a50000003d000048da0000013d000014a10000013d001900000006001d002100000005001d000000000152004b000014ad0000a13d000000190200002900000021012000290000000000010435000000400100043d002000000001001d004100180000002d000114b20000003d0000441d0000013d000000410440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001802000029000000040220008c000014c80000613d00000021020000290000001f02200039000000150220017f0000001902200029000000200300002900000000043200490000001802000029000114c50000003d000049890000013d000001560000613d000000400100043d002000000001001d000114ca0000003d000048260000013d0000002008000029000014d20000613d000000000500001900000005065002100000000007680019000114d10000003d000045be0000013d000014cd0000413d000000000503004b000014d90000613d0000000504400210000000000242034f0000002004400029000114d90000003d0000446e0000013d0000130802000041000114dc0000003d00004ac30000013d0000130804100197000000000504004b0000000002008019000013080440009c000000000203c0190000001f03100039000000150330017f0000002003300029002100000003001d000000400030043f000000000202004b0000006d0000613d00000020020000290000000002020433000013160320009c0000006d0000813d0000002001100029000000200220002900000000032100490000130804000041000114f20000003d00004abf0000013d0000130803300197000000000603004b0000000004008019000013080330009c000000000405c019000000000304004b0000006d0000613d0000002103000029000013190330009c00001b020000813d00000021030000290000004003300039000000400030043f00000000340204340000131705400197000000000554004b0000006d0000c13d000000210500002900000000004504350000000003030433000013160430009c0000006d0000813d00000000022300190000001f0320003900001308040000410001150d0000003d00004abb0000013d00001308033001970000130806100197000115110000003d00004ab70000013d000013080330009c000000000405c019000000000304004b0000006d0000613d0000000043020434000013160230009c00001b020000813d0000003f02300039000000150520017f000000400200043d0000000005520019000000000625004b00001b020000413d000013160650009c00001b020000813d000115220000003d00004a1e0000013d0000006d0000213d0000000001000019000000000631004b00001ad60000813d000115280000003d000048d40000013d000015240000013d00000020010000290001152c0000003d000048bc0000013d001800000002001d4bfc43d70000040f000000000101041a001513090010019c000018a10000c13d00000021010000290000131701100197000000200110006c000017d40000c13d000115370000003d00004b800000013d0000001903000029000000000032043500000000000104350000001a01000029000000000101043300000000120104344bfc43d70000040f0000001b020000290000000002020433002600000001001d00000000120204344bfc43d70000040f000000260110006b0021001e0000002d000015500000613d000000400200043d0000004001200039000000400010043f002100000002001d0001154c0000003d000048b60000013d000000000001043500000021010000290000002001100039000000000021043500000021010000290000000001010433000013660110009c0000155b0000813d000000400200043d00000044012000390000138d03000041000000000031043500000024012000390000001203000039000025810000013d000000400100043d0000008002100039000000400020043f00000020021000390000002203000029000000000032043500000060021000390000000000020435000000000031043500000040011000390000000000010435000000400100043d0000008002100039000000400020043f0000002002100039000000000032043500000000003104350000006002100039000000000002043500000040011000390000000000010435000115720000003d000047380000013d0000001f01000029000000000101043300000000010104330000000012010434002000000002001d00000000010104330000002503000029002500000003001d000000e0023000390000000003030433002600000003001d001b00000002001d0000000002020433001e00000002001d00000000120104344bfc43d70000040f00000020020000290000131702200197000000400400043d002000000004001d000000400340003900000000002304350000131d0300004100000020024000390001158c0000003d0000465a0000013d0000001d02000029000000000202043300000000020204330000000023020434001900000003001d0000000002020433001a00000001001d00000000120204344bfc43d70000040f000000190200002900001317022001970000002004000029000000c0034000390000000000230435000000a0024000390000131d030000410001159e0000003d000046650000013d0000001e090000290000131703900197000000260200002900001309052001970000002006000029002601a00060003d000001800260003900000160046000390000014007600039000000000a0600190000012008600039000000250b0000290000008006b00039001400000006001d0000000006060433000013380990009c001e010000b0003d000015ca0000213d000013390330009c000015ca0000613d0000001e03000029000000000303043300000000005804350000001a05000029000000000057043500000000001404350000000000620435000000a00100003900000026020000290000000000120435000001c001a0003900000000020304330000000000210435000001e001a0003900000000020304330000000004000019000000000524004b000015d30000813d00000000051400190000002004400039000000000634001900000000060604330000000000650435000015c20000013d00000000005804350000001a03000029000000000037043500000000001404350000000000620435000000400100043d00000000021200490000000000210435000015dc0000013d002600000012001d0000001f01200190000015d80000613d000115d80000003d000047050000013d000000400100043d0000002602100069000000200220008a00000000002104350000002602000029002600000002001d000000400020043f000000000201043300000020011000394bfc43d70000040f0000001c020000290000000002020433000000000202043300000020032000390000000002020433002000000002001d0000000002030433001200000001001d0000001701000029001700000001001d0000000003010433001a00000003001d000000e001100039001500000001001d0000000001010433001900000001001d00000000120204344bfc43d70000040f0000002002000029000013170220019700000026040000290000004003400039000000000023043500000020024000390000131d03000041000115fd0000003d0000465a0000013d0000001602000029000000000202043300000000020204330000000023020434002000000003001d0000000002020433001800000001001d00000000120204344bfc43d70000040f000000200200002900001317022001970000002604000029000000c0034000390000000000230435000000a0024000390000131d030000410001160f0000003d000046650000013d0000002603000029002001a00030003d0000018002300039000001600430003900000140053000390000012007300039000000190900002900001317039001970000001a060000290000130908600197000000170a0000290000008006a00039001300000006001d0000000006060433000013380990009c001a010000a0003d0000163b0000213d000013390330009c0000163b0000613d0000001a03000029000000000303043300000000008704350000001807000029000000000075043500000000001404350000000000620435000000a001000039000000200200002900000000001204350000002604000029000001c00140003900000000020304330000000000210435000001e00140003900000000020304330000000004000019000000000524004b000016440000813d00000000051400190000002004400039000000000634001900000000060604330000000000650435000016330000013d00000000008704350000001803000029000000000035043500000000001404350000000000620435000000400100043d00000000021200490000000000210435000016530000013d002000000012001d0000001f012001900000164f0000613d0000002002100069000000030110021000000100011000890000000043020434002000000004001d000000000313022f00000000011301cf0000000000120435000000400100043d0000002002100069000000200220008a00000000002104350000002002000029000000400020043f000000000201043300000020011000394bfc43d70000040f001900000001001d0000000002000411000000230120006b001100000002001d0000000001020019000016850000c13d00000000010000310000003f02100039000000200300008a000000000232016f00000020040000290000000002420019000000400020043f0000001f0310018f000000000214043600000002040003670000000505100272000016710000613d000000000600001900000005076002100000000008720019000000000774034f000116700000003d000044a70000013d0000166b0000413d000000000603004b000016800000613d0000000505500210000000000454034f00000000055200190000000303300210000000000605043300000000063601cf000000000636022f000000000404043b0000010003300089000000000434022f00000000033401cf000000000363019f0000000000350435000000000212001900000000000204350000002001100029000000000101043300001309011001970000002502000029000000000202043300001309022001980000168c0000c13d000013090210019700000025030000290000000000230435000000170200002900000000020204330000130902200198000016930000c13d000013090110019700000017020000290000000000120435000000400200043d0000008001200039000000400010043f00000020032000390000002201000029002000000003001d000000000013043500000000001204350000006001200039001800000001001d0000000000010435002600000002001d000000400120003900000000000104350000001b0200002900000000020204330000131703200197000013390430009c000017080000c13d0000001e020000290000000002020433000000003202043400001308040000410000001f0520008c000000000500001900000000050420190000130806200197000000000706004b0000000004008019000013080660009c000000000405c019000000000404004b0000006d0000613d0000000004030433000013160540009c0000006d0000813d00000000022300190000000004340019000000000342004900001308050000410000003f0630008c000000000600001900000000060520190000130803300197000000000703004b0000000005008019000013080330009c000000000506c019000000000305004b0000006d0000613d000000400300043d000013190530009c00001b020000813d0000004005300039000000400050043f0000000067040434000013160870009c0000006d0000813d00000000074700190000001f087000390000130809000041000000000a28004b000000000a000019000000000a0940190000130808800197000013080b200197000116d70000003d00004b600000013d000013080880009c00000000090ac019000000000809004b0000006d0000613d0000000087070434000013160970009c00001b020000813d000000050a7002100000006009300039000000000aa90019000013160ba0009c00001b020000813d0000004000a0043f0000000000750435000000060a700210000000000aa80019000000000aa2004b0000006d0000413d000013080a000041000000000b000019000000000c7b004b000019890000813d000000000c8200490000003f0dc0008c000000000d000019000000000d0a2019000013080cc00197000000000e0c004b000000000e000019000000000e0a4019000013080cc0009c000000000e0dc019000000000c0e004b0000006d0000613d000000400c00043d000013190dc0009c00001b020000813d000000400dc000390000004000d0043f00000000de0804340000130a0fe0009c0000006d0000813d000000000eec0436000000000d0d04330000136b0fd0009c0000006d0000813d000117070000003d00004b5b0000013d000016eb0000013d000013680430009c0000176b0000c13d0000001e02000029000000000202043300000000230204340000130804000041000117100000003d000049aa0000013d0000130806300197000000000706004b0000000004008019000013080660009c000000000405c019000000000404004b0000006d0000613d0000000004020433000013160540009c0000006d0000813d00000000033200190000000002240019000000000423004900001308050000410000005f0640008c000000000600001900000000060520190000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d000000400400043d0000136a0540009c00001b020000813d0000006005400039000000400050043f0000000067020434000013160870009c0000006d0000813d00000000072700190000001f087000390000130809000041000000000a38004b000000000a000019000000000a0940190000130808800197000013080b3001970001173a0000003d00004b600000013d000013080880009c00000000090ac019000000000809004b0000006d0000613d0000000087070434000013160970009c00001b020000813d000000050a7002100000008009400039000000000aa90019000013160ba0009c00001b020000813d0000004000a0043f0000000000750435000000060a700210000000000aa80019000000000aa3004b0000006d0000413d000013080a000041000000000b000019000000000c7b004b000019cb0000813d000000000c8300490000003f0dc0008c000000000d000019000000000d0a2019000013080cc00197000000000e0c004b000000000e000019000000000e0a4019000013080cc0009c000000000e0dc019000000000c0e004b0000006d0000613d000000400c00043d000013190dc0009c00001b020000813d000000400dc000390000004000d0043f00000000de0804340000130a0fe0009c0000006d0000813d000000000eec0436000000000d0d04330000136b0fd0009c0000006d0000813d0001176a0000003d00004b5b0000013d0000174e0000013d000013690330009c000017ce0000c13d0000001e02000029000000000202043300000000230204340000130804000041000117730000003d000049aa0000013d0000130806300197000000000706004b0000000004008019000013080660009c000000000405c019000000000404004b0000006d0000613d0000000004020433000013160540009c0000006d0000813d00000000033200190000000002240019000000000423004900001308050000410000005f0640008c000000000600001900000000060520190000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d000000400400043d0000136a0540009c00001b020000813d0000006005400039000000400050043f0000000067020434000013160870009c0000006d0000813d00000000072700190000001f087000390000130809000041000000000a38004b000000000a000019000000000a0940190000130808800197000013080b3001970001179d0000003d00004b600000013d000013080880009c00000000090ac019000000000809004b0000006d0000613d0000000087070434000013160970009c00001b020000813d000000050a7002100000008009400039000000000aa90019000013160ba0009c00001b020000813d0000004000a0043f0000000000750435000000060a700210000000000aa80019000000000aa3004b0000006d0000413d000013080a000041000000000b000019000000000c7b004b00001a550000813d000000000c8300490000003f0dc0008c000000000d000019000000000d0a2019000013080cc00197000000000e0c004b000000000e000019000000000e0a4019000013080cc0009c000000000e0dc019000000000c0e004b0000006d0000613d000000400c00043d000013190dc0009c00001b020000813d000000400dc000390000004000d0043f00000000de0804340000130a0fe0009c0000006d0000813d000000000eec0436000000000d0d04330000136b0fd0009c0000006d0000813d000117cd0000003d00004b5b0000013d000017b10000013d000013170220009c00001ae90000813d000000400200043d00000044012000390000136c03000041000017d70000013d000000400200043d00000044012000390000136703000041000000000031043500000024012000390000001703000039000025810000013d000117dd0000003d000049a40000013d000017f50000813d0000132c02000041000117e10000003d00004bd50000013d000117e30000003d000045530000013d0000000001000414000117e60000003d00004b570000013d4bfc00340000040f000000000101004b000001560000613d000000400200043d000000200120008a000000000101043300001309011001980000195f0000613d000000240110006c000019800000c13d000000250100002900000000010104330000130901100198000011910000c13d0000197a0000013d000019650000013d000000400100043d0000136502000041000000000021043500000004021000390000001b050000290000000000520435000000200300002900000000030304330000131703300197000000440410003900000000003404350000001d03000029000118040000003d000046360000013d000000000847004b000018090000813d000118080000003d000048ec0000013d000018040000013d000000000647004b0000180d0000a13d000000000554001900000000000504350000001f044000390020002000000092000000200440017f000118120000003d00004ad30000013d000013170110019700000000001404350000001e01000029000000000101043300000040023000390000001b040000290001181a0000003d000047460000013d000000000352004b0000181f0000813d0001181e0000003d000048da0000013d0000181a0000013d002100000006001d002400000005001d000000000152004b000018260000a13d000000210200002900000024012000290000000000010435000000400100043d002600000001001d0040001a0000002d0001182b0000003d0000441d0000013d000000400440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001a02000029000000040220008c000018410000613d00000024020000290000001f02200039000000200220017f0000002102200029000000260300002900000000043200490000001a020000290001183e0000003d000049890000013d000001560000613d000000400100043d002600000001001d000118430000003d000048260000013d0000184a0000613d000000000500001900000005065002100000002607600029000118490000003d000045be0000013d000018450000413d000000000503004b000018510000613d0000000504400210000000000242034f0000002604400029000118510000003d0000446e0000013d0000130802000041000118540000003d00004ac30000013d0000130804100197000000000504004b0000000002008019000013080440009c000000000203c0190000001f03100039000000200330017f0000002603300029002400000003001d000000400030043f000000000202004b0000006d0000613d00000026020000290000000002020433000013160320009c0000006d0000813d00000026011000290000002602200029000000000321004900001308040000410001186a0000003d00004abf0000013d0000130803300197000000000603004b0000000004008019000013080330009c000000000405c019000000000304004b0000006d0000613d0000002403000029000013190330009c00001b020000813d00000024030000290000004003300039000000400030043f00000000340204340000131705400197000000000554004b0000006d0000c13d000000240500002900000000004504350000000003030433000013160430009c0000006d0000813d00000000022300190000001f032000390000130804000041000118850000003d00004abb0000013d00001308033001970000130806100197000118890000003d00004ab70000013d000013080330009c000000000405c019000000000304004b0000006d0000613d0000000043020434000013160230009c00001b020000813d0000003f02300039000000200520017f000000400200043d0000000005520019000000000625004b00001b020000413d000013160650009c00001b020000813d0001189a0000003d00004a1e0000013d0000006d0000213d0000000001000019000000000631004b00001ada0000813d000118a00000003d000048d40000013d0000189c0000013d000000400100043d000013650200004100000000002104350000000402100039000000180500002900000000005204350000001e0300002900000000030304330000131703300197000000440410003900000000003404350000001a03000029000118af0000003d000046360000013d000000000847004b000018b40000813d000118b30000003d000048ec0000013d000018af0000013d000000000647004b000018b80000a13d000000000554001900000000000504350000001f04400039001e0020000000920000001e0440017f000118bd0000003d00004ad30000013d000013170110019700000000001404350000001b01000029000000000101043300000040023000390000001804000029000118c50000003d000047460000013d000000000352004b000018ca0000813d000118c90000003d000048da0000013d000018c50000013d002000000006001d002100000005001d000000000152004b000018d10000a13d000000200200002900000021012000290000000000010435000000400100043d002600000001001d004200150000002d000118d60000003d0000441d0000013d000000420440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001502000029000000040220008c000018ec0000613d00000021020000290000001f022000390000001e0220017f0000002002200029000000260300002900000000043200490000001502000029000118e90000003d000049890000013d000001560000613d000000400100043d002600000001001d000118ee0000003d000048260000013d000018f50000613d000000000500001900000005065002100000002607600029000118f40000003d000045be0000013d000018f00000413d000000000503004b000018fc0000613d0000000504400210000000000242034f0000002604400029000118fc0000003d0000446e0000013d0000130802000041000118ff0000003d00004ac30000013d0000130804100197000000000504004b0000000002008019000013080440009c000000000203c0190000001f031000390000001e0330017f0000002603300029002100000003001d000000400030043f000000000202004b0000006d0000613d00000026020000290000000002020433000013160320009c0000006d0000813d0000002601100029000000260220002900000000032100490000130804000041000119150000003d00004abf0000013d0000130803300197000000000603004b0000000004008019000013080330009c000000000405c019000000000304004b0000006d0000613d0000002103000029000013190330009c00001b020000813d00000021030000290000004003300039000000400030043f00000000340204340000131705400197000000000554004b0000006d0000c13d000000210500002900000000004504350000000003030433000013160430009c0000006d0000813d00000000022300190000001f032000390000130804000041000119300000003d00004abb0000013d00001308033001970000130806100197000119340000003d00004ab70000013d000013080330009c000000000405c019000000000304004b0000006d0000613d0000000043020434000013160230009c00001b020000813d0000003f023000390000001e0520017f000000400200043d0000000005520019000000000625004b00001b020000413d000013160650009c00001b020000813d000119450000003d00004a1e0000013d0000006d0000213d0000000001000019000000000631004b00001ade0000813d0001194b0000003d000048d40000013d000019470000013d0001194e0000003d000049a40000013d000019650000813d0000132c02000041000119520000003d00004bd50000013d000119540000003d000045530000013d0000000001000414000119570000003d00004b570000013d4bfc00340000040f000000000101004b000001560000613d000000400200043d000000200120008a00000000010104330000130901100198000019740000c13d00000044012000390000133103000041000000000031043500000024012000390000001803000039000025810000013d000013100100004100000022060000290000000000160435000013290100004100000000001304350000132d0100004100000000001504350000002201000039000000000014043500000020010000390000000000120435000000400100043d000000000219004900000506022000394bfc43c30000040f000000240110006c000019800000c13d000000170100002900000000010104330000130901100198000011910000c13d00000044012000390000133003000041000000000031043500000024012000390000000803000039000025810000013d00000064012000390000132e03000041000000000031043500000044012000390000132f0300004100000000003104350000002401200039000000220300003900000ac90000013d00000000055304360000000006060433000013160760009c0000006d0000813d00000000044600190000001f064000390000130807000041000000000826004b0000000008000019000000000807401900001308066001970000130809200197000119970000003d000049970000013d000013080660009c000000000708c019000000000607004b0000006d0000613d0000000064040434000013160740009c00001b020000813d0000000508400210000000400700043d00000000087800190000002008800039000000000978004b00001b020000413d000013160980009c00001b020000813d000000400080043f000000000047043500000006084002100000000008860019000000000882004b0000006d0000413d00001308080000410000000009070019000000000a000019000000000b4a004b00001ae20000813d000000000b6200490000003f0cb0008c000000000c000019000000000c082019000013080bb00197000000000d0b004b000000000d000019000000000d084019000013080bb0009c000000000d0cc019000000000b0d004b0000006d0000613d000000400b00043d000013190cb0009c00001b020000813d000119c20000003d00004b2e0000013d0000130a0ec0009c0000006d0000813d000000000ccb0436000000000d0d04330000136b0ed0009c0000006d0000813d000119ca0000003d0000474d0000013d000019af0000013d00000000055404360000000006060433000013160760009c0000006d0000813d00000000062600190000001f076000390000130808000041000000000937004b000000000900001900000000090840190000130807700197000013080a300197000000000ba7004b000000000800a0190000000007a7013f000013080770009c000000000809c019000000000708004b0000006d0000613d0000000076060434000013160860009c00001b020000813d0000000509600210000119e40000003d00004baa0000013d00001b020000413d000013160a90009c00001b020000813d000000400090043f000000000068043500000006096002100000000009970019000000000993004b0000006d0000413d0000130809000041000000000a080019000000000b000019000000000c6b004b00001ed60000813d000119f40000003d00004b170000013d000013080cc00197000000000e0c004b000000000e000019000000000e094019000013080cc0009c000000000e0dc019000000000c0e004b0000006d0000613d000000400c00043d000013190dc0009c00001b020000813d000000400dc000390000004000d0043f00000000ed0704340000130a0fd0009c0000006d0000813d000000000ddc0436000000000e0e04330000136b0fe0009c0000006d0000813d00011a0a0000003d00004a040000013d000019f00000013d000000a00100043d00000000010104330000000012010434002600000002001d00000000010104330000000012010434000000800300043d002500000003001d000001600300043d002400000003001d4bfc43d70000040f0000002602000029000013170220019700011a1a0000003d000049110000013d0000131d03000041000000200240003900011a1e0000003d0000465a0000013d000000e00200043d00000000020204330000000023020434002200000003001d0000000002020433002300000001001d00000000120204344bfc43d70000040f000000220200002900001317022001970000002604000029000000c0034000390000000000230435000000a0024000390000131d0300004100011a2f0000003d000046650000013d00000024090000290000131702900197000000250300002900001309053001970000002606000029000001a00a600039000001800360003900000160046000390000014007600039000000000b0600190000012008600039000001000600043d000013380990009c00001a950000213d000013390220009c00001a950000613d000001800200043d00000000005804350000002305000029000000000057043500000000001404350000000000630435000000a00100003900000000001a0435000001c001b0003900000000030204330000000000310435000001e001b0003900000000030204330000000004000019000000000534004b00001a9e0000813d0000000005140019000000200440003900000000062400190000000006060433000000000065043500001a4d0000013d00000000055404360000000006060433000013160760009c0000006d0000813d00000000062600190000001f076000390000130808000041000000000937004b000000000900001900000000090840190000130807700197000013080a300197000000000ba7004b000000000800a0190000000007a7013f000013080770009c000000000809c019000000000708004b0000006d0000613d0000000076060434000013160860009c00001b020000813d000000050960021000011a6e0000003d00004baa0000013d00001b020000413d000013160a90009c00001b020000813d000000400090043f000000000068043500000006096002100000000009970019000000000993004b0000006d0000413d0000130809000041000000000a080019000000000b000019000000000c6b004b00001edc0000813d00011a7e0000003d00004b170000013d000013080cc00197000000000e0c004b000000000e000019000000000e094019000013080cc0009c000000000e0dc019000000000c0e004b0000006d0000613d000000400c00043d000013190dc0009c00001b020000813d000000400dc000390000004000d0043f00000000ed0704340000130a0fd0009c0000006d0000813d000000000ddc0436000000000e0e04330000136b0fe0009c0000006d0000813d00011a940000003d00004a040000013d00001a7a0000013d00000000005804350000002302000029000000000027043500000000001404350000000000630435000000400100043d0000000002130049000000000021043500001aac0000013d000000000a1300190000001f0130019000001aa80000613d00000000021a00490000000301100210000001000110008900000000a3020434000000000313022f00000000011301cf0000000000120435000000400100043d00000000021a0049000000200220008a000000000021043500260000000a001d0000004000a0043f000000000201043300000020011000394bfc43d70000040f002500000001001d00000000001004350000012f01000039000000200010043f000000400200003900000000010000194bfc43d70000040f000000010200008a000000000021041b0000002602000029000000250100002900011abe0000003d00004a9b0000013d0000130003000041000013000410009c000000000103801900000040011002100000002002200039000013000420009c00011ac60000003d000049450000013d0000000002000414000013000420009c00011aca0000003d000048ac0000013d0000130b011001c70000800d0200003900000001030000390000133a040000414bfc44050000040f0000000101200190000002a90000c13d0000006d0000013d000000000131004b000012dd0000a13d0000000001350019000012dc0000013d000000000131004b000014470000a13d0000000001350019000014460000013d000000000131004b000013ea0000a13d0000000001350019000013e90000013d000000000131004b0000154d0000a13d00000000013500190000154c0000013d0000000000750435000000000203043300000026030000290000000000230435000000000205043300000020030000290000000000230435000000260200002900000000020204330000000002020433000000000202004b00001b0b0000c13d00000025020000290000000004020433000000400200043d000000010300003900000000033204360000008005200039000000400050043f000000600520003900000000000504350000004005200039000000000053043500000000000504350000000006020433000000000606004b00001b020000613d000013090440019700000000004504350000000004020433000000000404004b00001b050000c13d000000010100008a00000000000104350000000000000431000000000303043300000020033000390000271004000039000000000043043500000026030000290000000000230435000000400300043d0000008002300039000000400020043f00000020043000390000002202000029001b00000004001d000000000024043500000000002304350000006002300039001000000002001d0000000000020435001e00000003001d00000040023000390000000000020435000000150300002900000000030304330000131704300197000013390540009c00001b820000c13d0000001a030000290000000003030433000000004303043400001308050000410000001f0630008c000000000600001900000000060520190000130807300197000000000807004b0000000005008019000013080770009c000000000506c019000000000505004b0000006d0000613d0000000005040433000013160650009c0000006d0000813d00000000033400190000000005450019000000000453004900001308060000410000003f0740008c000000000700001900000000070620190000130804400197000000000804004b0000000006008019000013080440009c000000000607c019000000000406004b0000006d0000613d000000400400043d000013190640009c00001b020000813d0000004006400039000000400060043f0000000078050434001a00000007001d000013160780009c0000006d0000813d00000000085800190000001f078000390000130809000041000000000a37004b000000000a000019000000000a0940190000130807700197000013080b300197000000000cb7004b000000000900a0190000000007b7013f000013080770009c00000000090ac019000000000709004b0000006d0000613d0000000098080434000013160a80009c00001b020000813d0000000507800210000000600a400039000000000b7a00190000131607b0009c00001b020000813d0000004000b0043f000000000086043500000006078002100000000007790019000000000773004b0000006d0000413d000013080b000041000000000c000019000000000d8c004b00001db50000813d00000000079300490000003f0d70008c000000000d000019000000000d0b20190000130807700197000000000e07004b000000000e000019000000000e0b4019000013080770009c000000000e0dc01900000000070e004b0000006d0000613d000000400d00043d000013190ed0009c00001b020000813d000000400ed000390000004000e0043f00000000ef0904340000130a07f0009c0000006d0000813d000000000ffd0436000000000e0e04330000136b07e0009c0000006d0000813d00011b810000003d00004bb40000013d00001b650000013d000013680540009c00001be80000c13d0000001a030000290000000003030433000000003403043400001308050000410000001f0640008c000000000600001900000000060520190000130807400197000000000807004b0000000005008019000013080770009c000000000506c019000000000505004b0000006d0000613d0000000005030433000013160650009c0000006d0000813d00000000044300190000000003350019000000000534004900001308060000410000005f0750008c000000000700001900000000070620190000130805500197000000000805004b0000000006008019000013080550009c000000000607c019000000000506004b0000006d0000613d000000400500043d0000136a0650009c00001b020000813d0000006006500039000000400060043f0000000078030434001a00000007001d000013160780009c0000006d0000813d00000000083800190000001f078000390000130809000041000000000a47004b000000000a000019000000000a0940190000130807700197000013080b400197000000000cb7004b000000000900a0190000000007b7013f000013080770009c00000000090ac019000000000709004b0000006d0000613d0000000098080434000013160a80009c00001b020000813d0000000507800210000000800a500039000000000b7a00190000131607b0009c00001b020000813d0000004000b0043f000000000086043500000006078002100000000007790019000000000774004b0000006d0000413d000013080b000041000000000c000019000000000d8c004b00001df60000813d00000000079400490000003f0d70008c000000000d000019000000000d0b20190000130807700197000000000e07004b000000000e000019000000000e0b4019000013080770009c000000000e0dc01900000000070e004b0000006d0000613d000000400d00043d000013190ed0009c00001b020000813d000000400ed000390000004000e0043f00000000ef0904340000130a07f0009c0000006d0000813d000000000ffd0436000000000e0e04330000136b07e0009c0000006d0000813d00011be70000003d00004bb40000013d00001bcb0000013d000013690440009c00001c4e0000c13d0000001a030000290000000003030433000000003403043400001308050000410000001f0640008c000000000600001900000000060520190000130807400197000000000807004b0000000005008019000013080770009c000000000506c019000000000505004b0000006d0000613d0000000005030433000013160650009c0000006d0000813d00000000044300190000000003350019000000000534004900001308060000410000005f0750008c000000000700001900000000070620190000130805500197000000000805004b0000000006008019000013080550009c000000000607c019000000000506004b0000006d0000613d000000400500043d0000136a0650009c00001b020000813d0000006006500039000000400060043f0000000078030434001a00000007001d000013160780009c0000006d0000813d00000000083800190000001f078000390000130809000041000000000a47004b000000000a000019000000000a0940190000130807700197000013080b400197000000000cb7004b000000000900a0190000000007b7013f000013080770009c00000000090ac019000000000709004b0000006d0000613d0000000098080434000013160a80009c00001b020000813d0000000507800210000000800a500039000000000b7a00190000131607b0009c00001b020000813d0000004000b0043f000000000086043500000006078002100000000007790019000000000774004b0000006d0000413d000013080b000041000000000c000019000000000d8c004b00001e820000813d00000000079400490000003f0d70008c000000000d000019000000000d0b20190000130807700197000000000e07004b000000000e000019000000000e0b4019000013080770009c000000000e0dc01900000000070e004b0000006d0000613d000000400d00043d000013190ed0009c00001b020000813d000000400ed000390000004000e0043f00000000ef0904340000130a07f0009c0000006d0000813d000000000ffd0436000000000e0e04330000136b07e0009c0000006d0000813d00011c4d0000003d00004bb40000013d00001c310000013d000013380330009c000017d00000a13d0000001e0300002900000000030304330000000003030433000000000303004b00001c6f0000c13d00000017030000290000000005030433000000400300043d000000010400003900000000044304360000008006300039000000400060043f000000600630003900000000000604350000004006300039000000000064043500000000000604350000000007030433000000000707004b00001b020000613d000013090550019700000000005604350000000005030433000000000505004b00001b020000613d00000000040404330000002004400039000027100500003900000000005404350000001e0400002900000000003404350000000002020433000c00000002001d0000000001010433001500000001001d00011c750000003d000047380000013d00000014010000290000000001010433000000000101004b001a00000000001d00001c810000613d000000120100002900000000001004350000012f01000039000000200010043f00011c800000003d000049eb0000013d001a00000001001d00000013010000290000000001010433000000000101004b000f00000000001d00001c8d0000613d000000190100002900000000001004350000012f01000039000000200010043f00011c8c0000003d000049eb0000013d000f00000001001d00011c8f0000003d000047380000013d000000150100006b00001cc60000c13d0000001d01000029000000000101043300000020011000390000000002010433000e00000002001d0000001a0120006c00001ccd0000413d0000000e0100006b00001cd60000613d0000000e020000290000001a0220006a0000001f01000029000000000101043300000020011000390000000001010433000d00000001001d000000000101004b00000000010000190000000101006039000900000001001d000a00000002001d000000000102004b00001cbb0000613d0000000d0100006b00001cbb0000613d0000000a010000290000000d020000290000000e030000294bfc43610000040f0000000d040000290000000a324000b900000000434200d90000000a0330006c000041ad0000c13d000000000301004b000000000300001900001cb90000613d00011cb80000003d00004a370000013d000041ad0000c13d000000000123004b00001e5e0000813d0000000d0100006b000000000100001900001cc30000613d0000000d030000290000000a213000b900000000323100d90000000a0220006c000041ad0000c13d000b000e10100102000800000000001d00001d080000013d0000001f01000029000000000101043300000020011000390000000002010433000d00000002001d0000001a0120006c00001cd40000813d000000400200043d00000044012000390000138c03000041000000000031043500000024012000390000001e03000039000025810000013d0000000d0100006b00001cdd0000c13d000000400200043d00000044012000390000138b03000041000000000031043500000024012000390000001003000039000025810000013d0000000d020000290000001a0220006a0000001d01000029000000000101043300000020011000390000000001010433000e00000001001d000000000101004b00000000010000190000000101006039000800000001001d000b00000002001d000000000102004b00001cfe0000613d0000000e0100006b00001cfe0000613d0000000b010000290000000e020000290000000d030000294bfc43610000040f0000000e040000290000000b324000b900000000434200d90000000b0330006c000041ad0000c13d000000000301004b000000000300001900001cfc0000613d00011cfb0000003d00004a370000013d000041ad0000c13d000000000123004b00001e5e0000813d0000000e0100006b000000000100001900001d060000613d0000000b040000290000000e214000b90000000e321000fa000000000242004b000041ad0000c13d000a000d10100102000900000000001d0000000c0100006b00001d3f0000c13d0000001601000029000000000101043300000020011000390000000002010433000700000002001d0000000f0120006c00001ccd0000413d000000070100006b00001cd60000613d00000007020000290000000f0220006a0000001c01000029000000000101043300000020011000390000000001010433000600000001001d000000000101004b00000000010000190000000101006039000300000001001d000500000002001d000000000102004b00001d340000613d000000060100006b00001d340000613d0000000501000029000000060200002900000007030000294bfc43610000040f000000060400002900000005324000b900000000434200d9000000050330006c000041ad0000c13d000000000301004b000000000300001900001d320000613d00011d310000003d00004a370000013d000041ad0000c13d000000000123004b00001e5e0000813d000000060100006b000000000100001900001d3c0000613d000000050400002900000006214000b900000006321000fa000000000242004b000041ad0000c13d0004000710100102000200000000001d00001d730000013d0000001c01000029000000000101043300000020011000390000000002010433000600000002001d0000000f0120006c00001ccd0000413d000000060100006b00001cd60000613d00000006020000290000000f0220006a0000001601000029000000000101043300000020011000390000000001010433000700000001001d000000000101004b00000000010000190000000101006039000200000001001d000400000002001d000000000102004b00001d690000613d000000070100006b00001d690000613d0000000401000029000000070200002900000006030000294bfc43610000040f000000070400002900000004324000b900000000434200d9000000040330006c000041ad0000c13d000000000301004b000000000300001900001d670000613d00011d660000003d00004a370000013d000041ad0000c13d000000000123004b00001e5e0000813d000000070100006b000000000100001900001d710000613d000000040400002900000007214000b900000007321000fa000000000242004b000041ad0000c13d0005000610100102000300000000001d00011d750000003d000047380000013d00000005020000290000000b0120006c00001d980000213d00000005020000290000000b012001b000001d980000613d0000000901000029000000010110019000001cd60000c13d000000050100006b000000080100002900000001011061bf000000010110019000001e370000613d000000050100006b000000000100001900001d8b0000613d00000005030000290000000e213000b900000000323100d90000000e0220006c000041ad0000c13d0000000d121000fa000000400100043d000e00000001001d000a00000002001d000000040120006c00001e650000a13d0000000e0300002900000044013000390000136d0200004100000000002104350000002401300039000000190200003900000eb10000013d0000000301000029000000010110019000001cd60000c13d0000000a0100006b000000020100002900000001011061bf000000010110019000001e4b0000613d0000000a0100006b000000000100001900001da80000613d00000007040000290000000a214000b90000000a321000fa000000000242004b000041ad0000c13d00000006211000fa000000400200043d000e00000002001d0000000b0110006c0005000b0000002d00001e650000a13d0000000e0300002900000044013000390000138a0200004100000000002104350000002401300039000000180200003900000eb10000013d00000000066404360000001a070000290000000007070433000013160870009c0000006d0000813d00000000055700190000001f075000390000130808000041000000000937004b000000000900001900000000090840190000130807700197000013080a300197000000000ba7004b000000000800a0190000000007a7013f000013080770009c000000000809c019000000000708004b0000006d0000613d0000000075050434000013160850009c00001b020000813d000000050950021000011dcf0000003d00004baa0000013d00001b020000413d000013160a90009c00001b020000813d000000400090043f000000000058043500000006095002100000000009970019000000000993004b0000006d0000413d0000130809000041000000000a080019000000000b000019000000000c5b004b000020130000813d00011ddf0000003d00004b170000013d000013080cc00197000000000e0c004b000000000e000019000000000e094019000013080cc0009c000000000e0dc019000000000c0e004b0000006d0000613d000000400c00043d000013190dc0009c00001b020000813d000000400dc000390000004000d0043f00000000ed0704340000130a0fd0009c0000006d0000813d000000000ddc0436000000000e0e04330000136b0fe0009c0000006d0000813d00011df50000003d00004a040000013d00001ddb0000013d00000000066504360000001a070000290000000007070433000013160870009c0000006d0000813d00000000073700190000001f087000390000130809000041000000000a48004b000000000a000019000000000a0940190000130808800197000013080b40019700011e050000003d00004b600000013d000013080880009c00000000090ac019000000000809004b0000006d0000613d0000000087070434000013160970009c00001b020000813d00011e0e0000003d00004b9c0000013d00001b020000413d0000131609a0009c00001b020000813d00011e130000003d00004aef0000013d0000006d0000413d000013080a0000410000001a0b000029000000000c000019000000000d7c004b000022690000813d00000000098400490000003f0d90008c000000000d000019000000000d0a20190000130809900197000000000e09004b000000000e000019000000000e0a4019000013080990009c000000000e0dc01900000000090e004b0000006d0000613d000000400d00043d000013190ed0009c00001b020000813d000000400ed000390000004000e0043f00000000fe0804340000130a09e0009c0000006d0000813d000000000eed0436000000000f0f04330000136b09f0009c0000006d0000813d000000200bb000390000000000fe04350000000000db0435000000010cc00039000000400880003900001e170000013d0000000e01000029000e00000001001d0000000502000029000500000002001d0000000d030000294bfc43610000040f00000005040000290000000e324000b900000000434200d90000000e0330006c000041ad0000c13d000000000301004b000000000300001900001e480000613d00011e470000003d00004a370000013d000041ad0000c13d000000000123004b00001d830000413d00001e5e0000013d0000000701000029000700000001001d0000000a02000029000a00000002001d00000006030000294bfc43610000040f0000000a0400002900000007324000b900000000434200d9000000070330006c000041ad0000c13d000000000301004b000000000300001900001e5c0000613d00011e5b0000003d00004a370000013d000041ad0000c13d000000000123004b00001da00000413d000000400200043d00000044012000390000136e03000041000000000031043500000024012000390000000e03000039000025810000013d0000000e020000290000004001200039000000400010043f000000050100002900000000021204360000000a01000029000d00000002001d00000000001204350000001f0100002900011e700000003d00004a2c0000013d00001e750000c13d000000160100002900011e740000003d00004a2c0000013d00001e790000613d0000000e010000290000000001010433000000000101004b00001ec50000613d0000001d0100002900011e7c0000003d00004a2c0000013d00001ec30000c13d0000001c0100002900011e800000003d00004a2c0000013d00001ec30000c13d00001ecc0000013d00000000066504360000001a070000290000000007070433000013160870009c0000006d0000813d00000000073700190000001f087000390000130809000041000000000a48004b000000000a000019000000000a0940190000130808800197000013080b40019700011e910000003d00004b600000013d000013080880009c00000000090ac019000000000809004b0000006d0000613d0000000087070434000013160970009c00001b020000813d00011e9a0000003d00004b9c0000013d00001b020000413d0000131609a0009c00001b020000813d00011e9f0000003d00004aef0000013d0000006d0000413d000013080a0000410000001a0b000029000000000c000019000000000d7c004b0000226f0000813d00000000098400490000003f0d90008c000000000d000019000000000d0a20190000130809900197000000000e09004b000000000e000019000000000e0a4019000013080990009c000000000e0dc01900000000090e004b0000006d0000613d000000400d00043d000013190ed0009c00001b020000813d000000400ed000390000004000e0043f00000000fe0804340000130a09e0009c0000006d0000813d000000000eed0436000000000f0f04330000136b09f0009c0000006d0000813d000000200bb000390000000000fe04350000000000db0435000000010cc00039000000400880003900001ea30000013d0000000a0100006b00001ecc0000c13d000000400200043d00000044012000390000138903000041000000000031043500000024012000390000000f03000039000025810000013d00000014010000290000000001010433000000000101004b00001eec0000613d000000150100006b00001ee50000c13d0000000a02000029001f001a0020002e000041bf0000413d00001ee90000013d00011ed80000003d00004a9f0000013d0000006d0000c13d00011edb0000003d000047990000013d00001ae90000013d00011ede0000003d00004a9f0000013d0000006d0000c13d00011ee10000003d000047990000013d00000001020000390000001803000029000000000023043500001ae90000013d0000000e010000290000000001010433001f001a0010002e000041bf0000413d000000120100002900011eec0000003d000049f00000013d00000013010000290000000001010433000000000101004b00001efe0000613d0000000c0100006b00001ef70000c13d0000000e010000290000000001010433001f000f0010002e000041bf0000413d00001efb0000013d0000000d010000290000000001010433001f000f0010002e000041bf0000413d000000190100002900011efe0000003d000049f00000013d0000000d0100002900000000010104330000000e020000290000000002020433000000400300043d000000600430003900000000002404350000004002300039000000000012043500000020013000390000001902000029000000000021043500000012010000290000000000130435000000400100043d00000000021300490000130003000041000013000410009c000000000103801900000040011002100000008002200039000013000420009c00011f160000003d000049450000013d0000000002000414000013000420009c00011f1a0000003d000048ac0000013d0000130b011001c70000800d020000390000000103000039001f00000003001d0000136f040000414bfc44050000040f00000001012001900000006d0000613d000000400500043d001300000005001d0000010001500039000000400010043f000000c001500039000000240200002900000000002104350000000004020019002400000004001d0000000e020000290000000002020433000000e0035000390000000000230435000000000215043600000026010000290000000001010433000b00000002001d0000000000120435000000200100002900000000010104330000004002500039000a00000002001d00000000001204350000000001040433000013170110019700000000001004350000009701000039002600000001001d000000200010043f0000004002000039001500000002001d00000000010000194bfc43d70000040f000000000101041a000013090110019700000013030000290000006002300039000f00000002001d00000000001204350000002501000029000000000101043300001309011001970000008002300039001200000002001d000000000012043500000018010000290000000001010433000000000101004b0000000001000019000000010100c039000000a002300039002500000002001d0000000000120435000000400500043d001400000005001d0000010001500039000000400010043f000000c001500039000000210400002900000000004104350000000d020000290000000002020433000000e003500039000000000023043500000000021504360000001e010000290000000001010433000c00000002001d00000000001204350000001b0100002900000000010104330000004002500039000900000002001d00000000001204350000000001040433000013170110019700000000001004350000002601000029000000200010043f000000000100001900000015020000294bfc43d70000040f000000000101041a000013090110019700000014030000290000006002300039000e00000002001d00000000001204350000001701000029000000000101043300001309011001970000008002300039000d00000002001d000000000012043500000010010000290000000001010433000000000101004b0000000002000019000000010200c039000000a00130003900000000002104350000002402000029000000000202043300001317022001970000134b0320009c0000001f0300002900001fa50000613d00000002050000390000002103000029000000000303043300001317043001970000134b0340009c001f00000000001d000000000305001900001fa50000613d001f00010000003d0000134a0320009c0000001f0300002900001fa50000613d0000134a0340009c001f00000000001d000000000305001900001fa50000613d00000001030000390000135f0220009c001f00000003001d00001fa50000613d0000135f0240009c00000000030000190000000203006039001f00000000001d0000001402000029000000000202043300000020022000390000000002020433001000000002001d0000001f0200006b00001fda0000613d000000400200043d0000006003200039000000400030043f0000016103000039000000000403041a0000004005200039000000d003400270000000000035043500001309054001970000000005520436000000a0044002700000131104400197000000000045043500000025040000290000000004040433000000000404004b000000000400001900001fbf0000613d00000000040504330000000001010433000000000101004b000000000300601900001311044001970000000a01000029000000000101043300000020071000390000000008010433000000130100002900000000010104330000002005100039000000000505043300000000060400190000000009000019000000000a89004b0000201b0000813d000000050a900210000000000aa70019000000000a0a0433000000200aa00039000000000a0a0433000013700aa00197000027110ba0008c0000200f0000813d00000000066a0019000000010990003900001fcd0000013d0000001302000029000000000202043300000020042000390000000004040433002000000004001d000000020330008c000020670000c13d000000400200043d0000006003200039000000400030043f0000016103000039000000000503041a0000004004200039000000d003500270000000000034043500001309045001970000000004420436000000a005500270000013110550019700000000005404350000000001010433000000000101004b000000000100001900001ff30000613d000000000104043300000025040000290000000004040433000000000404004b000000000300601900001311041001970000000901000029000000000101043300000020071000390000000008010433000000140100002900000000010104330000002005100039000000000505043300000000060400190000000009000019000000000a89004b000022780000813d000000050a900210000000000aa70019000000000a0a0433000000200aa00039000000000a0a0433000013700aa00197000027110ba0008c0000200f0000813d00000000066a00190000000109900039000020020000013d000000400200043d00000044012000390000138803000041000042300000013d000000000086043500000000030404330000001e04000029000000000034043500000000030604330000001b04000029000000000034043500001c500000013d000000000705004b0000000007000019000020220000613d00000000875600a900000000985700d9000000000668004b000041ad0000c13d000027107670011a002000000056001e000041bf0000413d0000000f06000029000000000d0604330000000006010433000000000202043300000012010000290000000001010433000000000705004b0000000007000019000020330000613d000000000343001900000000475300a900000000545700d9000000000334004b000041ad0000c13d000027104370011a0000002007300069000000200470006c00000000040000190000000104002039000000000404004b000000000700c019002200000007001d000000200430006b0000002003004029000000000403004b000026d70000613d000120410000003d00004acb0000013d0000131707700197000013640870009c001e0000000d001d000022c40000c13d0000000004060433000000005604043400001308070000410000003f0860008c000000000800001900000000080720190000130806600197000000000906004b0000000007008019000013080660009c000000000708c019000000000607004b0000006d0000613d0000000005050433002613090050019b0000130a0550009c0000006d0000813d000000010330008c000042340000c13d0001205a0000003d00004b340000013d000013090220019700000004074000390000130901100197000000230810006b000023090000c13d0000137801000041000000000014043500000023010000290000130901100197000000000017043500000000002604350000000000350435000023dd0000013d0000000c010000290000000001010433001e00000001001d0000000031010434001b00000003001d000000000301004b0000405f0000613d0000000002020433001800000002001d0000002302000029001613090020019b00000012020000290000000002020433001a13090020019b0000000f020000290000000002020433001913090020019b002500000000001d001f00200000002d002600000000001d000000010210008a000000260320006b0000230d0000813d000000260110006b00001b020000813d000120820000003d000045370000013d0000137002200197000000200300006b00000000040000190000208a0000613d00000020342000b900000020534000fa000000000323004b000041ad0000c13d002500250020002e000041bf0000413d000027100240008c000021700000413d000027102340011a0000001f0230006b00001ccd0000413d000120930000003d000045e20000013d00001b020000813d001f001f00300071000120970000003d000049360000013d0000131707700197000013640870009c000020b70000c13d0001209c0000003d00004b510000013d0000130808000041000000000600001900000000060820190000130805500197000120a20000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000003030433001d13090030019b0000130a0330009c0000006d0000813d000027100340008a000027100330008c000042340000813d000120af0000003d000045300000013d0000130901100197000120b20000003d000046a50000013d000020f80000c13d0000137807000041000120b60000003d000044870000013d0000211c0000013d0000134a0470009c000020ff0000c13d000120bb0000003d00004b4d0000013d0000130807000041000000000500001900000000050720190000130804400197000120c10000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000002020433001d13090020019b0000130a0220009c0000006d0000813d000120cb0000003d000049ca0000013d00001309011001970000001a06000029000000230560006b0000212f0000c13d0000137505000041000120d20000003d0000490a0000013d0037001d0000002d000120d50000003d0000441d0000013d000000370440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001d02000029000000040220008c000020e50000613d0000001c03000029000120e20000003d000045ec0000013d000001560000613d000000400100043d001c00000001001d00000001010000310000001f0210008c0000130805000041000000000200001900000000020520190000130803100197000120ed0000003d000047250000013d000013080330009c000120f00000003d000044d40000013d0000006d0000613d0000001c01000029000120f40000003d0000445d0000013d0000006d0000c13d000000000101004b000021700000c13d0000233d0000013d000013770700004100000000007304350000001d07000029000120fd0000003d00004b420000013d001d00840030003d0000215a0000013d0000135f0470009c000021440000c13d000121030000003d00004b490000013d0000130808000041000000000600001900000000060820190000130805500197000121090000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000004040433001d13090040019b0000130a0440009c0000006d0000813d000000400500043d001c00c40050003d000121150000003d000045890000013d000013090a100197000121180000003d000045b90000013d000021500000c13d00001373020000410001211c0000003d000044c30000013d000000400100043d001700000001001d0091001d0000002d000121210000003d0000441d0000013d000000910440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001d02000029000000040220008c000021700000613d00000017030000290000001c043000690000001d020000290000216d0000013d00001374050000410000001c06000029000121330000003d000044b70000013d006900190000002d000121360000003d0000441d0000013d000000690440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000021700000613d0000001d030000290000001c0230006900000084042000390000216c0000013d0000134b0470009c000021730000c13d0000130904100197000000230140006b000021700000613d000000400200043d0000000001000414000000040540008c0000219f0000c13d00000001020000390000000101000031000021ac0000013d000013720200004100000000002504350000001d0200002900000000002b04350000001a02000029000121570000003d00004bf50000013d0000001c010000290000000000010435001d00e40050003d000000400100043d001c00000001001d007d00190000002d0001215f0000003d0000441d0000013d0000007d0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000021700000613d0000001d020000290000001c03000029000000000432004900000019020000290001216f0000003d0000452b0000013d000001560000613d000121720000003d000048520000013d0000207b0000013d000000400300043d0000137104000041000000000043043500000004043000390000002206000029000000000064043500000000040504330001217c0000003d000045210000013d00001317044001970001217f0000003d0000461e0000013d0000001d0650006c000021850000813d0000001c06500029000121840000003d000045260000013d0000217f0000013d0000001d0450006c0000218a0000a13d0000001d050000290000001c045000290000000000040435000000000202043300001309011001970001218e0000003d000044430000013d005300190000002d000121910000003d0000441d0000013d000000530440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000021700000613d0000001d020000290001219e0000003d000045a50000013d0000216b0000013d000013000510009c00001300060000410000000001068019000013000520009c0000000002068019000121a60000003d0000460e0000013d0000130b011001c70000800902000039000121aa0000003d000044570000013d000113000010019d0000130001100197000000000301004b000021b90000613d000121b00000003d000044290000013d000021b50000613d0000000006000019000121b40000003d000044210000013d000021b20000413d0000001f01100190000021b90000613d000121b90000003d0000440f0000013d000000000102004b000021700000c13d0000435d0000013d0000000002000411000000230320006b000021ce0000c13d0000001f03000029000121c20000003d0000481e0000013d000021c70000613d0000000004000019000121c60000003d000048160000013d000021c40000413d000000200400006b000021cb0000613d000121cb0000003d000044330000013d000121cd0000003d000046ed0000013d0000130902200197000000000112013f00001309011001980000253e0000613d000000a00100043d0000000021010434002200000002001d0000000012010434002600000002001d00000000010104330000000012010434000000800300043d002400000003001d4bfc43d70000040f00000026020000290000131702200197000121df0000003d000049110000013d0000131d03000041000121e20000003d0000448d0000013d0000131e03000041000121e50000003d000045d80000013d000000e00200043d0000000032020434002000000003001d0000000023020434001100000003001d0000000002020433002200000001001d0000000012020434000000c00300043d002100000003001d4bfc43d70000040f00000011020000290000131702200197000121f40000003d000049ae0000013d0000131d03000041000121f70000003d000045020000013d0000131e05000041000121fa0000003d0000453e0000013d002000000001001d000001800100043d0000000012010434000001000300043d001100000003001d000001200300043d001000000003001d000001400300043d000f00000003001d000001600300043d000e00000003001d4bfc43d70000040f0000000e02000029000013170220019700000026040000290000032003400039000000000023043500000300024000390000000f030000290000000000320435000002e00240003900000010030000290000000000320435000002c00240003900000011030000290000000000320435000002a00240003900000020030000290000000000320435000000210200002900001309022001970000028003400039000000000023043500000260024000390000002203000029000000000032043500000024020000290000130902200197000002400340003900000000002304350000131f02000041000122250000003d000048740000013d000000800200043d002200000002001d003c13090020019b002400000001001d0001222b0000003d0000441d0000013d0000003c0440008a00000020044000c900001320020000414bfc43ed0000040f000000c902000039000000000202041a002000000002001d000000ca02000039000000000202041a001100000002001d002100000001001d000122380000003d000045110000013d00001321020000414bfc43ed0000040f0000002604000029000003c00240003900000011030000290000000000320435000003a002400039000000200300002900000000003204350000132202000041000122440000003d0000486e0000013d0000130901100197000122470000003d000045c40000013d00001323020000410001224a0000003d000046bb0000013d002213090020019b0001224d0000003d0000468d0000013d0000233e0000c13d0000001d060000290000000006060433000000410660008c000027780000c13d0000001e060000290000000006060433002100000006001d0000001d07000029000122580000003d000048680000013d000013280770009c0000277b0000813d000000f8076002700000132b0660009c000004a2069000390000234d0000813d0000001b0870008a000000020880008c00002b020000813d0000002402000029000122640000003d000044f30000013d0000000001000414000000200530008a000000010200003900000020060000390000236a0000013d0001226b0000003d0000498e0000013d0000006d0000c13d0001226e0000003d000047ab0000013d00001c500000013d000122710000003d0000498e0000013d0000006d0000c13d000122740000003d000047ab0000013d00000001030000390000001004000029000000000034043500001c500000013d000000000705004b00000000070000190000227f0000613d00000000875600a900000000985700d9000000000668004b000041ad0000c13d000027107670011a001000000056001e000041bf0000413d0000000e06000029000000000d060433000000000601043300000000020204330000000d010000290000000001010433000000000705004b0000000007000019000022900000613d000000000343001900000000475300a900000000545700d9000000000334004b000041ad0000c13d000027104370011a0000001007300069000000100470006c00000000040000190000000104002039000000000404004b000000000700c019001f00000007001d000000100430006b0000001003004029000000000403004b000027ba0000613d0001229e0000003d00004acb0000013d0000131707700197000013640870009c001d0000000d001d000023730000c13d0000000004060433000000005604043400001308070000410000003f0860008c000000000800001900000000080720190000130806600197000000000906004b0000000007008019000013080660009c000000000708c019000000000607004b0000006d0000613d0000000005050433002613090050019b0000130a0550009c0000006d0000813d000000010330008c000042340000c13d000122b70000003d00004b340000013d000013090220019700000004074000390000130901100197000000230810006b000023b80000c13d00001378010000410000000000140435000000230100002900001309011001970000000000170435000000000026043500000000003504350000249f0000013d0000134a0870009c000023bc0000c13d0000000004060433000000004504043400001308060000410000001f0750008c000000000700001900000000070620190000130805500197000000000805004b0000000006008019000013080550009c000000000607c019000000000506004b0000006d0000613d0000000004040433002513090040019b0000130a0440009c0000006d0000813d000000400500043d001f00440050003d0000002404500039002600000005001d000000040550003900001309022001970000130901100197000000230610006b000023f00000c13d0000137501000041000122e30000003d00004b8e0000013d002700250000002d000122e60000003d0000441d0000013d000000270440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002502000029000000040220008c000022f70000613d00000026030000290000001f04300069000122f40000003d000045900000013d000001560000613d000000400100043d002600000001001d00000001010000310000130803000041000122fb0000003d0000499b0000013d0000130804100197000000000504004b0000000003008019000013080440009c000123010000003d0000454b0000013d0000006d0000613d0000002601000029000123050000003d0000445d0000013d0000006d0000c13d000000000101004b000026d70000c13d0000422e0000013d00001377080000410001230c0000003d0000497b0000013d000024df0000013d000000000101004b00001b020000613d00000005012002100000001b011000290000000001010433000000200210003900000000020204330000137002200197000000250220002a000041bf0000413d000027100220008c000041ea0000c13d0000001f0200006b000029580000613d0001231d0000003d000046700000013d0000131705500197000013640650009c0000240e0000c13d000000000203043300000000340204340000130805000041000123250000003d000048800000013d0000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d0000000003030433002613090030019b0000130a0330009c0000006d0000813d0000001f03000029000000010330008c000042340000c13d000123350000003d0000467b0000013d0000130901100197000123380000003d000046a50000013d000024520000c13d00001378070000410001233c0000003d000044870000013d000025100000013d0000422e0000013d00001324060000410000002407000029000123420000003d000049ff0000013d0000001d02000029000123450000003d000049610000013d000000000412004b000024560000813d00000000043200190000001e05200029000000000505043300000000005404350000002002200039000023450000013d000000fc07700039000000ff0770018f001e00000007001d0000001b0770008a000000020770008c00002b020000813d0000132c02000041000123560000003d00004be20000013d00000000000204350000002605000029000004fe02500039000000400020043f0000055e03500039000000200400002900000000004304350000053e03500039000000210400002900000000004304350000051e035000390000001e0400002900000000004304350000000000120435000000400300043d00000000013500490000057e0410003900000000010004140001236a0000003d00004b570000013d4bfc00340000040f000000000101004b000001560000613d000000400200043d000000200120008a00000000010104330000130901100198000024780000c13d0000195f0000013d0000134a0870009c0000247e0000c13d0000000004060433000000004504043400001308060000410000001f0750008c000000000700001900000000070620190000130805500197000000000805004b0000000006008019000013080550009c000000000607c019000000000506004b0000006d0000613d0000000004040433002513090040019b0000130a0440009c0000006d0000813d000000400500043d001e00440050003d0000002404500039002600000005001d000000040550003900001309022001970000130901100197000000230610006b000024b20000c13d0000137501000041000123920000003d00004b8e0000013d002e00250000002d000123950000003d0000441d0000013d0000002e0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002502000029000000040220008c000023a60000613d00000026030000290000001e04300069000123a30000003d000045900000013d000001560000613d000000400100043d002600000001001d00000001010000310000130803000041000123aa0000003d0000499b0000013d0000130804100197000000000504004b0000000003008019000013080440009c000123b00000003d0000454b0000013d0000006d0000613d0000002601000029000123b40000003d0000445d0000013d0000006d0000c13d000000000101004b000027ba0000c13d0000422e0000013d0000137708000041000123bb0000003d0000497b0000013d000025960000013d0000135f0870009c000024d00000c13d0000000005060433000000004605043400001308070000410000003f0860008c000000000800001900000000080720190000130806600197000000000906004b0000000007008019000013080660009c000000000708c019000000000607004b0000006d0000613d0000000004040433002613090040019b0000130a0440009c0000006d0000813d000123d10000003d00004a230000013d000013090b200197000000400250003900000000020204330000130901100197000000230510006b000024dc0000c13d0000137301000041000000000016043500000023010000290000130901100197000123dd0000003d00004a430000013d000000400100043d001f00000001001d008100260000002d000123e20000003d0000441d0000013d000000810440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002602000029000000040220008c000026d70000613d0000001f0300002900000025043000690000002602000029000026d20000013d0000137406000041000000260700002900000000006704350000002506000029000000000065043500000000001404350000001f01000029000000000021043500000064017000390000000000310435000000400100043d002500000001001d0059130900d0019b000123ff0000003d0000441d0000013d000000590440008a00000020044000c900001320020000414bfc43ed0000040f0000001e020000290000130902200197000000000101004b0000006d0000613d0000000001000414000000040320008c000026d70000613d000000250500002900000026035000690000008404300039000024f10000013d0000134a0650009c000024f30000c13d000000000203043300000000230204340000130804000041000124150000003d000049aa0000013d0000130803300197000000000603004b0000000004008019000013080330009c000000000405c019000000000304004b0000006d0000613d0000000002020433002513090020019b0000130a0220009c0000006d0000813d000000400300043d001e00440030003d0000002402300039002600000003001d000000040330003900001309011001970000001a05000029000000230450006b000025230000c13d00001375040000410001242c0000003d000047f90000013d003800250000002d0001242f0000003d0000441d0000013d000000380440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002502000029000000040220008c000024400000613d00000026030000290000001e043000690001243d0000003d000045900000013d000001560000613d000000400100043d002600000001001d00000001010000310000130803000041000124440000003d0000499b0000013d0000130804100197000000000504004b0000000003008019000013080440009c0001244a0000003d0000454b0000013d0000006d0000613d00000026010000290001244e0000003d0000445d0000013d0000006d0000c13d000000000101004b000029580000c13d0000422e0000013d0000137707000041000124550000003d000045ce0000013d000025e80000013d002400000031001d0000001f011001900000245b0000613d0001245b0000003d000049660000013d000000400100043d002600000001001d009600220000002d000124600000003d0000441d0000013d000000960440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002202000029000000040220008c0000246f0000613d0001246c0000003d00004a4b0000013d000001560000613d000000400100043d002600000001001d00000001010000310000001f0110008c0000006d0000a13d000000260100002900000000010104330000131701100197000013240110009c0000253e0000613d00002b000000013d000000220110006c0000253d0000c13d000000800100043d00001309011001980000253e0000c13d0000197a0000013d0000135f0870009c000025870000c13d0000000005060433000000004605043400001308070000410000003f0860008c000000000800001900000000080720190000130806600197000000000906004b0000000007008019000013080660009c000000000708c019000000000607004b0000006d0000613d0000000004040433002613090040019b0000130a0440009c0000006d0000813d000124930000003d00004a230000013d000013090b200197000000400250003900000000020204330000130901100197000000230510006b000025930000c13d00001373010000410000000000160435000000230100002900001309011001970001249f0000003d00004a430000013d000000400100043d001e00000001001d008800260000002d000124a40000003d0000441d0000013d000000880440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002602000029000000040220008c000027ba0000613d0000001e0300002900000025043000690000002602000029000027b50000013d0000137406000041000000260700002900000000006704350000002506000029000000000065043500000000001404350000001e01000029000000000021043500000064017000390000000000310435000000400100043d002500000001001d0060130900d0019b000124c10000003d0000441d0000013d000000600440008a00000020044000c900001320020000414bfc43ed0000040f0000001d020000290000130902200197000000000101004b0000006d0000613d0000000001000414000000040320008c000027ba0000613d000000250500002900000026035000690000008404300039000025a80000013d0000134b0670009c000025aa0000c13d0000130904200197000000230140006b000026d70000613d000000400200043d0000000001000414000000040540008c000025bc0000c13d00000001020000390000000105000031000025c90000013d0000137205000041000124df0000003d000048090000013d000000400100043d002500000001001d006d130900d0019b000124e40000003d0000441d0000013d0000006d0440008a00000020044000c900001320020000414bfc43ed0000040f0000001e020000290000130902200197000000000101004b0000006d0000613d0000000001000414000000040320008c000026d70000613d000000250500002900000026045000690000000003050019000026d30000013d0000135f0650009c000025d90000c13d000000000203043300000000340204340000130805000041000124fa0000003d000048800000013d0000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d0000000003030433002613090030019b0000130a0330009c0000006d0000813d000000400400043d002500c40040003d000125090000003d000044cd0000013d00001309091001970001250c0000003d0000499f0000013d000025e50000c13d0000137302000041000125100000003d0000464f0000013d000000400100043d001f00000001001d009200260000002d000125150000003d0000441d0000013d000000920440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002602000029000000040220008c000029580000613d0000001f0300002900000025043000690000002602000029000029550000013d0000137404000041000125260000003d00004b270000013d0000001e02000029000000000012043500000064015000390000001f020000290000000000210435000000400100043d002500000001001d006a00190000002d000125300000003d0000441d0000013d0000006a0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000029580000613d0001253c0000003d00004b8a0000013d000029540000013d000019800000013d00000015010000290000000001010433002600000001001d000000000101004b000025490000613d000125450000003d000045110000013d0000131c020000414bfc43ed0000040f000000260110006b000025740000813d00000014010000290000000001010433002600000001001d000000000101004b000025540000613d000125500000003d000045110000013d0000131c020000414bfc43ed0000040f000000260110006b0000257b0000a13d0000001701000029000000000101043300000018020000290000000002020433000000000202004b000025fa0000c13d000013090110019800002cdb0000613d0000000002000411000000230320006b000025700000c13d00000000020000310000003f032000390000001f0430017f000125640000003d000046cd0000013d000025690000613d0000000008000019000125680000003d000045760000013d000025660000413d000000000805004b0000256d0000613d0001256d0000003d000044790000013d0001256f0000003d00004a190000013d00001309022001970000130902200197000000000112004b00002cdb0000613d00000ea50000013d000000400200043d00000044012000390000136103000041000000000031043500000024012000390000001d03000039000025810000013d000000400200043d00000044012000390000136203000041000000000031043500000024012000390000001b030000390000000000310435000013100100004100000000001204350000000401200039000000200300003900000adc0000013d0000134b0670009c000026800000c13d0000130904200197000000230140006b000027ba0000613d000000400200043d0000000001000414000000040540008c000026920000c13d000000010200003900000001050000310000269f0000013d0000137205000041000125960000003d000048090000013d000000400100043d002500000001001d0074130900d0019b0001259b0000003d0000441d0000013d000000740440008a00000020044000c900001320020000414bfc43ed0000040f0000001d020000290000130902200197000000000101004b0000006d0000613d0000000001000414000000040320008c000027ba0000613d000000250500002900000026045000690000000003050019000027b60000013d000000400300043d0000137106000041000000000063043500000004063000390000006007000039000125b10000003d00004b3b0000013d0000131705500197000125b40000003d0000485c0000013d000000260760006c000026af0000813d00000025076000290000002006600039000000000856001900000000080804330000000000870435000025b40000013d0000130005000041000013000610009c0000000001058019000013000620009c0000000002058019000125c30000003d0000460e0000013d0000130b011001c70000800902000039000125c70000003d000044570000013d000113000010019d0000130005100197000000000105004b000025d60000613d000125cd0000003d000044ac0000013d000025d20000613d0000000006000019000125d10000003d000044210000013d000025cf0000413d000000000601004b000025d60000613d000125d60000003d0000440f0000013d000000000102004b000026d70000c13d0000435d0000013d0000134b0350009c0000273b0000c13d0000130904100197000000230140006b000029580000613d000000400200043d0000000001000414000000040340008c0000274b0000c13d00000001020000390000000105000031000027590000013d0000137202000041000125e80000003d000045960000013d000000400100043d002500000001001d007e00190000002d000125ed0000003d0000441d0000013d0000007e0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000029580000613d00000026020000290000002503000029000029530000013d0000000002000411000000230320006b0000260e0000c13d00000000020000310000003f032000390000001f0430017f000126020000003d000046cd0000013d000026070000613d0000000008000019000126060000003d000045760000013d000026040000413d000000000805004b0000260b0000613d0001260b0000003d000044790000013d0001260d0000003d00004a190000013d0000130902200197000000000112013f000013090110019800002cdb0000613d0000001b01000029000126140000003d00004adf0000013d000126160000003d000049d60000013d0000131702200197000126190000003d000049110000013d0000131d030000410001261c0000003d0000448d0000013d0000131e030000410001261f0000003d000045d80000013d0000001902000029000126220000003d000047c70000013d0000131702200197000126250000003d000049ae0000013d0000131d03000041000126280000003d000045020000013d0000131e050000410001262b0000003d0000453e0000013d00000018020000290000000002020433002000000002001d00000015020000290000000002020433001f00000002001d00000014020000290000000002020433001d00000002001d00000013020000290000000002020433001b00000002001d00000012020000290000000002020433001e00000001001d00000000120204344bfc43d70000040f0000001b020000290000131702200197000126400000003d000045650000013d0000130902200197000126430000003d000048f80000013d0000130902200197000002400340003900000000002304350000131f02000041000126490000003d000047610000013d002200000002001d003b13090020019b002400000001001d0001264e0000003d0000441d0000013d0000003b0440008a00000020044000c90000132002000041000126530000003d00004bcc0000013d000126550000003d000045110000013d0000132102000041000126580000003d0000471c0000013d00001322020000410001265b0000003d0000486e0000013d00001309011001970001265e0000003d000045c40000013d0000132302000041000126610000003d000046bb0000013d002213090020019b000126640000003d0000468d0000013d000027690000c13d0000001a060000290000000006060433000000410660008c000027780000c13d0000001c060000290000000006060433002100000006001d0000001a070000290001266f0000003d000048680000013d000013280770009c0000277b0000813d000000f8076002700000132b0660009c000004a2069000390000277e0000813d0000001b0870008a000000020880008c00002b020000813d00000024020000290001267b0000003d000044f30000013d0000000001000414000000200530008a00000001020000390000002006000039000027890000013d000000400300043d0000137106000041000000000063043500000004063000390000002207000029000126870000003d00004b3b0000013d00001317055001970001268a0000003d0000485c0000013d000000260760006c000027920000813d000000250760002900000020066000390000000008560019000000000808043300000000008704350000268a0000013d0000130005000041000013000610009c0000000001058019000013000620009c0000000002058019000126990000003d0000460e0000013d0000130b011001c700008009020000390001269d0000003d000044570000013d000113000010019d0000130005100197000000000105004b000026ac0000613d000126a30000003d000044ac0000013d000026a80000613d0000000006000019000126a70000003d000044210000013d000026a50000413d000000000601004b000026ac0000613d000126ac0000003d0000440f0000013d000000000102004b000027ba0000c13d0000435d0000013d001f130900d0019b000000260560006c000026b50000a13d000000260600002900000025056000290000000000050435000000000404043300001309022001970000004405300039000000000025043500001309011001970000002402300039000000000012043500000084013000390000000000410435000000400100043d001e00000001001d0043001f0000002d000126c30000003d0000441d0000013d000000430440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001f02000029000000040220008c000026d70000613d000126cf0000003d0000496f0000013d0000001e0300002900000000043200490000001f02000029000000000503001900000000060000194bfc000d0000040f000000000101004b000001560000613d0000000f010000290000000001010433001d00000001001d00000012010000290000000001010433001c00000001001d0000000c010000290000000001010433001a00000001001d000000130100002900000000010104330000000012010434001800000002001d0000000001010433001e00000001001d000000140100002900000000010104330000000001010433000000001201043400001317022001970000135f0320009c0000281e0000613d000013640320009c0000281e0000613d000013790320009c000028b10000c13d0000000003010433000000002103043400001308040000410000003f0510008c000000000500001900000000050420190000130806100197000000000706004b0000000004008019000013080660009c000000000405c019000000000404004b0000006d0000613d00000000040204330000130a0440009c0000006d0000813d00000040033000390000000003030433000013160430009c0000006d0000813d0000000001120019000000000423001900000000024100490000130803000041000000bf0520008c000000000500001900000000050320190000130802200197000000000602004b0000000003008019000013080220009c000000000305c019000000000203004b0000006d0000613d000000400200043d002600000002001d0000137c0320009c00001b020000813d000127190000003d00004b100000013d000013160630009c0000006d0000813d00000000034300190000001f063000390000130807000041000127200000003d00004adb0000013d00001308066001970000130809100197000127240000003d000049970000013d000013080660009c000000000708c019000000000607004b0000006d0000613d0000000086030434000013160360009c00001b020000813d0001272d0000003d00004bc50000013d00001b020000413d000013160a90009c00001b020000813d000000400090043f0000000009670436000000000a680019000000000a1a004b0000006d0000213d000000000a000019000000000b6a004b000028fe0000813d0001273a0000003d000048e60000013d000027360000013d000000400300043d0000137105000041000000000053043500000004053000390000002206000029000127420000003d000044a00000013d0000131704400197000127450000003d000044e70000013d000000260650006c0000293a0000813d00000025065000290001274a0000003d000045260000013d000027450000013d0000130003000041000013000510009c0000000001038019000013000520009c0000000002038019000127520000003d0000460e0000013d0000130b011001c700008009020000390000001f03000029000127570000003d000044570000013d000113000010019d0000130005100197000000000105004b000027660000613d0001275d0000003d000044ac0000013d000027620000613d0000000006000019000127610000003d000044210000013d0000275f0000413d000000000601004b000027660000613d000127660000003d0000440f0000013d000000000102004b000029580000c13d0000435d0000013d000013240600004100000024070000290001276d0000003d000049ff0000013d0000001a02000029000127700000003d000049610000013d000000000412004b00002adf0000813d00000000043200190000001c05200029000000000505043300000000005404350000002002200039000027700000013d00001310010000410000002403000029000012710000013d00001310010000410000002406000029000013100000013d000127800000003d000049a40000013d00002b020000813d0000132c02000041000127840000003d00004be20000013d000127860000003d000045530000013d0000000001000414000127890000003d00004b570000013d4bfc00340000040f000000000101004b000001560000613d000000400200043d000000200120008a0000000001010433000013090110019800002b050000c13d0000195f0000013d001e130900d0019b000000260560006c000027980000a13d000000260600002900000025056000290000000000050435000000000404043300001309022001970000004405300039000000000025043500001309011001970000002402300039000000000012043500000084013000390000000000410435000000400100043d001d00000001001d004a001e0000002d000127a60000003d0000441d0000013d0000004a0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001e02000029000000040220008c000027ba0000613d000127b20000003d0000496f0000013d0000001d0300002900000000043200490000001e02000029000000000503001900000000060000194bfc000d0000040f000000000101004b000001560000613d0000000e010000290000000001010433001d00000001001d0000000d010000290000000001010433001c00000001001d0000000b010000290000000001010433001a00000001001d000000140100002900000000010104330000000012010434001800000002001d0000000001010433001e00000001001d000000130100002900000000010104330000000001010433000000001201043400001317022001970000135f0320009c00002b0c0000613d000013640320009c00002b0c0000613d000013790320009c00002b9f0000c13d0000000003010433000000002103043400001308040000410000003f0510008c000000000500001900000000050420190000130806100197000000000706004b0000000004008019000013080660009c000000000405c019000000000404004b0000006d0000613d00000000040204330000130a0440009c0000006d0000813d00000040033000390000000003030433000013160430009c0000006d0000813d0000000001120019000000000423001900000000024100490000130803000041000000bf0520008c000000000500001900000000050320190000130802200197000000000602004b0000000003008019000013080220009c000000000305c019000000000203004b0000006d0000613d000000400200043d002600000002001d0000137c0320009c00001b020000813d000127fc0000003d00004b100000013d000013160630009c0000006d0000813d00000000034300190000001f063000390000130807000041000128030000003d00004adb0000013d00001308066001970000130809100197000128070000003d000049970000013d000013080660009c000000000708c019000000000607004b0000006d0000613d0000000086030434000013160360009c00001b020000813d000128100000003d00004bc50000013d00001b020000413d000013160a90009c00001b020000813d000000400090043f0000000009670436000000000a680019000000000a1a004b0000006d0000213d000000000a000019000000000b6a004b00002beb0000813d0001281d0000003d000048e60000013d000028190000013d000000000101043300000000230104340000130804000041000128230000003d00004abf0000013d0000130803300197000000000603004b0000000004008019000013080330009c000000000405c019000000000304004b0000006d0000613d00000000020204330000130a0320009c0000006d0000813d0000016203000039000000000503041a001f00000005001d00000040011000390000000001010433000000400400043d000000240340003900000000001304350000137d01000041000128380000003d00004b640000013d005713090050019b0001283b0000003d0000441d0000013d000000570440008a00000020044000c900001320020000414bfc43ed0000040f0000001f020000290000130902200197000000000101004b0000006d0000613d0000000001000414000000040320008c0000284b0000613d000128480000003d00004a570000013d000001560000613d000000400100043d002600000001001d0001284d0000003d000048260000013d000028540000613d000000000500001900000005065002100000002607600029000128530000003d000045be0000013d0000284f0000413d000000000503004b0000285b0000613d0000000504400210000000000242034f00000026044000290001285b0000003d0000446e0000013d00001308020000410001285e0000003d00004ac30000013d0000130804100197000000000504004b0000000002008019000013080440009c000000000203c0190000001f03100039000000200400008a000000000343016f0000002603300029001f00000003001d000000400030043f000000000202004b0000006d0000613d00000026020000290000000002020433000013160320009c0000006d0000813d000000260110002900000026022000290000001f032000390000130804000041000128750000003d00004abb0000013d00001308033001970000130806100197000128790000003d00004ab70000013d000013080330009c000000000405c019000000000304004b0000006d0000613d0000000032020434000013160420009c00001b020000813d00000005042002100000001f0440002900000020044000390000001f0540006c00001b020000413d000013160540009c00001b020000813d000000400040043f0000001f04000029000000000024043500000006042002100000000004430019000000000441004b0000006d0000413d00001308040000410000001f050000290000000006000019000000000726004b00002ff60000813d00000000073100490000003f0870008c000000000800001900000000080420190000130807700197000000000907004b00000000090000190000000009044019000013080770009c000000000908c019000000000709004b0000006d0000613d000000400700043d000013190870009c00001b020000813d0000004008700039000000400080043f00000000980304340000130a0a80009c0000006d0000813d000000000887043600000000090904330000136b0a90009c0000006d0000813d00000020055000390000000000980435000000000075043500000001066000390000004003300039000028910000013d001f00600000003d0000137a0220009c00002ff60000c13d0000000003010433000000002103043400001308040000410000003f0510008c000000000500001900000000050420190000130806100197000000000706004b0000000004008019000013080660009c000000000405c019000000000404004b0000006d0000613d00000000040204330000130a0440009c0000006d0000813d00000040033000390000000003030433000013160430009c0000006d0000813d00000000011200190000000004230019000000000241004900001308030000410000009f0520008c000000000500001900000000050320190000130802200197000000000602004b0000000003008019000013080220009c000000000305c019000000000203004b0000006d0000613d000000400200043d002600000002001d0000137b0220009c00001b020000813d000128dc0000003d00004b200000013d000013160320009c0000006d0000813d00000000034200190000001f023000390000130806000041000128e30000003d00004ab30000013d00001308022001970000130808100197000128e70000003d00004aa70000013d000013080220009c000000000607c019000000000206004b0000006d0000613d0000000086030434000013160260009c00001b020000813d000128f00000003d00004ba30000013d00001b020000413d000013160920009c00001b020000813d000000400020043f00000000096704360000000002680019000000000212004b0000006d0000213d000000000a00001900000000026a004b00002c270000813d000128fd0000003d000048e60000013d000028f90000013d00000000026a004b000029020000a13d00000000026900190000000000020435000129040000003d000049e20000013d000013160650009c0000006d0000813d00000000054500190000001f0650003900001308070000410001290b0000003d00004adb0000013d000013080660019700001308091001970001290f0000003d000049970000013d000013080660009c000000000708c019000000000607004b0000006d0000613d0000000065050434000013160750009c00001b020000813d000129180000003d000048ce0000013d00001b020000413d000013160980009c00001b020000813d0001291d0000003d000048c80000013d0000006d0000413d00001308080000410000000009070019000000000a000019000000000b5a004b00002c650000813d000129250000003d000046fc0000013d0000130802200197000129280000003d0000495d0000013d000013080220009c000000000c0bc01900000000020c004b0000006d0000613d000000400b00043d000013190cb0009c00001b020000813d000129310000003d00004b2e0000013d0000130a0ec0009c0000006d0000813d000000000ccb0436000000000d0d04330000136b0ed0009c0000006d0000813d000129390000003d0000474d0000013d000029210000013d000000260450006c0000293e0000a13d0001293e0000003d00004b1c0000013d00000000020204330000130901100197000129420000003d000049bc0000013d001f00000001001d005400190000002d000129460000003d0000441d0000013d000000540440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000029580000613d000129520000003d0000496f0000013d0000001f0300002900000000043200490000001902000029000129570000003d0000452b0000013d000001560000613d0000000b010000290000000001010433001d00000001001d0000000021010434001a00000002001d000000000201004b0000405f0000613d000000140200002900000000020204330000000023020434001700000003001d00000000030204330000000d020000290000000002020433001913090020019b0000000e020000290000000002020433001813090020019b002500000000001d001f00000003001d001e00000003001d002600000000001d000000010210008a000000260320006b00002ca00000813d000000260110006b00001b020000813d000000260100002900000005011002100000001a0110002900000000020104330000002002200039000000000202043300001370022001970000001f0300006b0000000004000019000029810000613d0000001f342000b90000001f534000fa000000000323004b000041ad0000c13d002500250020002e000041bf0000413d000027100240008c00002a840000413d000027102340011a0000001e0230006b00001ccd0000413d000000400500043d0000004002500039000000400020043f0000001702000029000000000225043600000000003204350000001d060000290000000006060433000000260660006b00001b020000813d001e001e00300071000129950000003d000049360000013d0000131707700197000013640870009c000029b60000c13d0001299a0000003d00004b510000013d0000130808000041000000000600001900000000060820190000130805500197000129a00000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000003030433001c13090030019b0000130a0330009c0000006d0000813d000027100340008a000027100330008c000042340000813d000129ad0000003d0000473f0000013d000013090110019700000004063000390000001908000029000000230780006b000029fd0000c13d0000137807000041000129b50000003d000044870000013d00002a270000013d0000134a0470009c00002a080000c13d000129ba0000003d00004b4d0000013d0000130807000041000000000500001900000000050720190000130804400197000129c00000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000002020433001c13090020019b0000130a0220009c0000006d0000813d000000400400043d001400440040003d0000002402400039001b00000004001d000000040440003900001309011001970000001906000029000000230560006b00002a3a0000c13d0000137505000041000129d40000003d0000470e0000013d0039001c0000002d000129d70000003d0000441d0000013d000000390440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001c02000029000000040220008c000029ea0000613d0000001b03000029000000140430006900000020060000390000001c02000029000129e70000003d0000460a0000013d000001560000613d000000400100043d001b00000001001d00000001010000310000001f0210008c0000130805000041000000000200001900000000020520190000130803100197000129f20000003d000047250000013d000013080330009c000129f50000003d0000469d0000013d0000006d0000613d0000001b01000029000129f90000003d0000445d0000013d0000006d0000c13d000000000101004b00002a840000c13d00002cd90000013d000013770700004100000000007304350000001c0700002900000000007604350000001906000029000000000065043500000000001404350000001b010000290000000000210435001c00840030003d00002a6e0000013d0000135f0470009c00002a580000c13d00012a0c0000003d00004b490000013d000013080800004100000000060000190000000006082019000013080550019700012a120000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000004040433001c13090040019b0000130a0440009c0000006d0000813d000000400500043d001b00c40050003d00012a1e0000003d000045890000013d000013090a10019700000040012000390000000001010433000000190c0000290000002302c0006b00002a640000c13d000013730200004100012a270000003d000044c30000013d000000400100043d001400000001001d0093001c0000002d00012a2c0000003d0000441d0000013d000000930440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001c02000029000000040220008c00002a840000613d00000014030000290000001b043000690000001c0200002900002a810000013d00001374050000410000001b0600002900000000005604350000001c050000290000000000540435000000190400002900000000004204350000001402000029000000000012043500000064016000390000000000310435000000400100043d001c00000001001d006b00180000002d00012a4a0000003d0000441d0000013d0000006b0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001802000029000000040220008c00002a840000613d0000001c030000290000001b02300069000000840420003900002a800000013d0000134b0470009c00002a890000c13d0000130904100197000000230140006b00002a840000613d000000400200043d0000000001000414000000040540008c00002ac20000c13d0000000102000039000000010100003100002acf0000013d000013720200004100000000002504350000001c0200002900000000002b0435000000190200002900012a6b0000003d00004bf50000013d0000001b010000290000000000010435001c00e40050003d000000400100043d001b00000001001d007f00180000002d00012a730000003d0000441d0000013d0000007f0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001802000029000000040220008c00002a840000613d0000001c020000290000001b030000290000000004320049000000180200002900012a830000003d0000452b0000013d000001560000613d0000001d0100002900000000010104330000002602000029002600010020003d0000296e0000013d000000400300043d00001371040000410000000000430435000000040430003900000022060000290000000000640435000000000405043300012a920000003d000045210000013d0000131704400197000000a40630003900000000004604350000000004050433000000c4053000390000000000750435000000e4053000390000000006040433001c00000006001d0000000000650435001b01040030003d00000000050000190000001c0650006c00002aa40000813d0000001b0650002900012aa30000003d000045260000013d00002a9e0000013d0000001c0450006c00002aa90000a13d0000001c050000290000001b0450002900000000000404350000000002020433000013090110019700012aad0000003d000049b30000013d001400000001001d005500180000002d00012ab10000003d0000441d0000013d000000550440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001802000029000000040220008c00002a840000613d0000001c020000290000001f02200039000000200300008a000000000232016f0000001b02200029000000140300002900002a7f0000013d000013000510009c00001300060000410000000001068019000013000520009c000000000206801900012ac90000003d0000460e0000013d0000130b011001c7000080090200003900012acd0000003d000044570000013d000113000010019d0000130001100197000000000301004b00002adc0000613d00012ad30000003d000044290000013d00002ad80000613d000000000600001900012ad70000003d000044210000013d00002ad50000413d0000001f0110019000002adc0000613d00012adc0000003d0000440f0000013d000000000102004b00002a840000c13d0000435d0000013d002400000031001d0000001f0110019000002ae40000613d00012ae40000003d000049660000013d000000400100043d002600000001001d009700220000002d00012ae90000003d0000441d0000013d000000970440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002202000029000000040220008c00002af80000613d00012af50000003d00004a4b0000013d000001560000613d000000400100043d002600000001001d00000001010000310000001f0110008c0000006d0000a13d000000260100002900000000010104330000131701100197000013240110009c00002cdb0000613d0000002603000029000012ae0000013d00001310010000410000002406000029000019670000013d000000220110006c00002cda0000c13d00000017010000290000000001010433000013090110019800002cdb0000c13d0000197a0000013d00000000010104330000000023010434000013080400004100012b110000003d00004abf0000013d0000130803300197000000000603004b0000000004008019000013080330009c000000000405c019000000000304004b0000006d0000613d00000000020204330000130a0320009c0000006d0000813d0000016203000039000000000503041a002200000005001d00000040011000390000000001010433000000400400043d000000240340003900000000001304350000137d0100004100012b260000003d00004b640000013d005813090050019b00012b290000003d0000441d0000013d000000580440008a00000020044000c900001320020000414bfc43ed0000040f00000022020000290000130902200197000000000101004b0000006d0000613d0000000001000414000000040320008c00002b390000613d00012b360000003d00004a570000013d000001560000613d000000400100043d002600000001001d00012b3b0000003d000048260000013d00002b420000613d00000000050000190000000506500210000000260760002900012b410000003d000045be0000013d00002b3d0000413d000000000503004b00002b490000613d0000000504400210000000000242034f000000260440002900012b490000003d0000446e0000013d000013080200004100012b4c0000003d00004ac30000013d0000130804100197000000000504004b0000000002008019000013080440009c000000000203c0190000001f03100039000000200400008a000000000343016f0000002603300029002200000003001d000000400030043f000000000202004b0000006d0000613d00000026020000290000000002020433000013160320009c0000006d0000813d000000260110002900000026022000290000001f03200039000013080400004100012b630000003d00004abb0000013d0000130803300197000013080610019700012b670000003d00004ab70000013d000013080330009c000000000405c019000000000304004b0000006d0000613d0000000032020434000013160420009c00001b020000813d000000050420021000000022044000290000002004400039000000220540006c00001b020000413d000013160540009c00001b020000813d000000400040043f0000002204000029000000000024043500000006042002100000000004430019000000000441004b0000006d0000413d000013080400004100000022050000290000000006000019000000000726004b000030380000813d00000000073100490000003f0870008c000000000800001900000000080420190000130807700197000000000907004b00000000090000190000000009044019000013080770009c000000000908c019000000000709004b0000006d0000613d000000400700043d000013190870009c00001b020000813d0000004008700039000000400080043f00000000980304340000130a0a80009c0000006d0000813d000000000887043600000000090904330000136b0a90009c0000006d0000813d0000002005500039000000000098043500000000007504350000000106600039000000400330003900002b7f0000013d0000137a0220009c000030380000c13d0000000003010433000000002103043400001308040000410000003f0510008c000000000500001900000000050420190000130806100197000000000706004b0000000004008019000013080660009c000000000405c019000000000404004b0000006d0000613d00000000040204330000130a0440009c0000006d0000813d00000040033000390000000003030433000013160430009c0000006d0000813d00000000011200190000000004230019000000000241004900001308030000410000009f0520008c000000000500001900000000050320190000130802200197000000000602004b0000000003008019000013080220009c000000000305c019000000000203004b0000006d0000613d000000400200043d002600000002001d0000137b0220009c00001b020000813d00012bc90000003d00004b200000013d000013160320009c0000006d0000813d00000000034200190000001f02300039000013080600004100012bd00000003d00004ab30000013d0000130802200197000013080810019700012bd40000003d00004aa70000013d000013080220009c000000000607c019000000000206004b0000006d0000613d0000000086030434000013160260009c00001b020000813d00012bdd0000003d00004ba30000013d00001b020000413d000013160920009c00001b020000813d000000400020043f00000000096704360000000002680019000000000212004b0000006d0000213d000000000a00001900000000026a004b00002d020000813d00012bea0000003d000048e60000013d00002be60000013d00000000026a004b00002bef0000a13d0000000002690019000000000002043500012bf10000003d000049e20000013d000013160650009c0000006d0000813d00000000054500190000001f06500039000013080700004100012bf80000003d00004adb0000013d0000130806600197000013080910019700012bfc0000003d000049970000013d000013080660009c000000000708c019000000000607004b0000006d0000613d0000000065050434000013160750009c00001b020000813d00012c050000003d000048ce0000013d00001b020000413d000013160980009c00001b020000813d00012c0a0000003d000048c80000013d0000006d0000413d00001308080000410000000009070019000000000a000019000000000b5a004b00002d400000813d00012c120000003d000046fc0000013d000013080220019700012c150000003d0000495d0000013d000013080220009c000000000c0bc01900000000020c004b0000006d0000613d000000400b00043d000013190cb0009c00001b020000813d00012c1e0000003d00004b2e0000013d0000130a0ec0009c0000006d0000813d000000000ccb0436000000000d0d04330000136b0ed0009c0000006d0000813d00012c260000003d0000474d0000013d00002c0e0000013d00000000026a004b00002c2b0000a13d00000000026900190000000000020435000000000075043500000040024000390000000002020433000013160520009c0000006d0000813d00000000054200190000001f02500039000013080600004100012c350000003d00004ab30000013d0000130802200197000013080810019700012c390000003d00004aa70000013d000013080220009c000000000607c019000000000206004b0000006d0000613d0000000065050434000013160250009c00001b020000813d00012c420000003d000048c20000013d00001b020000413d000013160820009c00001b020000813d00012c470000003d000048e00000013d0000006d0000413d00001308080000410000000009070019000000000a00001900000000025a004b00002d7b0000813d00012c4f0000003d000046fc0000013d000013080220019700012c520000003d0000495d0000013d000013080220009c000000000c0bc01900000000020c004b0000006d0000613d000000400b00043d0000131902b0009c00001b020000813d0000004002b00039000000400020043f00000000c20604340000130a0d20009c0000006d0000813d00000000022b0436000000000c0c04330000136b0dc0009c0000006d0000813d00012c640000003d000048f20000013d00002c4b0000013d00000026020000290000006005200039000000000075043500000080054000390000000005050433000013160650009c0000006d0000813d00000000054500190000001f06500039000013080700004100012c710000003d00004adb0000013d0000130806600197000013080910019700012c750000003d000049970000013d000013080660009c000000000708c019000000000607004b0000006d0000613d0000000065050434000013160750009c00001b020000813d00012c7e0000003d000048ce0000013d00001b020000413d000013160980009c00001b020000813d00012c830000003d000048c80000013d0000006d0000413d00001308080000410000000009070019000000000a000019000000000b5a004b00002db70000813d00012c8b0000003d000046fc0000013d000013080220019700012c8e0000003d0000495d0000013d000013080220009c000000000c0bc01900000000020c004b0000006d0000613d000000400b00043d000013190cb0009c00001b020000813d00012c970000003d00004b2e0000013d0000130a0ec0009c0000006d0000813d000000000ccb0436000000000d0d04330000136b0ed0009c0000006d0000813d00012c9f0000003d0000474d0000013d00002c870000013d000000000101004b00001b020000613d00000005012002100000001a011000290000000001010433000000200210003900000000020204330000137002200197000000250220002a000041bf0000413d000027100220008c000041ea0000c13d0000001e0200006b000042e80000613d000000400400043d0000004002400039000000400020043f00000020024000390000001e03000029000000000032043500000017030000290000000000340435000000000101043300000000350304340000131705500197000013640650009c00002e0b0000c13d00000000020304330000000034020434000013080500004100012cc00000003d000048800000013d0000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d0000000003030433002613090030019b0000130a0330009c0000006d0000813d0000001e03000029000000010330008c000042340000c13d00012cd00000003d0000467b0000013d000013090110019700000004063000390000001908000029000000230780006b00002e510000c13d000013780700004100012cd80000003d000044870000013d00002f6a0000013d0000422e0000013d000019800000013d000000c00100043d000013090410019800002ce70000613d00000017010000290000000001010433000013090510019800002ce70000613d000013320300004100001333020000410000002301000039000000000445004b00002cf30000c13d000000190100002900000000010104330000130904100198000011910000613d000000800100043d0000130905100198000011910000613d000013340300004100001335020000410000002401000039000000000454004b000011910000613d000000400400043d00000064054000390000000000350435000000440340003900000000002304350000002402400039000000000012043500001310010000410000000000140435000000040140003900000020020000390000000000210435000000400100043d000000000214004900004b550000013d00000000026a004b00002d060000a13d00000000026900190000000000020435000000000075043500000040024000390000000002020433000013160520009c0000006d0000813d00000000054200190000001f02500039000013080600004100012d100000003d00004ab30000013d0000130802200197000013080810019700012d140000003d00004aa70000013d000013080220009c000000000607c019000000000206004b0000006d0000613d0000000065050434000013160250009c00001b020000813d00012d1d0000003d000048c20000013d00001b020000413d000013160820009c00001b020000813d00012d220000003d000048e00000013d0000006d0000413d00001308080000410000000009070019000000000a00001900000000025a004b00002e5c0000813d00012d2a0000003d000046fc0000013d000013080220019700012d2d0000003d0000495d0000013d000013080220009c000000000c0bc01900000000020c004b0000006d0000613d000000400b00043d0000131902b0009c00001b020000813d0000004002b00039000000400020043f00000000c20604340000130a0d20009c0000006d0000813d00000000022b0436000000000c0c04330000136b0dc0009c0000006d0000813d00012d3f0000003d000048f20000013d00002d260000013d00000026020000290000006005200039000000000075043500000080054000390000000005050433000013160650009c0000006d0000813d00000000054500190000001f06500039000013080700004100012d4c0000003d00004adb0000013d0000130806600197000013080910019700012d500000003d000049970000013d000013080660009c000000000708c019000000000607004b0000006d0000613d0000000065050434000013160750009c00001b020000813d00012d590000003d000048ce0000013d00001b020000413d000013160980009c00001b020000813d00012d5e0000003d000048c80000013d0000006d0000413d00001308080000410000000009070019000000000a000019000000000b5a004b00002e980000813d00012d660000003d000046fc0000013d000013080220019700012d690000003d0000495d0000013d000013080220009c000000000c0bc01900000000020c004b0000006d0000613d000000400b00043d000013190cb0009c00001b020000813d00012d720000003d00004b2e0000013d0000130a0ec0009c0000006d0000813d000000000ccb0436000000000d0d04330000136b0ed0009c0000006d0000813d00012d7a0000003d0000474d0000013d00002d620000013d00000026020000290000004002200039000000000072043500000060024000390000000002020433000013160520009c0000006d0000813d00000000054200190000001f02500039000013080600004100012d870000003d00004ab30000013d0000130802200197000013080810019700012d8b0000003d00004aa70000013d000013080220009c000000000607c019000000000206004b0000006d0000613d0000000065050434000013160250009c00001b020000813d00012d940000003d000048c20000013d00001b020000413d000013160820009c00001b020000813d00012d990000003d000048e00000013d0000006d0000413d00001308080000410000000009070019000000000a00001900000000025a004b00002eec0000813d00012da10000003d000046fc0000013d000013080220019700012da40000003d0000495d0000013d000013080220009c000000000c0bc01900000000020c004b0000006d0000613d000000400b00043d0000131902b0009c00001b020000813d0000004002b00039000000400020043f00000000c20604340000130a0d20009c0000006d0000813d00000000022b0436000000000c0c04330000136b0dc0009c0000006d0000813d00012db60000003d000048f20000013d00002d9d0000013d00000026020000290000008002200039001f00000002001d0000000000720435000000a0054000390000000005050433000013160650009c0000006d0000813d00000000064500190000001f046000390000130805000041000000000714004b0000000007000019000000000705401900001308044001970000130808100197000000000984004b000000000500a019000000000484013f000013080440009c000000000507c019000000000405004b0000006d0000613d0000000007060433000013160470009c00001b020000813d00012dd30000003d00004b790000013d00001b020000413d000013160850009c00001b020000813d000000400050043f000000250900002900000000007904350000130808000041000000000a060019000000000b00001900000000057b004b00002f400000813d00012de00000003d000046db0000013d0000130802200197000013080c10019700012de40000003d000049c50000013d000013080220009c000000000d05c01900000000020d004b0000006d0000613d0000002005e00039000000000c0504330000131605c0009c00001b020000813d0000003f05c00039000000000535016f000000400d00043d00000000055d0019000000000fd5004b00001b020000413d000013160f50009c00001b020000813d000000400050043f000000000fcd0436000000400ee000390000000005ce0019000000000515004b0000006d0000213d000000200990003900000000050000190000000002c5004b00002e040000813d0000000002f5001900000000045e001900000000040404330000000000420435000000200550003900002dfc0000013d0000000002c5004b00002e080000a13d0000000002cf001900000000000204350000000000d90435000000010bb0003900002ddc0000013d0000134a0650009c00002f430000c13d00000000020304330000000023020434000013080400004100012e120000003d000049aa0000013d0000130803300197000000000603004b0000000004008019000013080330009c000000000405c019000000000304004b0000006d0000613d0000000002020433002513090020019b0000130a0220009c0000006d0000813d00012e1f0000003d000049f90000013d00001309011001970000001905000029000000230450006b00002f7a0000c13d00001375040000410000002605000029000000000045043500000000001304350000001e010000290000000000120435000000400100043d002600000001001d003a00250000002d00012e2e0000003d0000441d0000013d0000003a0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002502000029000000040220008c00002e3f0000613d0000002603000029000000220430006900012e3c0000003d000045900000013d000001560000613d000000400100043d002600000001001d0000000101000031000013080300004100012e430000003d0000499b0000013d0000130804100197000000000504004b0000000003008019000013080440009c00012e490000003d0000454b0000013d0000006d0000613d000000260100002900012e4d0000003d0000445d0000013d0000006d0000c13d000000000101004b000042e80000c13d0000422e0000013d000013770700004100000000007304350000002607000029000000000076043500000019060000290000000000650435000000000014043500000025010000290000000000210435002600840030003d0000301f0000013d00000026020000290000004002200039000000000072043500000060024000390000000002020433000013160520009c0000006d0000813d00000000054200190000001f02500039000013080600004100012e680000003d00004ab30000013d0000130802200197000013080810019700012e6c0000003d00004aa70000013d000013080220009c000000000607c019000000000206004b0000006d0000613d0000000065050434000013160250009c00001b020000813d00012e750000003d000048c20000013d00001b020000413d000013160820009c00001b020000813d00012e7a0000003d000048e00000013d0000006d0000413d00001308080000410000000009070019000000000a00001900000000025a004b00002f980000813d00012e820000003d000046fc0000013d000013080220019700012e850000003d0000495d0000013d000013080220009c000000000c0bc01900000000020c004b0000006d0000613d000000400b00043d0000131902b0009c00001b020000813d0000004002b00039000000400020043f00000000c20604340000130a0d20009c0000006d0000813d00000000022b0436000000000c0c04330000136b0dc0009c0000006d0000813d00012e970000003d000048f20000013d00002e7e0000013d00000026020000290000008002200039002200000002001d0000000000720435000000a0054000390000000005050433000013160650009c0000006d0000813d00000000064500190000001f046000390000130805000041000000000714004b0000000007000019000000000705401900001308044001970000130808100197000000000984004b000000000500a019000000000484013f000013080440009c000000000507c019000000000405004b0000006d0000613d0000000007060433000013160470009c00001b020000813d00012eb40000003d00004b790000013d00001b020000413d000013160850009c00001b020000813d000000400050043f000000250900002900000000007904350000130808000041000000000a060019000000000b00001900000000057b004b00002fec0000813d00012ec10000003d000046db0000013d0000130802200197000013080c10019700012ec50000003d000049c50000013d000013080220009c000000000d05c01900000000020d004b0000006d0000613d0000002005e00039000000000c0504330000131605c0009c00001b020000813d0000003f05c00039000000000535016f000000400d00043d00000000055d0019000000000fd5004b00001b020000413d000013160f50009c00001b020000813d000000400050043f000000000fcd0436000000400ee000390000000005ce0019000000000515004b0000006d0000213d000000200990003900000000050000190000000002c5004b00002ee50000813d0000000002f5001900000000045e001900000000040404330000000000420435000000200550003900002edd0000013d0000000002c5004b00002ee90000a13d0000000002cf001900000000000204350000000000d90435000000010bb0003900002ebd0000013d00000026020000290000006002200039001f00000002001d000000000072043500000080024000390000000002020433000013160520009c0000006d0000813d00000000064200190000001f026000390000130804000041000000000512004b0000000005000019000000000504401900001308022001970000130807100197000000000872004b000000000400a019000000000272013f000013080220009c000000000405c019000000000204004b0000006d0000613d0000000007060433000013160270009c00001b020000813d00012f080000003d00004b6b0000013d00001b020000413d000013160520009c00001b020000813d000000400020043f000000250900002900000000007904350000130808000041000000000a060019000000000b00001900000000027b004b00002fef0000813d00012f150000003d000046db0000013d0000130802200197000013080c10019700012f190000003d000049c50000013d000013080220009c000000000d05c01900000000020d004b0000006d0000613d0000002002e00039000000000c0204330000131602c0009c00001b020000813d0000003f02c00039000000000232016f000000400d00043d00000000022d00190000000005d2004b00001b020000413d000013160520009c00001b020000813d000000400020043f000000000fcd0436000000400ee000390000000002ce0019000000000212004b0000006d0000213d000000200990003900000000020000190000000005c2004b00002f390000813d0000000005f2001900000000042e001900000000040404330000000000450435000000200220003900002f310000013d0000000002c2004b00002f3d0000a13d0000000002cf001900000000000204350000000000d90435000000010bb0003900002f110000013d0000002601000029000000a00110003900002ff10000013d0000135f0650009c000030080000c13d00000000020304330000000034020434000013080500004100012f4a0000003d000048800000013d0000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d0000000003030433002613090030019b0000130a0330009c0000006d0000813d000000400400043d002500c40040003d00012f590000003d000044cd0000013d000013090910019700000040012000390000000001010433000000190b0000290000002302b0006b000030140000c13d00001373020000410000000000240435000000160200002900000000002a0435000000000098043500000000001704350000001e010000290000000000160435000000a00100003900000000001504350000000000030435000000400100043d002300000001001d009400260000002d00012f6f0000003d0000441d0000013d000000940440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002602000029000000040220008c000042e80000613d000042680000013d00001374040000410000002605000029000000000045043500000025040000290000000000430435000000190300002900000000003204350000002202000029000000000012043500000064015000390000001e020000290000000000210435000000400100043d002500000001001d006c00180000002d00012f8b0000003d0000441d0000013d0000006c0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001802000029000000040220008c000042e80000613d00012f970000003d00004b8a0000013d0000349a0000013d00000026020000290000006002200039002200000002001d000000000072043500000080024000390000000002020433000013160520009c0000006d0000813d00000000064200190000001f026000390000130804000041000000000512004b0000000005000019000000000504401900001308022001970000130807100197000000000872004b000000000400a019000000000272013f000013080220009c000000000405c019000000000204004b0000006d0000613d0000000007060433000013160270009c00001b020000813d00012fb40000003d00004b6b0000013d00001b020000413d000013160520009c00001b020000813d000000400020043f000000250900002900000000007904350000130808000041000000000a060019000000000b00001900000000027b004b000030310000813d00012fc10000003d000046db0000013d0000130802200197000013080c10019700012fc50000003d000049c50000013d000013080220009c000000000d05c01900000000020d004b0000006d0000613d0000002002e00039000000000c0204330000131602c0009c00001b020000813d0000003f02c00039000000000232016f000000400d00043d00000000022d00190000000005d2004b00001b020000413d000013160520009c00001b020000813d000000400020043f000000000fcd0436000000400ee000390000000002ce0019000000000212004b0000006d0000213d000000200990003900000000020000190000000005c2004b00002fe50000813d0000000005f2001900000000042e001900000000040404330000000000450435000000200220003900002fdd0000013d0000000002c2004b00002fe90000a13d0000000002cf001900000000000204350000000000d90435000000010bb0003900002fbd0000013d0000002601000029000000a001100039000030330000013d00000026010000290000008001100039000000250200002900000000002104350000001f010000290000000001010433001f00000001001d0000001f010000290000000021010434001b00000002001d000000010210008c0000304a0000c13d0000001a020000290000000023020434000000010330008c0000304a0000c13d000130010000003d00004b720000013d00001309033001980000304a0000c13d00000000010204330000137001100197000013890110008c000033020000413d000037620000013d0000134b0350009c0000318e0000c13d0000130904100197000000230140006b000042e80000613d000000400200043d0000000001000414000000040340008c0000319e0000c13d00000001020000390000000105000031000031ac0000013d00001372020000410000000000240435000000260200002900000000002a043500000019020000290000000000280435000000000097043500000000001604350000001e010000290001301f0000003d000046430000013d000000400100043d002500000001001d008000180000002d000130240000003d0000441d0000013d000000800440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001802000029000000040220008c000042e80000613d00000026020000290000002503000029000034990000013d000000260100002900000080011000390000002502000029000000000021043500000022010000290000000001010433002200000001001d00000022010000290000000021010434001b00000002001d000000010210008c000031ba0000c13d0000001a020000290000000023020434000000010330008c000031ba0000c13d000130430000003d00004b720000013d0000130903300198000031ba0000c13d00000000010204330000137001100197000013890110008c000034a00000413d000037620000013d0000002302000029001613090020019b0000001c02000029001a13090020019b0000001d02000029001913090020019b002500000000001d002600000000001d0000002203000029000000260110006b000032fe0000813d000130570000003d000045370000013d0000137002200197002500250020002e000041bf0000413d0000001e0400006b0000000004000019000030610000613d0000001e542000b90000001e654000fa000000000225004b000041ad0000c13d000130630000003d00004a7f0000013d002200000005001d000000000423004b0000000003028019000000000203004b000031450000613d0001306a0000003d00004a8b0000013d0000001f050000290000000005050433000000260550006b00001b020000813d00000000010104330000000001010433000000000504043300000000560504340000131706600197000013640760009c000030920000c13d000000000205043300000000450204340000003f0650008c00001308080000410000000006000019000000000608201900001308055001970001307e0000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000004040433001d13090040019b0000130a0440009c0000006d0000813d000000010330008c000042340000c13d0001308a0000003d000045300000013d00001309011001970001308d0000003d000046a50000013d000030d40000c13d0000137807000041000130910000003d000044870000013d000030f80000013d0000134a0760009c000030da0000c13d000000000205043300000000240204340000001f0540008c00001308070000410000000005000019000000000507201900001308044001970001309d0000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000002020433001d13090020019b0000130a0220009c0000006d0000813d000130a70000003d000049ca0000013d00001309011001970000001a06000029000000230560006b0000310b0000c13d0000137505000041000130ae0000003d0000490a0000013d0028001d0000002d000130b10000003d0000441d0000013d000000280440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001d02000029000000040220008c000030c10000613d0000001c03000029000130be0000003d000045ec0000013d000001560000613d000000400100043d001c00000001001d00000001010000310000001f0210008c0000130805000041000000000200001900000000020520190000130803100197000130c90000003d000047250000013d000013080330009c000130cc0000003d000044d40000013d0000006d0000613d0000001c01000029000130d00000003d0000445d0000013d0000006d0000c13d000000000101004b000031450000c13d000034800000013d000013770700004100000000007304350000001d07000029000130d90000003d000045f30000013d0000312f0000013d0000135f0760009c000031200000c13d000000000205043300000000450204340000003f0650008c0000130808000041000000000600001900000000060820190000130805500197000130e50000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000004040433001d13090040019b0000130a0440009c0000006d0000813d000000400500043d001c00c40050003d000130f10000003d000045890000013d000013090a100197000130f40000003d000045b90000013d0000312c0000c13d0000137302000041000130f80000003d000044c30000013d000000400100043d001700000001001d0082001d0000002d000130fd0000003d0000441d0000013d000000820440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001d02000029000000040220008c000031450000613d00000017030000290000001c043000690000001d02000029000031420000013d00001374050000410000001c060000290001310f0000003d000044b70000013d005a00190000002d000131120000003d0000441d0000013d0000005a0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000031450000613d0000001d030000290000001c023000690000008404200039000031410000013d0000134b0560009c0000314a0000c13d0000130904100197000000230140006b000031450000613d000000400200043d0000000001000414000000040540008c000031710000c13d000000010200003900000001010000310000317e0000013d00001372020000410001312f0000003d0000478b0000013d000000400100043d001d00000001001d006e00190000002d000131340000003d0000441d0000013d0000006e0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000031450000613d0000001c020000290000001d0300002900000000043200490000001902000029000131440000003d0000452b0000013d000001560000613d0000001f0100002900000000010104330000002602000029002600010020003d000030520000013d000000400300043d00001371050000410001314e0000003d0000444d0000013d0000131704400197000131510000003d0000461e0000013d0000001d0650006c000031570000813d0000001c06500029000131560000003d000045260000013d000031510000013d0000001d0450006c0000315c0000a13d0000001d050000290000001c04500029000000000004043500000000020204330000130901100197000131600000003d000044430000013d004400190000002d000131630000003d0000441d0000013d000000440440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000031450000613d0000001d02000029000131700000003d000045a50000013d000031400000013d000013000510009c00001300060000410000000001068019000013000520009c0000000002068019000131780000003d0000460e0000013d0000130b011001c700008009020000390001317c0000003d000044570000013d000113000010019d0000130001100197000000000301004b0000318b0000613d000131820000003d000044290000013d000031870000613d0000000006000019000131860000003d000044210000013d000031840000413d0000001f011001900000318b0000613d0001318b0000003d0000440f0000013d000000000102004b000031450000c13d0000435d0000013d000000400300043d0000137105000041000000000053043500000004053000390000002206000029000131950000003d000044a00000013d0000131704400197000131980000003d000044e70000013d000000260650006c000034810000813d00000025065000290001319d0000003d000045260000013d000031980000013d0000130003000041000013000510009c0000000001038019000013000520009c0000000002038019000131a50000003d0000460e0000013d0000130b011001c700008009020000390000001e03000029000131aa0000003d000044570000013d000113000010019d0000130005100197000000000105004b000042c80000613d000131b00000003d000044ac0000013d000031b50000613d0000000006000019000131b40000003d000044210000013d000031b20000413d000000000601004b000042c80000613d000131b90000003d0000440f0000013d000042c80000013d0000002302000029001613090020019b0000001c02000029001a13090020019b0000001d02000029001913090020019b002500000000001d002600000000001d0000001f03000029000000260110006b0000349c0000813d000131c70000003d000045370000013d0000137002200197002500250020002e000041bf0000413d0000001e0400006b0000000004000019000031d10000613d0000001e542000b90000001e654000fa000000000225004b000041ad0000c13d000131d30000003d00004a7f0000013d001f00000005001d000000000423004b0000000003028019000000000203004b000032b50000613d000131da0000003d00004a8b0000013d00000022050000290000000005050433000000260550006b00001b020000813d00000000010104330000000001010433000000000504043300000000560504340000131706600197000013640760009c000032020000c13d000000000205043300000000450204340000003f0650008c0000130808000041000000000600001900000000060820190000130805500197000131ee0000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000004040433001d13090040019b0000130a0440009c0000006d0000813d000000010330008c000042340000c13d000131fa0000003d000045300000013d0000130901100197000131fd0000003d000046a50000013d000032440000c13d0000137807000041000132010000003d000044870000013d000032680000013d0000134a0760009c0000324a0000c13d000000000205043300000000240204340000001f0540008c00001308070000410000000005000019000000000507201900001308044001970001320d0000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000002020433001d13090020019b0000130a0220009c0000006d0000813d000132170000003d000049ca0000013d00001309011001970000001a06000029000000230560006b0000327b0000c13d00001375050000410001321e0000003d0000490a0000013d002f001d0000002d000132210000003d0000441d0000013d0000002f0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001d02000029000000040220008c000032310000613d0000001c030000290001322e0000003d000045ec0000013d000001560000613d000000400100043d001c00000001001d00000001010000310000001f0210008c0000130805000041000000000200001900000000020520190000130803100197000132390000003d000047250000013d000013080330009c0001323c0000003d000044d40000013d0000006d0000613d0000001c01000029000132400000003d0000445d0000013d0000006d0000c13d000000000101004b000032b50000c13d0000361e0000013d000013770700004100000000007304350000001d07000029000132490000003d000045f30000013d0000329f0000013d0000135f0760009c000032900000c13d000000000205043300000000450204340000003f0650008c0000130808000041000000000600001900000000060820190000130805500197000132550000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000004040433001d13090040019b0000130a0440009c0000006d0000813d000000400500043d001c00c40050003d000132610000003d000045890000013d000013090a100197000132640000003d000045b90000013d0000329c0000c13d0000137302000041000132680000003d000044c30000013d000000400100043d001700000001001d0089001d0000002d0001326d0000003d0000441d0000013d000000890440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001d02000029000000040220008c000032b50000613d00000017030000290000001c043000690000001d02000029000032b20000013d00001374050000410000001c060000290001327f0000003d000044b70000013d006100190000002d000132820000003d0000441d0000013d000000610440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000032b50000613d0000001d030000290000001c023000690000008404200039000032b10000013d0000134b0560009c000032ba0000c13d0000130904100197000000230140006b000032b50000613d000000400200043d0000000001000414000000040540008c000032e10000c13d00000001020000390000000101000031000032ee0000013d00001372020000410001329f0000003d0000478b0000013d000000400100043d001d00000001001d007500190000002d000132a40000003d0000441d0000013d000000750440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000032b50000613d0000001c020000290000001d0300002900000000043200490000001902000029000132b40000003d0000452b0000013d000001560000613d000000220100002900000000010104330000002602000029002600010020003d000031c20000013d000000400300043d0000137105000041000132be0000003d0000444d0000013d0000131704400197000132c10000003d0000461e0000013d0000001d0650006c000032c70000813d0000001c06500029000132c60000003d000045260000013d000032c10000013d0000001d0450006c000032cc0000a13d0000001d050000290000001c04500029000000000004043500000000020204330000130901100197000132d00000003d000044430000013d004b00190000002d000132d30000003d0000441d0000013d0000004b0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000032b50000613d0000001d02000029000132e00000003d000045a50000013d000032b00000013d000013000510009c00001300060000410000000001068019000013000520009c0000000002068019000132e80000003d0000460e0000013d0000130b011001c70000800902000039000132ec0000003d000044570000013d000113000010019d0000130001100197000000000301004b000032fb0000613d000132f20000003d000044290000013d000032f70000613d0000000006000019000132f60000003d000044210000013d000032f40000413d0000001f01100190000032fb0000613d000132fb0000003d0000440f0000013d000000000102004b000032b50000c13d0000435d0000013d0000002501000029000013890110008c002200000003001d000037620000813d0000000a010000290000000001010433001e00000001001d0000000021010434001b00000002001d000000010210008c0000361f0000c13d000000090200002900000000020204330000000023020434000000010330008c0000361f0000c13d000133100000003d00004b950000013d00001309022001980000361f0000c13d000133140000003d0000477d0000013d000000090200002900000000020204330000000023020434000000000303004b00001b020000613d0000001e030000290000000003030433000000000303004b00001b020000613d00000000020204330000000002020433000013090220019700000000002104350000000a0100002900000000010104330000000012010434000000000202004b00001b020000613d000000090200002900000000020204330000000023020434000000000303004b00001b020000613d0000001e030000290000000003030433000000000303004b00001b020000613d000133310000003d00004a930000013d00001370011001970000001b020000290000000002020433000000200220003900000000001204350000002301000029001613090010019b00000012010000290000000001010433001a13090010019b0000000f010000290000000001010433001913090010019b0000001301000029000133410000003d00004ae70000013d001f00220000002d0000001e010000290000000001010433000000260110006b00003b570000813d000133480000003d000045370000013d0000137002200197002500250020002e000041bf0000413d0000001d0300006b0000000003000019000033510000613d000133500000003d00004a6b0000013d000041ad0000c13d000027103230011a0000001f042000690000001f0340006c00000000030000190000000103002039000000000303004b000000000400c019002200000004001d0000001f0320006b00000000050200190000001f05004029000000000b050019000000000205004b000034380000613d000133610000003d000044dc0000013d00001b020000813d000133640000003d000048570000013d0000131705500197000013640650009c000033830000c13d000133690000003d000047a70000013d00001308070000410000000005000019000000000507201900001308044001970001336f0000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000003030433001f13090030019b0000130a0330009c0000006d0000813d0000000103b0008c000042340000c13d0001337b0000003d000045300000013d00001309011001970001337e0000003d000046a50000013d000033c70000c13d0000137807000041000133820000003d000044870000013d000033ea0000013d0000134a0650009c000033cd0000c13d000133870000003d00004a870000013d00001308060000410000000004000019000000000406201900001308033001970001338d0000003d00004a530000013d000013080330009c000000000504c019000000000305004b0000006d0000613d0000000002020433001f13090020019b0000130a0220009c0000006d0000813d000133970000003d000046d50000013d00001309011001970000001a05000029000000230450006b000033fd0000c13d00001375040000410001339e0000003d000046030000013d0029001f0000002d000133a10000003d0000441d0000013d000000290440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001f02000029000000040220008c000033b40000613d0000001c03000029000000170430006900000020060000390000001f02000029000133b10000003d0000460a0000013d000001560000613d000000400100043d001c00000001001d00000001010000310000001f0210008c0000130805000041000000000200001900000000020520190000130803100197000133bc0000003d000047250000013d000013080330009c000133bf0000003d000044d40000013d0000006d0000613d0000001c01000029000133c30000003d0000445d0000013d0000006d0000c13d000000000101004b000034380000c13d000037610000013d000013770700004100000000007304350000001f07000029000133cc0000003d000045f30000013d000034220000013d0000135f0650009c000034110000c13d000133d10000003d000047a70000013d0000130807000041000000000500001900000000050720190000130804400197000133d70000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000003030433001f13090030019b0000130a0330009c0000006d0000813d000000400400043d001c00c40040003d000133e30000003d000044cd0000013d0000130909100197000133e60000003d000045b90000013d0000341d0000c13d0000137302000041000133ea0000003d000045170000013d000000400100043d001700000001001d0083001f0000002d000133ef0000003d0000441d0000013d000000830440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001f02000029000000040220008c000034380000613d00000017030000290000001c043000690000001f02000029000034350000013d0000137404000041000134000000003d000048450000013d005b00190000002d000134030000003d0000441d0000013d0000005b0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000034380000613d0000001f030000290000001c023000690000008404200039000034340000013d0000134b0350009c0000343b0000c13d0000130904100197000000230140006b000034380000613d000000400200043d0000000001000414000000040340008c000034620000c13d00000001010000310000000802000029000034700000013d000013720200004100000000002404350000001f02000029000134220000003d000046120000013d000000400100043d001f00000001001d006f00190000002d000134270000003d0000441d0000013d0000006f0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000034380000613d0000001c020000290000001f0300002900000000043200490000001902000029000134370000003d0000452b0000013d000001560000613d0000002601000029002600010010003d000033410000013d000000400300043d00001371050000410001343f0000003d0000444d0000013d0000131704400197000134420000003d000048940000013d0000001f0650006c000034480000813d0000001c06500029000134470000003d000045260000013d000034420000013d0000001f0450006c0000344d0000a13d0000001f050000290000001c04500029000000000004043500000000020204330000130901100197000134510000003d000044430000013d004500190000002d000134540000003d0000441d0000013d000000450440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000034380000613d0000001f02000029000134610000003d000045a50000013d000034330000013d000013000310009c00001300050000410000000001058019000013000320009c0000000002058019000134690000003d0000460e0000013d0000130b011001c7000080090200003900000000030b00190001346e0000003d000044570000013d000113000010019d0000130001100197000000000301004b0000347d0000613d000134740000003d000044290000013d000034790000613d0000000006000019000134780000003d000044210000013d000034760000413d0000001f011001900000347d0000613d0001347d0000003d0000440f0000013d000000000102004b000034380000c13d0000435d0000013d0000422e0000013d000000260450006c000034850000a13d000134850000003d00004b1c0000013d00000000020204330000130901100197000134890000003d000049b30000013d002300000001001d005600180000002d0001348d0000003d0000441d0000013d000000560440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001802000029000000040220008c000042e80000613d000134990000003d00004b020000013d00000000043200490000001802000029000042e50000013d0000002501000029000013890110008c001f00000003001d000037620000813d00000009010000290000000001010433001e00000001001d0000000021010434001b00000002001d000000010210008c000037660000c13d0000000a0200002900000000020204330000000023020434000000010330008c000037660000c13d000134ae0000003d00004b950000013d0000130902200198000037660000c13d000134b20000003d0000477d0000013d0000000a0200002900000000020204330000000023020434000000000303004b00001b020000613d0000001e030000290000000003030433000000000303004b00001b020000613d0000000002020433000000000202043300001309022001970000000000210435000000090100002900000000010104330000000012010434000000000202004b00001b020000613d0000000a0200002900000000020204330000000023020434000000000303004b00001b020000613d0000001e030000290000000003030433000000000303004b00001b020000613d000134cf0000003d00004a930000013d00001370011001970000001b020000290000000002020433000000200220003900000000001204350000002301000029001613090010019b0000000d010000290000000001010433001a13090010019b0000000e010000290000000001010433001913090010019b0000001401000029000134df0000003d00004ae70000013d0022001f0000002d0000001e010000290000000001010433000000260110006b00003c9e0000813d000134e60000003d000045370000013d0000137002200197002500250020002e000041bf0000413d0000001d0300006b0000000003000019000034ef0000613d000134ee0000003d00004a6b0000013d000041ad0000c13d000027103230011a0000002204200069000000220340006c00000000030000190000000103002039000000000303004b000000000400c019001f00000004001d000000220320006b00000000050200190000002205004029000000000b050019000000000205004b000035d60000613d000134ff0000003d000044dc0000013d00001b020000813d000135020000003d000048570000013d0000131705500197000013640650009c000035210000c13d000135070000003d000047a70000013d00001308070000410000000005000019000000000507201900001308044001970001350d0000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000003030433002213090030019b0000130a0330009c0000006d0000813d0000000103b0008c000042340000c13d000135190000003d000045300000013d00001309011001970001351c0000003d000046a50000013d000035650000c13d0000137807000041000135200000003d000044870000013d000035880000013d0000134a0650009c0000356b0000c13d000135250000003d00004a870000013d00001308060000410000000004000019000000000406201900001308033001970001352b0000003d00004a530000013d000013080330009c000000000504c019000000000305004b0000006d0000613d0000000002020433002213090020019b0000130a0220009c0000006d0000813d000135350000003d000046d50000013d00001309011001970000001a05000029000000230450006b0000359b0000c13d00001375040000410001353c0000003d000046030000013d003000220000002d0001353f0000003d0000441d0000013d000000300440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002202000029000000040220008c000035520000613d0000001c030000290000001704300069000000200600003900000022020000290001354f0000003d0000460a0000013d000001560000613d000000400100043d001c00000001001d00000001010000310000001f0210008c00001308050000410000000002000019000000000205201900001308031001970001355a0000003d000047250000013d000013080330009c0001355d0000003d000044d40000013d0000006d0000613d0000001c01000029000135610000003d0000445d0000013d0000006d0000c13d000000000101004b000035d60000c13d000038a80000013d0000137707000041000000000073043500000022070000290001356a0000003d000045f30000013d000035c00000013d0000135f0650009c000035af0000c13d0001356f0000003d000047a70000013d0000130807000041000000000500001900000000050720190000130804400197000135750000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000003030433002213090030019b0000130a0330009c0000006d0000813d000000400400043d001c00c40040003d000135810000003d000044cd0000013d0000130909100197000135840000003d000045b90000013d000035bb0000c13d0000137302000041000135880000003d000045170000013d000000400100043d001700000001001d008a00220000002d0001358d0000003d0000441d0000013d0000008a0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002202000029000000040220008c000035d60000613d00000017030000290000001c043000690000002202000029000035d30000013d00001374040000410001359e0000003d0000482b0000013d006200190000002d000135a10000003d0000441d0000013d000000620440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000035d60000613d00000022030000290000001c023000690000008404200039000035d20000013d0000134b0350009c000035d90000c13d0000130904100197000000230140006b000035d60000613d000000400200043d0000000001000414000000040340008c000036000000c13d000000010100003100000008020000290000360e0000013d000013720200004100000000002404350000002202000029000135c00000003d000046120000013d000000400100043d002200000001001d007600190000002d000135c50000003d0000441d0000013d000000760440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000035d60000613d0000001c02000029000000220300002900000000043200490000001902000029000135d50000003d0000452b0000013d000001560000613d0000002601000029002600010010003d000034df0000013d000000400300043d0000137105000041000135dd0000003d0000444d0000013d0000131704400197000135e00000003d000048a00000013d000000220650006c000035e60000813d0000001c06500029000135e50000003d000045260000013d000035e00000013d000000220450006c000035eb0000a13d00000022050000290000001c04500029000000000004043500000000020204330000130901100197000135ef0000003d000044430000013d004c00190000002d000135f20000003d0000441d0000013d0000004c0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000035d60000613d0000002202000029000135ff0000003d000045a50000013d000035d10000013d000013000310009c00001300050000410000000001058019000013000320009c0000000002058019000136070000003d0000460e0000013d0000130b011001c7000080090200003900000000030b00190001360c0000003d000044570000013d000113000010019d0000130001100197000000000301004b0000361b0000613d000136120000003d000044290000013d000036170000613d0000000006000019000136160000003d000044210000013d000036140000413d0000001f011001900000361b0000613d0001361b0000003d0000440f0000013d000000000102004b000035d60000c13d0000435d0000013d0000422e0000013d0000002302000029001613090020019b00000012020000290000000002020433001a13090020019b0000000f020000290000000002020433001913090020019b000000130200002900000000020204330000000023020434001800000003001d0000000002020433001d00000002001d001f00000000001d002600000000001d002500220000002d000000260110006b000038a90000813d000136340000003d000045370000013d0000137002200197001f001f0020002e000041bf0000413d0000001d0300006b00000000030000190000363d0000613d0001363c0000003d00004a6b0000013d000041ad0000c13d0001363f0000003d00004a630000013d002200000004001d000000250320006b00000000050200190000002505004029000000000b050019000000000205004b000037090000613d000136480000003d000044dc0000013d00001b020000813d0001364b0000003d000048570000013d0000131705500197000013640650009c0000367c0000c13d000136500000003d000047a70000013d0000130807000041000000000500001900000000050720190000130804400197000136560000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000003030433002513090030019b0000130a0330009c0000006d0000813d0000000103b0008c000042340000c13d000136620000003d000045300000013d0000130901100197000136650000003d000046a50000013d000036be0000c13d0000137807000041000136690000003d000044870000013d000000400100043d001700000001001d008400250000002d0001366e0000003d0000441d0000013d000000840440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002502000029000000040220008c000037090000613d00000017030000290000001c043000690000002502000029000037060000013d0000134a0650009c000036d40000c13d000136800000003d00004a870000013d0000130806000041000000000400001900000000040620190000130803300197000136860000003d00004a530000013d000013080330009c000000000504c019000000000305004b0000006d0000613d0000000002020433002513090020019b0000130a0220009c0000006d0000813d000136900000003d000046d50000013d00001309011001970000001a05000029000000230450006b000036f20000c13d0000137504000041000136970000003d000046030000013d002a00250000002d0001369a0000003d0000441d0000013d0000002a0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002502000029000000040220008c000036ab0000613d0000001c030000290000001704300069000136a80000003d000045900000013d000001560000613d000000400100043d001c00000001001d00000001010000310000001f0210008c0000130805000041000000000200001900000000020520190000130803100197000136b30000003d000047250000013d000013080330009c000136b60000003d000044d40000013d0000006d0000613d0000001c01000029000136ba0000003d0000445d0000013d0000006d0000c13d000000000101004b000037090000c13d00003a040000013d0000137707000041000136c10000003d000049490000013d000000400100043d001c00000001001d007000190000002d000136c60000003d0000441d0000013d000000700440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000037090000613d00000025020000290000001c030000290000000004320049000037050000013d0000135f0650009c0000370c0000c13d000136d80000003d000047a70000013d0000130807000041000000000500001900000000050720190000130804400197000136de0000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000003030433002513090030019b0000130a0330009c0000006d0000813d000000400400043d001c00c40040003d000136ea0000003d000044cd0000013d0000130909100197000136ed0000003d000045b90000013d000037180000c13d0000137302000041000136f10000003d000045170000013d000036690000013d0000137404000041000136f50000003d000048380000013d005c00190000002d000136f80000003d0000441d0000013d0000005c0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000037090000613d00000025030000290000001c0230006900000084042000390000001902000029000137080000003d0000452b0000013d000001560000613d0001370b0000003d000048520000013d0000362f0000013d0000134b0350009c0000371c0000c13d0000130904100197000000230140006b000037090000613d000000400200043d0000000001000414000000040340008c000037430000c13d00000001020000390000000101000031000037510000013d00001372020000410001371b0000003d000047b90000013d000036c10000013d000000400300043d0000137105000041000137200000003d0000444d0000013d0000131704400197000137230000003d000048880000013d000000250650006c000037290000813d0000001c06500029000137280000003d000045260000013d000037230000013d000000250450006c0000372e0000a13d00000025050000290000001c04500029000000000004043500000000020204330000130901100197000137320000003d000044430000013d004600190000002d000137350000003d0000441d0000013d000000460440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000037090000613d0000002502000029000137420000003d000045a50000013d000036d20000013d000013000310009c00001300050000410000000001058019000013000320009c00000000020580190001374a0000003d0000460e0000013d0000130b011001c7000080090200003900000000030b00190001374f0000003d000044570000013d000113000010019d0000130001100197000000000301004b0000375e0000613d000137550000003d000044290000013d0000375a0000613d0000000006000019000137590000003d000044210000013d000037570000413d0000001f011001900000375e0000613d0001375e0000003d0000440f0000013d000000000102004b000037090000c13d0000435d0000013d0000422e0000013d000000400200043d00000044012000390000137e03000041000025770000013d0000002302000029001613090020019b0000000d020000290000000002020433001a13090020019b0000000e020000290000000002020433001913090020019b000000140200002900000000020204330000000023020434001800000003001d0000000002020433001d00000002001d002200000000001d002600000000001d0025001f0000002d000000260110006b00003a050000813d0001377b0000003d000045370000013d0000137002200197002200220020002e000041bf0000413d0000001d0300006b0000000003000019000037840000613d000137830000003d00004a6b0000013d000041ad0000c13d000137860000003d00004a630000013d001f00000004001d000000250320006b00000000050200190000002505004029000000000b050019000000000205004b000038500000613d0001378f0000003d000044dc0000013d00001b020000813d000137920000003d000048570000013d0000131705500197000013640650009c000037c30000c13d000137970000003d000047a70000013d00001308070000410000000005000019000000000507201900001308044001970001379d0000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000003030433002513090030019b0000130a0330009c0000006d0000813d0000000103b0008c000042340000c13d000137a90000003d000045300000013d0000130901100197000137ac0000003d000046a50000013d000038050000c13d0000137807000041000137b00000003d000044870000013d000000400100043d001700000001001d008b00250000002d000137b50000003d0000441d0000013d0000008b0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002502000029000000040220008c000038500000613d00000017030000290000001c0430006900000025020000290000384d0000013d0000134a0650009c0000381b0000c13d000137c70000003d00004a870000013d0000130806000041000000000400001900000000040620190000130803300197000137cd0000003d00004a530000013d000013080330009c000000000504c019000000000305004b0000006d0000613d0000000002020433002513090020019b0000130a0220009c0000006d0000813d000137d70000003d000046d50000013d00001309011001970000001a05000029000000230450006b000038390000c13d0000137504000041000137de0000003d000046030000013d003100250000002d000137e10000003d0000441d0000013d000000310440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002502000029000000040220008c000037f20000613d0000001c030000290000001704300069000137ef0000003d000045900000013d000001560000613d000000400100043d001c00000001001d00000001010000310000001f0210008c0000130805000041000000000200001900000000020520190000130803100197000137fa0000003d000047250000013d000013080330009c000137fd0000003d000044d40000013d0000006d0000613d0000001c01000029000138010000003d0000445d0000013d0000006d0000c13d000000000101004b000038500000c13d00003b560000013d0000137707000041000138080000003d000049490000013d000000400100043d001c00000001001d007700190000002d0001380d0000003d0000441d0000013d000000770440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000038500000613d00000025020000290000001c0300002900000000043200490000384c0000013d0000135f0650009c000038530000c13d0001381f0000003d000047a70000013d0000130807000041000000000500001900000000050720190000130804400197000138250000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000003030433002513090030019b0000130a0330009c0000006d0000813d000000400400043d001c00c40040003d000138310000003d000044cd0000013d0000130909100197000138340000003d000045b90000013d0000385f0000c13d0000137302000041000138380000003d000045170000013d000037b00000013d00001374040000410001383c0000003d000048380000013d006300190000002d0001383f0000003d0000441d0000013d000000630440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000038500000613d00000025030000290000001c02300069000000840420003900000019020000290001384f0000003d0000452b0000013d000001560000613d000138520000003d000048520000013d000037760000013d0000134b0350009c000038630000c13d0000130904100197000000230140006b000038500000613d000000400200043d0000000001000414000000040340008c0000388a0000c13d00000001020000390000000101000031000038980000013d0000137202000041000138620000003d000047b90000013d000038080000013d000000400300043d0000137105000041000138670000003d0000444d0000013d00001317044001970001386a0000003d000048880000013d000000250650006c000038700000813d0000001c065000290001386f0000003d000045260000013d0000386a0000013d000000250450006c000038750000a13d00000025050000290000001c04500029000000000004043500000000020204330000130901100197000138790000003d000044430000013d004d00190000002d0001387c0000003d0000441d0000013d0000004d0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000038500000613d0000002502000029000138890000003d000045a50000013d000038190000013d000013000310009c00001300050000410000000001058019000013000320009c0000000002058019000138910000003d0000460e0000013d0000130b011001c7000080090200003900000000030b0019000138960000003d000044570000013d000113000010019d0000130001100197000000000301004b000038a50000613d0001389c0000003d000044290000013d000038a10000613d0000000006000019000138a00000003d000044210000013d0000389e0000413d0000001f01100190000038a50000613d000138a50000003d0000440f0000013d000000000102004b000038500000c13d0000435d0000013d0000422e0000013d00000012010000290000000001010433001a13090010019b0000000f010000290000000001010433001913090010019b00000009010000290000000001010433001e00000001001d001b00200010003d000000130100002900000000010104330000000012010434001800000002001d0000000001010433001d00000001001d002200000000001d002600000000001d001f00250000002d0000001e010000290000000001010433000000260110006b00003b570000813d000138c20000003d000045370000013d0000137002200197002200220020002e000041bf0000413d0000001d0300006b0000000003000019000038cb0000613d000138ca0000003d00004a6b0000013d000041ad0000c13d000027103230011a0000001f052000690000001f0350006c00000000030000190000000103002039000000000303004b000000000500c019002500000005001d0000001f0320006b00000000040200190000001f04004029000000000b040019000000000204004b000039bc0000613d000138db0000003d000044dc0000013d00001b020000813d000138de0000003d000048570000013d0000131705500197000013640650009c000038fd0000c13d000138e30000003d000047a70000013d0000130807000041000000000500001900000000050720190000130804400197000138e90000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000003030433001f13090030019b0000130a0330009c0000006d0000813d0000000103b0008c000042340000c13d000138f50000003d000045300000013d0000130901100197000138f80000003d000046a50000013d000039410000c13d0000137807000041000138fc0000003d000044870000013d000039650000013d0000134a0650009c000039480000c13d000139010000003d00004a870000013d0000130806000041000000000400001900000000040620190000130803300197000139070000003d00004a530000013d000013080330009c000000000504c019000000000305004b0000006d0000613d0000000002020433001f13090020019b0000130a0220009c0000006d0000813d000139110000003d000046d50000013d00001309011001970000001a05000029000000230450006b000039780000c13d0000137504000041000139180000003d000046030000013d002b001f0000002d0001391b0000003d0000441d0000013d0000002b0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001f02000029000000040220008c0000392e0000613d0000001c03000029000000170430006900000020060000390000001f020000290001392b0000003d0000460a0000013d000001560000613d000000400100043d001c00000001001d00000001010000310000001f0210008c0000130805000041000000000200001900000000020520190000130803100197000139360000003d000047250000013d000013080330009c000139390000003d000044d40000013d0000006d0000613d0000001c010000290001393d0000003d0000445d0000013d0000006d0000c13d000000000101004b000039bc0000c13d00003c9d0000013d000013770700004100000000007304350000001f07000029000139460000003d00004b420000013d001f00840030003d000039a60000013d0000135f0650009c0000398c0000c13d0001394c0000003d000047a70000013d0000130807000041000000000500001900000000050720190000130804400197000139520000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000003030433001f13090030019b0000130a0330009c0000006d0000813d000000400400043d001c00c40040003d0001395e0000003d000044cd0000013d0000130909100197000139610000003d000045b90000013d000039980000c13d0000137302000041000139650000003d000045170000013d000000400100043d001700000001001d0085001f0000002d0001396a0000003d0000441d0000013d000000850440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001f02000029000000040220008c000039bc0000613d00000017030000290000001c043000690000001f02000029000039b90000013d00001374040000410001397b0000003d000048450000013d005d00190000002d0001397e0000003d0000441d0000013d0000005d0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000039bc0000613d0000001f030000290000001c023000690000008404200039000039b80000013d0000134b0350009c000039bf0000c13d0000130904100197000000230140006b000039bc0000613d000000400200043d0000000001000414000000040340008c000039e60000c13d00000001020000390000000101000031000039f40000013d000013720200004100000000002404350000001f0200002900000000002a04350000001a020000290000000000280435000000000097043500000000001604350000000000b50435000000c00100003900000000001304350000001c010000290000000000010435001f00e40040003d000000400100043d001c00000001001d007100190000002d000139ab0000003d0000441d0000013d000000710440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000039bc0000613d0000001f020000290000001c0300002900000000043200490000001902000029000139bb0000003d0000452b0000013d000001560000613d0000002601000029002600010010003d000038bb0000013d000000400300043d0000137105000041000139c30000003d0000444d0000013d0000131704400197000139c60000003d000048940000013d0000001f0650006c000039cc0000813d0000001c06500029000139cb0000003d000045260000013d000039c60000013d0000001f0450006c000039d10000a13d0000001f050000290000001c04500029000000000004043500000000020204330000130901100197000139d50000003d000044430000013d004700190000002d000139d80000003d0000441d0000013d000000470440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000039bc0000613d0000001f02000029000139e50000003d000045a50000013d000039b70000013d000013000310009c00001300050000410000000001058019000013000320009c0000000002058019000139ed0000003d0000460e0000013d0000130b011001c7000080090200003900000000030b0019000139f20000003d000044570000013d000113000010019d0000130001100197000000000301004b00003a010000613d000139f80000003d000044290000013d000039fd0000613d0000000006000019000139fc0000003d000044210000013d000039fa0000413d0000001f0110019000003a010000613d00013a010000003d0000440f0000013d000000000102004b000039bc0000c13d0000435d0000013d0000422e0000013d0000000d010000290000000001010433001a13090010019b0000000e010000290000000001010433001913090010019b0000000a010000290000000001010433001e00000001001d001b00200010003d000000140100002900000000010104330000000012010434001800000002001d0000000001010433001d00000001001d001f00000000001d002600000000001d002200250000002d0000001e010000290000000001010433000000260110006b00003c9e0000813d00013a1e0000003d000045370000013d0000137002200197001f001f0020002e000041bf0000413d0000001d0300006b000000000300001900003a270000613d00013a260000003d00004a6b0000013d000041ad0000c13d000027103230011a0000002205200069000000220350006c00000000030000190000000103002039000000000303004b000000000500c019002500000005001d000000220320006b00000000040200190000002204004029000000000b040019000000000204004b00003b0e0000613d00013a370000003d000044dc0000013d00001b020000813d00013a3a0000003d000048570000013d0000131705500197000013640650009c00003a590000c13d00013a3f0000003d000047a70000013d000013080700004100000000050000190000000005072019000013080440019700013a450000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000003030433002213090030019b0000130a0330009c0000006d0000813d0000000103b0008c000042340000c13d00013a510000003d000045300000013d000013090110019700013a540000003d000046a50000013d00003a9d0000c13d000013780700004100013a580000003d000044870000013d00003ac00000013d0000134a0650009c00003aa30000c13d00013a5d0000003d00004a870000013d000013080600004100000000040000190000000004062019000013080330019700013a630000003d00004a530000013d000013080330009c000000000504c019000000000305004b0000006d0000613d0000000002020433002213090020019b0000130a0220009c0000006d0000813d00013a6d0000003d000046d50000013d00001309011001970000001a05000029000000230450006b00003ad30000c13d000013750400004100013a740000003d000046030000013d003200220000002d00013a770000003d0000441d0000013d000000320440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002202000029000000040220008c00003a8a0000613d0000001c0300002900000017043000690000002006000039000000220200002900013a870000003d0000460a0000013d000001560000613d000000400100043d001c00000001001d00000001010000310000001f0210008c000013080500004100000000020000190000000002052019000013080310019700013a920000003d000047250000013d000013080330009c00013a950000003d000044d40000013d0000006d0000613d0000001c0100002900013a990000003d0000445d0000013d0000006d0000c13d000000000101004b00003b0e0000c13d00003de40000013d00001377070000410000000000730435000000220700002900013aa20000003d000045f30000013d00003af80000013d0000135f0650009c00003ae70000c13d00013aa70000003d000047a70000013d000013080700004100000000050000190000000005072019000013080440019700013aad0000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000003030433002213090030019b0000130a0330009c0000006d0000813d000000400400043d001c00c40040003d00013ab90000003d000044cd0000013d000013090910019700013abc0000003d000045b90000013d00003af30000c13d000013730200004100013ac00000003d000045170000013d000000400100043d001700000001001d008c00220000002d00013ac50000003d0000441d0000013d0000008c0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002202000029000000040220008c00003b0e0000613d00000017030000290000001c04300069000000220200002900003b0b0000013d000013740400004100013ad60000003d0000482b0000013d006400190000002d00013ad90000003d0000441d0000013d000000640440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c00003b0e0000613d00000022030000290000001c02300069000000840420003900003b0a0000013d0000134b0350009c00003b110000c13d0000130904100197000000230140006b00003b0e0000613d000000400200043d0000000001000414000000040340008c00003b380000c13d0000000102000039000000010100003100003b460000013d00001372020000410000000000240435000000220200002900013af80000003d000046120000013d000000400100043d002200000001001d007800190000002d00013afd0000003d0000441d0000013d000000780440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c00003b0e0000613d0000001c0200002900000022030000290000000004320049000000190200002900013b0d0000003d0000452b0000013d000001560000613d0000002601000029002600010010003d00003a170000013d000000400300043d000013710500004100013b150000003d0000444d0000013d000013170440019700013b180000003d000048a00000013d000000220650006c00003b1e0000813d0000001c0650002900013b1d0000003d000045260000013d00003b180000013d000000220450006c00003b230000a13d00000022050000290000001c0450002900000000000404350000000002020433000013090110019700013b270000003d000044430000013d004e00190000002d00013b2a0000003d0000441d0000013d0000004e0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c00003b0e0000613d000000220200002900013b370000003d000045a50000013d00003b090000013d000013000310009c00001300050000410000000001058019000013000320009c000000000205801900013b3f0000003d0000460e0000013d0000130b011001c7000080090200003900000000030b001900013b440000003d000044570000013d000113000010019d0000130001100197000000000301004b00003b530000613d00013b4a0000003d000044290000013d00003b4f0000613d000000000600001900013b4e0000003d000044210000013d00003b4c0000413d0000001f0110019000003b530000613d00013b530000003d0000440f0000013d000000000102004b00003b0e0000c13d0000435d0000013d0000422e0000013d0000000c0100002900013b5a0000003d00004a310000013d0000405f0000613d000000130200002900000000020204330000000002020433001800000002001d0000002302000029001613090020019b00000012020000290000000002020433001a13090020019b0000000f020000290000000002020433001913090020019b002500000000001d0022001f0000002d002600000000001d000000010210008a000000260320006b00003de50000813d000000260110006b00001b020000813d00013b710000003d000049240000013d00001370022001970000001f0300006b000000000400001900003b790000613d0000001f342000b90000001f534000fa000000000323004b000041ad0000c13d002500250020002e000041bf0000413d000027100240008c00003c550000413d000027102340011a000000220230006b00001ccd0000413d00013b820000003d000045e20000013d00001b020000813d002200220030007100013b860000003d000049360000013d0000131707700197000013640870009c00003ba60000c13d00013b8b0000003d00004b510000013d000013080800004100000000060000190000000006082019000013080550019700013b910000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000003030433001d13090030019b0000130a0330009c0000006d0000813d000027100340008a000027100330008c000042340000813d00013b9e0000003d0000473f0000013d000013090110019700013ba10000003d000046a50000013d00003be70000c13d000013780700004100013ba50000003d000044870000013d00003c080000013d0000134a0470009c00003beb0000c13d00013baa0000003d00004b4d0000013d000013080700004100000000050000190000000005072019000013080440019700013bb00000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000002020433001d13090020019b0000130a0220009c0000006d0000813d00013bba0000003d000049d00000013d00001309011001970000001a06000029000000230560006b00003c1b0000c13d000013750500004100013bc10000003d0000470e0000013d002c001d0000002d00013bc40000003d0000441d0000013d0000002c0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001d02000029000000040220008c00003bd40000613d0000001b0300002900013bd10000003d000045ec0000013d000001560000613d000000400100043d001b00000001001d00000001010000310000001f0210008c000013080500004100000000020000190000000002052019000013080310019700013bdc0000003d000047250000013d000013080330009c00013bdf0000003d0000469d0000013d0000006d0000613d0000001b0100002900013be30000003d0000445d0000013d0000006d0000c13d000000000101004b00003c550000c13d00003e1c0000013d000013770700004100013bea0000003d000046e30000013d00003c3f0000013d0000135f0470009c00003c300000c13d00013bef0000003d00004b490000013d000013080800004100000000060000190000000006082019000013080550019700013bf50000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000004040433001d13090040019b0000130a0440009c0000006d0000813d000000400500043d001b00c40050003d00013c010000003d000045890000013d000013090a10019700013c040000003d000045b90000013d00003c3c0000c13d000013730200004100013c080000003d000044c30000013d000000400100043d001700000001001d0086001d0000002d00013c0d0000003d0000441d0000013d000000860440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001d02000029000000040220008c00003c550000613d00000017030000290000001b043000690000001d0200002900003c520000013d00001374050000410000001b0600002900013c1f0000003d000044b70000013d005e00190000002d00013c220000003d0000441d0000013d0000005e0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c00003c550000613d0000001d030000290000001b02300069000000840420003900003c510000013d0000134b0470009c00003c580000c13d0000130904100197000000230140006b00003c550000613d000000400200043d0000000001000414000000040540008c00003c800000c13d0000000102000039000000010100003100003c8d0000013d000013720200004100013c3f0000003d000045ab0000013d000000400100043d001d00000001001d007200190000002d00013c440000003d0000441d0000013d000000720440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c00003c550000613d0000001b020000290000001d030000290000000004320049000000190200002900013c540000003d0000452b0000013d000001560000613d00013c570000003d000048520000013d00003b6a0000013d000000400300043d000013710400004100013c5c0000003d00004bef0000013d00013c5e0000003d000045210000013d000013170440019700013c610000003d0000462a0000013d0000001d0650006c00003c670000813d0000001b0650002900013c660000003d000045260000013d00003c610000013d0000001d0450006c00003c6c0000a13d0000001d050000290000001b0450002900000000000404350000000002020433000013090110019700013c700000003d000044430000013d004800190000002d00013c730000003d0000441d0000013d000000480440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c00003c550000613d00013c7f0000003d000049160000013d00003c500000013d000013000510009c00001300060000410000000001068019000013000520009c000000000206801900013c870000003d0000460e0000013d0000130b011001c7000080090200003900013c8b0000003d000044570000013d000113000010019d0000130001100197000000000301004b00003c9a0000613d00013c910000003d000044290000013d00003c960000613d000000000600001900013c950000003d000044210000013d00003c930000413d0000001f0110019000003c9a0000613d00013c9a0000003d0000440f0000013d000000000102004b00003c550000c13d0000435d0000013d0000422e0000013d0000000b0100002900013ca10000003d00004a310000013d0000405f0000613d000000140200002900000000020204330000000002020433001800000002001d0000002302000029001613090020019b0000000d020000290000000002020433001a13090020019b0000000e020000290000000002020433001913090020019b002500000000001d001f00220000002d002600000000001d000000010210008a000000260320006b00003e1d0000813d000000260110006b00001b020000813d00013cb80000003d000049240000013d0000137002200197000000220300006b000000000400001900003cc00000613d00000022342000b900000022534000fa000000000323004b000041ad0000c13d002500250020002e000041bf0000413d000027100240008c00003d9c0000413d000027102340011a0000001f0230006b00001ccd0000413d00013cc90000003d000045e20000013d00001b020000813d001f001f0030007100013ccd0000003d000049360000013d0000131707700197000013640870009c00003ced0000c13d00013cd20000003d00004b510000013d000013080800004100000000060000190000000006082019000013080550019700013cd80000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000003030433001d13090030019b0000130a0330009c0000006d0000813d000027100340008a000027100330008c000042340000813d00013ce50000003d0000473f0000013d000013090110019700013ce80000003d000046a50000013d00003d2e0000c13d000013780700004100013cec0000003d000044870000013d00003d4f0000013d0000134a0470009c00003d320000c13d00013cf10000003d00004b4d0000013d000013080700004100000000050000190000000005072019000013080440019700013cf70000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000002020433001d13090020019b0000130a0220009c0000006d0000813d00013d010000003d000049d00000013d00001309011001970000001a06000029000000230560006b00003d620000c13d000013750500004100013d080000003d0000470e0000013d0033001d0000002d00013d0b0000003d0000441d0000013d000000330440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001d02000029000000040220008c00003d1b0000613d0000001b0300002900013d180000003d000045ec0000013d000001560000613d000000400100043d001b00000001001d00000001010000310000001f0210008c000013080500004100000000020000190000000002052019000013080310019700013d230000003d000047250000013d000013080330009c00013d260000003d0000469d0000013d0000006d0000613d0000001b0100002900013d2a0000003d0000445d0000013d0000006d0000c13d000000000101004b00003d9c0000c13d00003e4a0000013d000013770700004100013d310000003d000046e30000013d00003d860000013d0000135f0470009c00003d770000c13d00013d360000003d00004b490000013d000013080800004100000000060000190000000006082019000013080550019700013d3c0000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000004040433001d13090040019b0000130a0440009c0000006d0000813d000000400500043d001b00c40050003d00013d480000003d000045890000013d000013090a10019700013d4b0000003d000045b90000013d00003d830000c13d000013730200004100013d4f0000003d000044c30000013d000000400100043d001700000001001d008d001d0000002d00013d540000003d0000441d0000013d0000008d0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001d02000029000000040220008c00003d9c0000613d00000017030000290000001b043000690000001d0200002900003d990000013d00001374050000410000001b0600002900013d660000003d000044b70000013d006500190000002d00013d690000003d0000441d0000013d000000650440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c00003d9c0000613d0000001d030000290000001b02300069000000840420003900003d980000013d0000134b0470009c00003d9f0000c13d0000130904100197000000230140006b00003d9c0000613d000000400200043d0000000001000414000000040540008c00003dc70000c13d0000000102000039000000010100003100003dd40000013d000013720200004100013d860000003d000045ab0000013d000000400100043d001d00000001001d007900190000002d00013d8b0000003d0000441d0000013d000000790440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c00003d9c0000613d0000001b020000290000001d030000290000000004320049000000190200002900013d9b0000003d0000452b0000013d000001560000613d00013d9e0000003d000048520000013d00003cb10000013d000000400300043d000013710400004100013da30000003d00004bef0000013d00013da50000003d000045210000013d000013170440019700013da80000003d0000462a0000013d0000001d0650006c00003dae0000813d0000001b0650002900013dad0000003d000045260000013d00003da80000013d0000001d0450006c00003db30000a13d0000001d050000290000001b0450002900000000000404350000000002020433000013090110019700013db70000003d000044430000013d004f00190000002d00013dba0000003d0000441d0000013d0000004f0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c00003d9c0000613d00013dc60000003d000049160000013d00003d970000013d000013000510009c00001300060000410000000001068019000013000520009c000000000206801900013dce0000003d0000460e0000013d0000130b011001c7000080090200003900013dd20000003d000044570000013d000113000010019d0000130001100197000000000301004b00003de10000613d00013dd80000003d000044290000013d00003ddd0000613d000000000600001900013ddc0000003d000044210000013d00003dda0000413d0000001f0110019000003de10000613d00013de10000003d0000440f0000013d000000000102004b00003d9c0000c13d0000435d0000013d0000422e0000013d000000000101004b00001b020000613d00013de90000003d000049750000013d0000137002200197000000250220002a000041bf0000413d000027100220008c000041ea0000c13d000000220200006b00013df10000003d0000464a0000013d0000405b0000613d000000400400043d0000004002400039000000400020043f00000020024000390000002203000029000000000032043500000018030000290000000000340435000000000101043300000000350304340000131705500197000013640650009c00003e4b0000c13d00000000020304330000000034020434000013080500004100013e040000003d000048800000013d0000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d0000000003030433002613090030019b0000130a0330009c0000006d0000813d0000002203000029000000010330008c000042340000c13d00013e140000003d0000467b0000013d000013090110019700013e170000003d000046a50000013d00003e960000c13d000013780700004100013e1b0000003d000044870000013d00003f040000013d0000422e0000013d000000000101004b00001b020000613d00013e210000003d000049750000013d0000137002200197000000250220002a000041bf0000413d000027100220008c000041ea0000c13d0000001f0200006b0000405b0000613d00013e2a0000003d000046700000013d0000131705500197000013640650009c00003e9a0000c13d00000000020304330000000034020434000013080500004100013e320000003d000048800000013d0000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d0000000003030433002613090030019b0000130a0330009c0000006d0000813d0000001f03000029000000010330008c000042340000c13d00013e420000003d0000467b0000013d000013090110019700013e450000003d000046a50000013d00003edb0000c13d000013780700004100013e490000003d000044870000013d00003f520000013d0000422e0000013d0000134a0650009c00003edf0000c13d00000000020304330000000023020434000013080400004100013e520000003d000049aa0000013d0000130803300197000000000603004b0000000004008019000013080330009c000000000405c019000000000304004b0000006d0000613d0000000002020433002513090020019b0000130a0220009c0000006d0000813d000000400300043d001f00440030003d0000002402300039002600000003001d000000040330003900001309011001970000001a05000029000000230450006b00003f190000c13d000013750400004100000026050000290000000000450435000000000013043500000022010000290000000000120435000000400100043d002600000001001d002d00250000002d00013e710000003d0000441d0000013d0000002d0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002502000029000000040220008c00003e820000613d00000026030000290000001f0430006900013e7f0000003d000045900000013d000001560000613d000000400100043d002600000001001d0000000101000031000013080300004100013e860000003d0000499b0000013d0000130804100197000000000504004b0000000003008019000013080440009c00013e8c0000003d0000454b0000013d0000006d0000613d000000260100002900013e900000003d0000445d0000013d0000006d0000c13d000000000101004b00013e940000003d0000464a0000013d0000405b0000c13d0000422e0000013d000013770700004100013e990000003d000045ce0000013d00003f910000013d0000134a0650009c00003f350000c13d00000000020304330000000023020434000013080400004100013ea10000003d000049aa0000013d0000130803300197000000000603004b0000000004008019000013080330009c000000000405c019000000000304004b0000006d0000613d0000000002020433002513090020019b0000130a0220009c0000006d0000813d00013eae0000003d000049f90000013d00001309011001970000001a05000029000000230450006b00003f650000c13d000013750400004100013eb50000003d000047f90000013d003400250000002d00013eb80000003d0000441d0000013d000000340440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002502000029000000040220008c00003ec90000613d0000002603000029000000220430006900013ec60000003d000045900000013d000001560000613d000000400100043d002600000001001d0000000101000031000013080300004100013ecd0000003d0000499b0000013d0000130804100197000000000504004b0000000003008019000013080440009c00013ed30000003d0000454b0000013d0000006d0000613d000000260100002900013ed70000003d0000445d0000013d0000006d0000c13d000000000101004b0000405b0000c13d0000422e0000013d000013770700004100013ede0000003d000045ce0000013d00003fb40000013d0000135f0650009c00003f780000c13d00000000020304330000000034020434000013080500004100013ee60000003d000048800000013d0000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d0000000003030433002613090030019b0000130a0330009c0000006d0000813d000000400400043d002500c40040003d00013ef50000003d000044cd0000013d000013090910019700013ef80000003d0000499f0000013d00003f860000c13d00001373020000410000000000240435000000160200002900000000002a04350000000000980435000000000017043500000022010000290000000000160435000000a00100003900000000001504350000000000030435000000400100043d002200000001001d008700260000002d00013f090000003d0000441d0000013d000000870440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002602000029000000040220008c00013f140000003d0000464a0000013d0000405b0000613d000000220300002900000025043000690000002602000029000040390000013d000013740400004100013f1c0000003d00004b270000013d0000001f020000290000000000120435000000640150003900000022020000290000000000210435000000400100043d002500000001001d005f00190000002d00013f260000003d0000441d0000013d0000005f0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c00013f310000003d0000464a0000013d0000405b0000613d00013f340000003d00004b8a0000013d000040380000013d0000135f0650009c00003fa50000c13d00000000020304330000000034020434000013080500004100013f3c0000003d000048800000013d0000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d0000000003030433002613090030019b0000130a0330009c0000006d0000813d000000400400043d002500c40040003d00013f4b0000003d000044cd0000013d000013090910019700013f4e0000003d0000499f0000013d00003fb10000c13d000013730200004100013f520000003d0000464f0000013d000000400100043d002200000001001d008e00260000002d00013f570000003d0000441d0000013d0000008e0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002602000029000000040220008c0000405b0000613d000000220300002900000025043000690000002602000029000040580000013d000013740400004100013f680000003d0000476f0000013d006600190000002d00013f6b0000003d0000441d0000013d000000660440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c0000405b0000613d00013f770000003d00004b8a0000013d000040570000013d0000134b0350009c00003fc60000c13d0000130904100197000000230140006b00013f7e0000003d0000464a0000013d0000405b0000613d000000400200043d0000000001000414000000040340008c00003fd30000c13d0000000102000039000000010500003100003fe10000013d00001372020000410000000000240435000000260200002900000000002a04350000001a02000029000000000028043500000000009704350000000000160435000000220100002900013f910000003d000046430000013d000000400100043d002500000001001d007300190000002d00013f960000003d0000441d0000013d000000730440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c00013fa10000003d0000464a0000013d0000405b0000613d00000026020000290000002503000029000040370000013d0000134b0350009c00003ff30000c13d0000130904100197000000230140006b0000405b0000613d000000400200043d0000000001000414000000040340008c000040000000c13d000000010200003900000001050000310000400e0000013d000013720200004100013fb40000003d000045960000013d000000400100043d002500000001001d007a00190000002d00013fb90000003d0000441d0000013d0000007a0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c0000405b0000613d00000026020000290000002503000029000040560000013d000000400300043d000013710500004100013fca0000003d0000444d0000013d000013170440019700013fcd0000003d000044e70000013d000000260650006c0000401e0000813d000000250650002900013fd20000003d000045260000013d00003fcd0000013d0000130003000041000013000510009c0000000001038019000013000520009c000000000203801900013fda0000003d0000460e0000013d0000130b011001c70000800902000039000000220300002900013fdf0000003d000044570000013d000113000010019d0000130005100197000000000105004b00003fee0000613d00013fe50000003d000044ac0000013d00003fea0000613d000000000600001900013fe90000003d000044210000013d00003fe70000413d000000000601004b00003fee0000613d00013fee0000003d0000440f0000013d000000000102004b00013ff10000003d0000464a0000013d0000405b0000c13d0000435d0000013d000000400300043d000013710500004100013ff70000003d0000444d0000013d000013170440019700013ffa0000003d000044e70000013d000000260650006c0000403f0000813d000000250650002900013fff0000003d000045260000013d00003ffa0000013d0000130003000041000013000510009c0000000001038019000013000520009c0000000002038019000140070000003d0000460e0000013d0000130b011001c700008009020000390000001f030000290001400c0000003d000044570000013d000113000010019d0000130005100197000000000105004b0000401b0000613d000140120000003d000044ac0000013d000040170000613d0000000006000019000140160000003d000044210000013d000040140000413d000000000601004b0000401b0000613d0001401b0000003d0000440f0000013d000000000102004b0000405b0000c13d0000435d0000013d000000260450006c000040220000a13d000140220000003d00004b1c0000013d00000000020204330000130901100197000140260000003d000049530000013d004900190000002d000140290000003d0000441d0000013d000000490440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000140340000003d0000464a0000013d0000405b0000613d000140370000003d00004b090000013d000000000432004900000019020000290001403b0000003d0000452b0000013d0001403d0000003d0000464a0000013d0000405b0000c13d000001560000013d000000260450006c000040430000a13d000140430000003d00004b1c0000013d00000000020204330000130901100197000140470000003d000049530000013d005000190000002d0001404a0000003d0000441d0000013d000000500440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c0000405b0000613d000140560000003d00004b090000013d000000000432004900000019020000290001405a0000003d0000452b0000013d000001560000613d0000000c010000290001405e0000003d00004a310000013d000040690000c13d000000400200043d0000006401200039000013810300004100000000003104350000004401200039000013820300004100000000003104350000002401200039000000240300003900000ac90000013d000000130200002900000000020204330000000023020434001800000003001d00000000030204330000002302000029001613090020019b00000012020000290000000002020433001a13090020019b0000000f020000290000000002020433001913090020019b002500000000001d002200000003001d001f00000003001d002600000000001d000000010210008a000000260320006b000041b70000813d000000260110006b00001b020000813d000140810000003d000049240000013d0000137002200197000000220300006b0000000004000019000040890000613d00000022342000b900000022534000fa000000000323004b000041ad0000c13d002500250020002e000041bf0000413d000027100240008c000041650000413d000027102340011a0000001f0230006b00001ccd0000413d000140920000003d000045e20000013d00001b020000813d001f001f00300071000140960000003d000049360000013d0000131707700197000013640870009c000040b60000c13d0001409b0000003d00004b510000013d0000130808000041000000000600001900000000060820190000130805500197000140a10000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000003030433001d13090030019b0000130a0330009c0000006d0000813d000027100340008a000027100330008c000042340000813d000140ae0000003d0000473f0000013d0000130901100197000140b10000003d000046a50000013d000040f70000c13d0000137807000041000140b50000003d000044870000013d000041180000013d0000134a0470009c000040fb0000c13d000140ba0000003d00004b4d0000013d0000130807000041000000000500001900000000050720190000130804400197000140c00000003d0000463f0000013d000013080440009c000000000605c019000000000406004b0000006d0000613d0000000002020433001d13090020019b0000130a0220009c0000006d0000813d000140ca0000003d000049d00000013d00001309011001970000001a06000029000000230560006b0000412b0000c13d0000137505000041000140d10000003d0000470e0000013d0035001d0000002d000140d40000003d0000441d0000013d000000350440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001d02000029000000040220008c000040e40000613d0000001b03000029000140e10000003d000045ec0000013d000001560000613d000000400100043d001b00000001001d00000001010000310000001f0210008c0000130805000041000000000200001900000000020520190000130803100197000140ec0000003d000047250000013d000013080330009c000140ef0000003d0000469d0000013d0000006d0000613d0000001b01000029000140f30000003d0000445d0000013d0000006d0000c13d000000000101004b000041650000c13d000041c30000013d0000137707000041000140fa0000003d000046e30000013d0000414f0000013d0000135f0470009c000041400000c13d000140ff0000003d00004b490000013d0000130808000041000000000600001900000000060820190000130805500197000141050000003d000047010000013d000013080550009c000000000706c019000000000507004b0000006d0000613d0000000004040433001d13090040019b0000130a0440009c0000006d0000813d000000400500043d001b00c40050003d000141110000003d000045890000013d000013090a100197000141140000003d000045b90000013d0000414c0000c13d0000137302000041000141180000003d000044c30000013d000000400100043d001700000001001d008f001d0000002d0001411d0000003d0000441d0000013d0000008f0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001d02000029000000040220008c000041650000613d00000017030000290000001b043000690000001d02000029000041620000013d00001374050000410000001b060000290001412f0000003d000044b70000013d006700190000002d000141320000003d0000441d0000013d000000670440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000041650000613d0000001d030000290000001b023000690000008404200039000041610000013d0000134b0470009c000041680000c13d0000130904100197000000230140006b000041650000613d000000400200043d0000000001000414000000040540008c000041900000c13d000000010200003900000001010000310000419d0000013d00001372020000410001414f0000003d000045ab0000013d000000400100043d001d00000001001d007b00190000002d000141540000003d0000441d0000013d0000007b0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000041650000613d0000001b020000290000001d0300002900000000043200490000001902000029000141640000003d0000452b0000013d000001560000613d000141670000003d000048520000013d0000407a0000013d000000400300043d00001371040000410001416c0000003d00004bef0000013d0001416e0000003d000045210000013d0000131704400197000141710000003d0000462a0000013d0000001d0650006c000041770000813d0000001b06500029000141760000003d000045260000013d000041710000013d0000001d0450006c0000417c0000a13d0000001d050000290000001b04500029000000000004043500000000020204330000130901100197000141800000003d000044430000013d005100190000002d000141830000003d0000441d0000013d000000510440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000041650000613d0001418f0000003d000049160000013d000041600000013d000013000510009c00001300060000410000000001068019000013000520009c0000000002068019000141970000003d0000460e0000013d0000130b011001c700008009020000390001419b0000003d000044570000013d000113000010019d0000130001100197000000000301004b000041aa0000613d000141a10000003d000044290000013d000041a60000613d0000000006000019000141a50000003d000044210000013d000041a30000413d0000001f01100190000041aa0000613d000141aa0000003d0000440f0000013d000000000102004b000041650000c13d0000435d0000013d000000400200043d0000006401200039000013830300004100000000003104350000004401200039000013840300004100000000003104350000002401200039000000210300003900000ac90000013d000000000101004b00001b020000613d000141bb0000003d000049750000013d0000137002200197000000250220002a000041bf0000413d000041c40000013d000000400200043d000000440120003900001387030000410000257e0000013d0000422e0000013d000027100220008c000041ea0000c13d0000001f0200006b000042e80000613d000141ca0000003d000046700000013d0000131705500197000013640650009c000041ee0000c13d000000000203043300000000340204340000130805000041000141d20000003d000048800000013d0000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d0000000003030433002613090030019b0000130a0330009c0000006d0000813d0000001f03000029000000010330008c000042340000c13d000141e20000003d0000467b0000013d0000130901100197000141e50000003d000046a50000013d000042380000c13d0000137807000041000141e90000003d000044870000013d000042590000013d000000400200043d00000044012000390000137f0300004100001cd00000013d0000134a0650009c0000423c0000c13d000000000203043300000000230204340000130804000041000141f50000003d000049aa0000013d0000130803300197000000000603004b0000000004008019000013080330009c000000000405c019000000000304004b0000006d0000613d0000000002020433002513090020019b0000130a0220009c0000006d0000813d000142020000003d000049f90000013d00001309011001970000001a05000029000000230450006b0000426c0000c13d0000137504000041000142090000003d000047f90000013d003600250000002d0001420c0000003d0000441d0000013d000000360440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002502000029000000040220008c0000421d0000613d000000260300002900000022043000690001421a0000003d000045900000013d000001560000613d000000400100043d002600000001001d00000001010000310000130803000041000142210000003d0000499b0000013d0000130804100197000000000504004b0000000003008019000013080440009c000142270000003d0000454b0000013d0000006d0000613d00000026010000290001422b0000003d0000445d0000013d0000006d0000c13d000000000101004b000042e80000c13d00000044012000390000137603000041000000000031043500000024012000390000001503000039000025810000013d000000400200043d00000044012000390000138603000041000015570000013d00001377070000410001423b0000003d000045ce0000013d0000428e0000013d0000135f0650009c0000427f0000c13d000000000203043300000000340204340000130805000041000142430000003d000048800000013d0000130804400197000000000704004b0000000005008019000013080440009c000000000506c019000000000405004b0000006d0000613d0000000003030433002613090030019b0000130a0330009c0000006d0000813d000000400400043d002500c40040003d000142520000003d000044cd0000013d0000130909100197000142550000003d0000499f0000013d0000428b0000c13d0000137302000041000142590000003d0000464f0000013d000000400100043d002300000001001d009000260000002d0001425e0000003d0000441d0000013d000000900440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000002602000029000000040220008c000042e80000613d000000230300002900000025043000690000002602000029000042e50000013d00001374040000410001426f0000003d0000476f0000013d006800190000002d000142720000003d0000441d0000013d000000680440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000042e80000613d0001427e0000003d00004b8a0000013d000042e40000013d0000134b0350009c000042a00000c13d0000130904100197000000230140006b000042e80000613d000000400200043d0000000001000414000000040340008c000042ad0000c13d00000001020000390000000105000031000042bb0000013d00001372020000410001428e0000003d000045960000013d000000400100043d002500000001001d007c00190000002d000142930000003d0000441d0000013d0000007c0440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000042e80000613d00000026020000290000002503000029000042e30000013d000000400300043d0000137105000041000142a40000003d0000444d0000013d0000131704400197000142a70000003d000044e70000013d000000260650006c000042cb0000813d0000002506500029000142ac0000003d000045260000013d000042a70000013d0000130003000041000013000510009c0000000001038019000013000520009c0000000002038019000142b40000003d0000460e0000013d0000130b011001c700008009020000390000001f03000029000142b90000003d000044570000013d000113000010019d0000130005100197000000000105004b000042c80000613d000142bf0000003d000044ac0000013d000042c40000613d0000000006000019000142c30000003d000044210000013d000042c10000413d000000000601004b000042c80000613d000142c80000003d0000440f0000013d000000000102004b000042e80000c13d0000435d0000013d000000260450006c000042cf0000a13d000142cf0000003d00004b1c0000013d00000000020204330000130901100197000142d30000003d000049bc0000013d002300000001001d005200190000002d000142d70000003d0000441d0000013d000000520440008a00000020044000c900001320020000414bfc43ed0000040f000000000101004b0000006d0000613d00000000010004140000001902000029000000040220008c000042e80000613d000142e30000003d00004b020000013d00000000043200490000001902000029000142e70000003d0000452b0000013d000001560000613d0000002101000029000000000101043300001317011001970000002402000029000000000202043300001317022001970000134b0220009c000043080000c13d0000134b0110009c0000006d0000613d0000000001000416000000200110006c0000430d0000413d0000000001000416000000200110006c000002a90000a13d0000000005000416000000200150006c00001ccd0000413d0000000101000039000000400300043d000000000200041400000011040000290000130904400197000000040640008c000043060000613d000000200150006c000043110000c13d000143060000003d00004bb90000013d00000001050000310000431f0000013d0000134b0110009c000002a90000c13d0000000001000416000000100110006c0000432d0000813d000000400200043d0000004401200039000013800300004100001e610000013d000000200550006a0000130001000041000013000620009c0000000002018019000013000630009c00000000030180190000004001300210000000c002200210000000000112019f0000130b011001c70001431d0000003d0000493b0000013d000113000020019d0000130005200197000000000205004b0000435b0000613d000143230000003d0000492b0000013d000043280000613d0000000006000019000143270000003d000044210000013d000043250000413d000000000602004b0000435b0000613d0001432c0000003d000047d50000013d0000435b0000013d0000000001000416000000100110006c000002a90000a13d0000000005000416000000100150006c00001ccd0000413d0000000101000039000000400300043d000000000200041400000011040000290000130904400197000000040640008c0000433e0000613d000000100150006c000043400000c13d0001433e0000003d00004bb90000013d00000001050000310000434e0000013d000000100550006a0000130001000041000013000620009c0000000002018019000013000630009c00000000030180190000004001300210000000c002200210000000000112019f0000130b011001c70001434c0000003d0000493b0000013d000113000020019d0000130005200197000000000205004b0000435b0000613d000143520000003d0000492b0000013d000043570000613d0000000006000019000143560000003d000044210000013d000043540000413d000000000602004b0000435b0000613d0001435b0000003d000047d50000013d000000000101004b000002a90000c13d000000400200043d0000004401200039000013850300004100001ec80000013d00000000243200d900000000143100d90000139a0430009c000043680000813d00000000211200a900000000123100d9000043c10000013d00000000421200a9000000010100008a000000000534004b000043c10000813d0000139b0130009c000000c0010000390000008001004039000000000513022f0000139b0130009c00000040010000390000008001004039000000200610008a0000139c0750009c000000000106801900000020065002700000139c0750009c0000000005068019000000100610008a0000139d0750009c000000000106801900000010065002700000139d0750009c0000000005068019000000080610008a000001000750008c000000000106801900000008055082700000000406500270000000100750008c00000000060540190000000207600270000000040860008c0000000007064019000000020800008a0000000009700049000000020770008c0000000009088019000000040710008a000000100550008c0000000001078019000000020510008a000000040660008c0000000001058019000000000119001a000000000414c1cf000001000510c089000000000552c22f000000000454c19f000000000212c1cf000000000313c1cf000000800530027000000000985400d900000080072002700000139e063001970000139f0a80009c000043a50000213d00000000ba6800a9000000800b900210000000000b7b019f000000000aba004b000043a90000a13d0000000009590019000000010880008a0000139e0a90009c0000439e0000413d0000139e0880019700000000983800a90000008004400210000000000447019f000000000484004900000000875400d90000139e022001970000139f0970009c000043b70000213d00000000a96700a9000000800a800210000000000a2a019f0000000009a9004b000043bb0000a13d0000000008580019000000010770008a0000139e0980009c000043b00000413d0000139e0570019700000000533500a90000008004400210000000000224019f0000000002320049000000000112022f000000000001042d000000000001042f0000130003000041000013000420009c0000000002038019000013000410009c000000000103801900000040011002100000006002200210000000000112019f00004bfe000104300000130004000041000013000520009c0000000002048019000013000510009c000000000104801900000040011002100000006002200210000000000112019f000000e002300210000000000121019f00004bfd0001042e00010000000000020000130003000041000013000410009c00000000010380190000004001100210000013000420009c000143df0000003d000049450000013d0000000002000414000013000420009c0000000002038019000000c002200210000000000112019f0000130b011001c700008010020000394bfc440a0000040f0000000102200190000043eb0000613d000000000101043b000000000001042d000000000100001900004bfe0001043000000000050100190000000000200439000000040130008c000043f40000a13d00000005014002700000000001010031000000040010044300001300010000410000000002000414000013000420009c0000000002018019000013000430009c00000000030180190000006001300210000000c002200210000000000112019f000013a0011001c700000000020500194bfc440a0000040f0000000102200190000044040000613d000000000101043b000000000001042d000000000001042f00004408002104210000000102000039000000000001042d0000000002000019000000000001042d0000440d002104230000000102000039000000000001042d0000000002000019000000000001042d0000000505500210000000000454034f00000000035300190000000301100210000000000503043300000000051501cf000000000515022f000000000404043b0000010001100089000000000414022f00000000011401cf000000000151019f0000000000130435000000010000013b000080020100003900000024030000390000000004000415000000010000013b00000005076002100000000008730019000000000774034f000000000707043b00000000007804350000000106600039000000000756004b000000010000013b0000003f03100039000000200400008a000000000343016f000000400400043d0000000003340019000000400030043f000000000314043600000003040003670000000505100272000000010000013b00000021040000290000000504400210000000220540035f000000000443001900000020060000290000000306600210000000000704043300000000076701cf000000000767022f000000000505043b0000010006600089000000000565022f00000000056501cf000000000575019f0000000000540435000000010000013b0000004404300039000000000014043500000024013000390000001a04000029000000000041043500000084013000390000000000210435000000400100043d001700000001001d000000010000013b000000000053043500000004053000390000006006000039000000000065043500000000040404330000006405300039000000150700002900000000007504350000000054040434000000010000013b00000000050000194bfc44050000040f000000010220018f00030000000103550000006001100270000000010000013b0000000001010433000000000301004b0000000003000019000000010300c039000000000331004b000000010000013b000000a001100039000000000401043300000000043401cf000000000434022f000000000202043b0000010003300089000000000232022f00000000023201cf000000000242019f0000000000210435000000010000013b0000000303300210000000000504043300000000053501cf000000000535022f000000000202043b0000010003300089000000000232022f00000000023201cf000000000252019f0000000000240435000000010000013b0000000507700210000000000676034f00000000077400190000000305500210000000000807043300000000085801cf000000000858022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000585019f0000000000570435000000010000013b00000000007304350000001603000029000000000036043500000000001504350000000000240435000000010000013b0000002002400039000000000032043500000060024000390000000000120435000000400300043d000000000132004900000000011304360000008002400039000000400020043f00000000020304334bfc43d70000040f000000220200002900000000020204330000002604000029000000c0034000390000000000130435000000e0014000390000000000210435000000010000013b000000000065043500000000040404330000006405300039000000150700002900000000007504350000000054040434000000010000013b000000000707043b00000000007804350000000106600039000000000756004b000000010000013b0000003f01500039000000200300008a000000000131016f000000400300043d0000000001130019000000400010043f0000001f0150018f000000000353043600000003040003670000000505500272000000010000013b00000000005604350000001d0500002900000000005404350000001a0400002900000000004204350000001702000029000000000012043500000064016000390000000000310435000000400100043d001d00000001001d000000010000013b0000000000250435000000160200002900000000002b04350000000000a9043500000000001804350000000000370435000000a00100003900000000001604350000000000040435000000010000013b000000a4034000390000008405400039000000640640003900000044074000390000002408400039000000040a400039000000010000013b000000000402c0190000001f01100039000000200200008a000000000121016f0000001c02100029000000400020043f000000000104004b000000010000013b000000400400043d0000004002400039000000400020043f00000020024000390000000000b20435000000180300002900000000003404350000001e030000290000000003030433000000260330006b000000010000013b000000a40630003900000000004604350000000004050433000000c4053000390000000000750435000000e4053000390000000006040433002600000006001d0000000000650435002501040030003d0000000005000019000000010000013b0000000000020435000000400060043f000005020290003900000020030000290000000000320435000004e20290003900000021030000290000000000320435000004c20290003900000000007204350000000000160435000000400300043d00000000013900490000052204100039000000010000013b000000000032043500000160024000390000000000120435000000400300043d000000000132004900000000011304360000018002400039000000400020043f00000000020304334bfc43d70000040f000000200200002900000000020204330000002604000029000001a003400039000000010000013b0000800b01000039000000040300003900000000040004150000009f0440008a00000020044000c9000000010000013b0000000000240435000000160200002900000000002a0435000000000098043500000000001704350000000000b60435000000a00100003900000000001504350000000000030435000000010000013b0000006405300039000000150700002900000000007504350000000054040434000000010000013b0000002005500039000000000745001900000000070704330000000000760435000000010000013b000000000503001900000000060000194bfc000d0000040f000000000101004b000000010000013b00000040022000390000000002020433000000400300043d001c00640030003d00000044043000390000002405300039000000010000013b000000260100002900000005011002100000001b01100029000000000201043300000020022000390000000002020433000000010000013b0000000000530435000001c0034000390000000000130435000001e0014000390000000000210435000000400200043d000000000121004900000000011204360000020003400039000000400030043f00000000020204334bfc43d70000040f000000010000013b000000000302c0190000001f01100039000000200200008a000000000121016f0000002602100029000000400020043f000000000103004b000000010000013b00000000000204350000002605000029000004fe02500039000000400020043f0000055e03500039000000200400002900000000004304350000053e03500039000000210400002900000000004304350000051e035000390000001f0400002900000000004304350000000000120435000000400300043d00000000013500490000057e04100039000000010000013b00000026040000290000032003400039000000000023043500000300024000390000001d030000290000000000320435000002e0024000390000001f030000290000000000320435000002c00240003900000020030000290000000000320435000002a0024000390000001e0300002900000000003204350000002202000029000000010000013b0000000509800210000000000a940019000000000996034f000000000909043b00000000009a04350000000108800039000000000978004b000000010000013b000000200200008a000000240320017f000000400200043d0000000003320019000000400030043f000000260300002900000000033204360000002108000029000000000408004b000000220700035f000000010000013b000000a4045000390000008406500039000000640750003900000044085000390000002409500039000000040b500039000000010000013b0000002006000039000000250200002900000000050300194bfc000d0000040f000000000101004b000000010000013b0000000000240435000000260200002900000000002a04350000001a020000290000000000280435000000000097043500000000001604350000001f010000290000000000150435000000c001000039000000000013043500000025010000290000000000010435002600e40040003d000000010000013b0000001f02200039000000200300008a000000000232016f0000001c022000290000001703000029000000010000013b00000000002504350000001d0200002900000000002b04350000001a0200002900000000002904350000000000a8043500000000001704350000000000360435000000c00100003900000000001404350000001b010000290000000000010435001b00e40050003d000000010000013b000000400120003900000000010104330000001a0c0000290000002302c0006b000000010000013b000000000662034f000000000606043b00000000006704350000000105500039000000000645004b000000010000013b00000400024000390000000000120435000000400300043d000000000132004900000000011304360000042002400039000000400020043f00000000020304334bfc43d70000040f000000010000013b0000000000730435000000260700002900000000007604350000001a060000290000000000650435000000000014043500000025010000290000000000210435002600840030003d000000010000013b000000a0024000390000000000320435000000400200043d000000000121004900000000011204360000010003400039000000400030043f00000000020204334bfc43d70000040f000000010000013b000000400500043d0000004002500039000000400020043f0000001802000029000000000225043600000000003204350000001e060000290000000006060433000000260660006b000000010000013b000000170430006900000020060000390000001d0200002900000000050300194bfc000d0000040f000000000101004b000000010000013b00000000007604350000001a06000029000000000065043500000000001404350000001c010000290000000000210435001c00840030003d000000010000013b00000005054002100000000006530019000000000557034f000000000505043b00000000005604350000000104400039000000000584004b000000010000013b0000001c05000029000000000045043500000000001304350000000000b20435000000400100043d001c00000001001d000000010000013b00000000050300194bfc000d0000040f000000000101004b000000010000013b0000004002200210000000c001100210000000000121019f000000010000013b00000000002a04350000001a020000290000000000280435000000000097043500000000001604350000000000b50435000000c00100003900000000001304350000001c010000290000000000010435001c00e40040003d000000010000013b000000a40630003900000000004604350000000004050433000000c4053000390000000000750435000000e4053000390000000006040433001d00000006001d0000000000650435001c01040030003d0000000005000019000000010000013b000000a40630003900000000004604350000000004050433000000c4053000390000000000750435000000e4053000390000000006040433001d00000006001d0000000000650435001b01040030003d0000000005000019000000010000013b000000000603043300000064031000390000000000530435000000a4051000390000008403100039000000000406043300000000004304350000000007000019000000010000013b000000000604004b00000000060000190000000006074019000000010000013b0000000000150435000000c001000039000000000013043500000025010000290000000000010435002600e40040003d000000010000013b0012000d0000002d000f000e0000002d001300140000002d000c000b0000002d000000010000013b0000000000240435000000160200002900000000002a0435000000000098043500000000001704350000001f010000290000000000160435000000a00100003900000000001504350000000000030435000000010000013b000000000032043500000060024000390000000000120435000000400300043d000000000132004900000000011304360000008002400039000000400020043f00000000020304334bfc43d70000040f000000010000013b0000000000320435000000e0024000390000000000120435000000400300043d000000000132004900000000011304360000010002400039000000400020043f00000000020304334bfc43d70000040f000000010000013b000000400400043d0000004002400039000000400020043f00000020024000390000001f0300002900000000003204350000001803000029000000000034043500000000010104330000000035030434000000010000013b00000040022000390000000002020433000000400300043d002500640030003d00000044043000390000002405300039000000010000013b000000030aa00210000000000d0c0433000000000dad01cf000000000dad022f000000000b0b043b000001000aa00089000000000bab022f000000000aab01cf000000000ada019f0000000000ac0435000000010000013b000000210200006b0000002603000029000004c605300039000004a60430003900000486023000390000000009030019000004e603300039000000010000013b0000000502100210000000000329034f000000000303043b000000a002200039000000000032043500000001011000390000000002b1004b000000010000013b000000000402c0190000001f01100039000000200200008a000000000121016f0000001b02100029000000400020043f000000000104004b000000010000013b00000004063000390000001a08000029000000230780006b000000010000013b00000026040000290000044003400039000000000023043500000442024000390000000000120435000004620140003900000022020000290000000000210435000000400200043d000000000121004900000000011204360000048203400039002200000003001d000000400030043f00000000020204334bfc43d70000040f0000002402000029000000010000013b00000026040000290000044003400039000000000023043500000442024000390000000000120435000004620140003900000024020000290000000000210435000000400200043d000000000121004900000000011204360000048203400039002400000003001d000000400030043f00000000020204334bfc43d70000040f0000002202000029000000010000013b000000400300043d0000000004340019000000400040043f0000001f0520018f000000000423043600000002060003670000000507200272000000010000013b000000400300043d001700440030003d0000002402300039001c00000003001d0000000403300039000000010000013b000000200aa0003900000000020a0433000000000e6200190000003f02e00039000000000512004b00000000050000190000000005084019000000010000013b00000000007304350000001d0700002900000000007604350000001a06000029000000000065043500000000001404350000001b010000290000000000210435001b00840030003d000000010000013b0000002603300029000000000003043500000026022000290000000002020433000000010000013b000000000779001900000000000704350000006007500039000000000087043500000000066504360000002004400039000000220440035f000000000404043b0000000000460435000000010000013b00000000026100490000003f0b20008c000000000b000019000000000b082019000000010000013b000000000705004b00000000070000190000000007084019000000010000013b0000002602100069000000030110021000000100011000890000000043020434002600000004001d000000000313022f00000000011301cf0000000000120435000000010000013b0000001b06000029000000000056043500000000001404350000000000320435000000400100043d001b00000001001d000000010000013b000000200100008a000000240110017f000000400010043f0000002601000029000000800010043f00000000010b004b000000010000013b4bfc43ed0000040f0000002604000029000003c0024000390000001f030000290000000000320435000003a00240003900000020030000290000000000320435000000010000013b000000000403004b00000000040000190000000004054019000000010000013b0000001c0100002900000000020104330000001e010000294bfc43d70000040f00000020020000290000000002020433002000000001001d00000021010000294bfc43d70000040f000000c9020000390000002003000029000000000032041b000000ca02000039000000000012041b000000010000013b000000400100043d0000004002100039000000400020043f000000200210003900000000000204350000000000010435000000010000013b00000040022000390000000002020433000000400300043d001b00640030003d00000044043000390000002405300039000000010000013b000000000042043500000060023000390000000005010433000000000052043500000080063000390000000002000019000000010000013b00000020099000390000000000dc04350000000000b90435000000010aa000390000004006600039000000010000013b0000000509900210000000000797034f00000000099600190000000308800210000000000b090433000000000b8b01cf000000000b8b022f000000000707043b0000010008800089000000000787022f00000000078701cf0000000007b7019f0000000000790435000000010000013b0000022003400039000000000023043500000340024000390000000000120435000000400300043d000000000132004900000000011304360000036002400039000000400020043f00000000020304334bfc43d70000040f00000017020000290000000002020433000000010000013b00000026050000290000000000450435000000250400002900000000004304350000001a0300002900000000003204350000002202000029000000000012043500000064015000390000001f020000290000000000210435000000400100043d002500000001001d000000010000013b000000400200043d0000000101000039000800000001001d00000000031204360000008001200039000000400010043f00000060012000390000000000010435001e00000002001d0000004001200039001b00000003001d00000000001304350000000000010435000000010000013b00000000002504350000001d0200002900000000002b04350000001a0200002900000000002904350000000000a8043500000000001704350000000000360435000000c00100003900000000001404350000001c010000290000000000010435001c00e40050003d000000010000013b000000400340003900000000002304350000000002040433000000260400002900000000002404350000000002050433000000200400002900000000002404350000000002030433000000000202004b0000000002000019000000010200c0390000000000210435000000010000013b000000000203043300000000340204340000003f0540008c000000010000013b0000004004500039000000000034043500000000030504330000001e05000029000000000035043500000000030604330000001b0500002900000000003504350000000003040433000000000303004b0000000003000019000000010300c0390000000000320435000000010000013b0000000000240435000000250200002900000000002a04350000001a020000290000000000280435000000000097043500000000001604350000000000b50435000000c00100003900000000001304350000001c010000290000000000010435002500e40040003d000000010000013b0000000002020433002200000002001d000000160200002900000000020204330000000032020434002000000003001d0000000023020434001f00000003001d0000000002020433002100000001001d00000000120204344bfc43d70000040f0000001f02000029000000010000013b0000000505500210000000000454034f00000000035300190000000302200210000000000503043300000000052501cf000000000525022f000000000404043b0000010002200089000000000424022f00000000022401cf000000000252019f0000000000230435000000010000013b0000000505500210000000000651034f00000000055900190000000304400210000000000705043300000000074701cf000000000747022f000000000606043b0000010004400089000000000646022f00000000044601cf000000000474019f0000000000450435000000010000013b0000016101000039002600000001001d000000000101041a000000400200043d000000200320003900000025040000290000000000430435000000010000013b0000002605000029000000000045043500000000001304350000001f010000290000000000120435000000400100043d002600000001001d000000010000013b000000400100043d0000004002100039000000400020043f0000002002100039000000220300002900000000003204350000000000010435000000010000013b0000000000560435000000260500002900000000005c043500000000001a04350000000000b9043500000000002804350000000000370435000000c001000039000000000014043500000025010000290000000000010435002600e40060003d000000010000013b00000005054002100000000006530019000000220550035f000000000505043b00000000005604350000000104400039000000210540006c000000010000013b000000240330017f000000400200043d0000000003230019000000400030043f00000026030000290000000003320436000000210400006b000000010000013b000000030200036700000001010000310000001f0310018f0000000504100272000000010000013b0000001c050000290000000000450435000000220400002900000000004304350000001a0300002900000000003204350000001702000029000000000012043500000064015000390000000000b10435000000400100043d002200000001001d000000010000013b0000001c050000290000000000450435000000250400002900000000004304350000001a0300002900000000003204350000001702000029000000000012043500000064015000390000000000b10435000000400100043d002500000001001d000000010000013b0000001c0500002900000000004504350000001f0400002900000000004304350000001a0300002900000000003204350000001702000029000000000012043500000064015000390000000000b10435000000400100043d001f00000001001d000000010000013b0000001e0100002900000000010104330000002602000029002600010020003d000000010000013b0000000001010433000000000101043300000000030404330000000035030434000000010000013b000000a40730003900000000005704350000000005060433000000c4063000390000000000860435000000e4063000390000000007050433002600000007001d0000000000760435002501040030003d0000000006000019000000010000013b0000006006700039000000000606043300000040077000390000000007070433002000000007001d000000010000013b00000380034000390000000000230435000003e00240003900000000001204350000002301000029000000010000013b0000022003400039000000000023043500000340024000390000000000120435000000400300043d000000000132004900000000011304360000036002400039000000400020043f00000000020304334bfc43d70000040f000000010000013b0000003f0640008c00000000060000190000000006052019000000010000013b0000001f0250008c00000000020000190000000002012019000000010000013b000000a40630003900000000004604350000000004050433000000c4053000390000000000750435000000e4053000390000000006040433002500000006001d0000000000650435001c01040030003d0000000005000019000000010000013b000000a40630003900000000004604350000000004050433000000c4053000390000000000750435000000e4053000390000000006040433001f00000006001d0000000000650435001c01040030003d0000000005000019000000010000013b000000a40630003900000000004604350000000004050433000000c4053000390000000000750435000000e4053000390000000006040433002200000006001d0000000000650435001c01040030003d0000000005000019000000010000013b0000000002038019000000c002200210000000000121019f000000010000013b000000200100008a000000240110017f000000400010043f0000002601000029000000800010043f000000010000013b0000000000020435000000400100043d0000002002100039000000400020043f0000000002010019000000010000013b00000000001004350000006501000039000000200010043f00000040020000390000000001000019000000010000013b0000000502500210000000400700043d00000000027200190000002002200039000000000872004b000000010000013b000000400080043f000000000057043500000006085002100000000008860019000000000881004b000000010000013b0000000508500210000000400700043d00000000087800190000002008800039000000000978004b000000010000013b00000000065100190000000007140019000000000707043300000000007604350000002001100039000000010000013b00000000036200190000002002200039000000000412001900000000040404330000000000430435000000010000013b000000400020043f000000000057043500000006025002100000000002260019000000000221004b000000010000013b00000000029a0019000000000ba80019000000000b0b04330000000000b20435000000200aa00039000000010000013b00000000085700190000002007700039000000000967001900000000090904330000000000980435000000010000013b00000020099000390000000000c204350000000000b90435000000010aa000390000004006600039000000010000013b000002800340003900000000002304350000026002400039000000210300002900000000003204350000002402000029000000010000013b000000a002200039000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000010000013b0000001c06000029000000000056043500000000001404350000000000320435000000400100043d001c00000001001d000000010000013b000000400400043d002600000004001d00000040034000390000000000230435000000010000013b0000001d020000290000001f02200039000000200300008a000000000232016f0000001b022000290000001703000029000000010000013b000000400100043d0000004002100039000000400020043f000000200210003900000000003204350000000000010435000000010000013b000000260100002900000005011002100000001c01100029000000000201043300000020022000390000000002020433000000010000013b0000003f02500039000000200300008a000000000232016f000000400300043d0000000002230019000000400020043f0000001f0250018f000000000353043600000003040003670000000505500272000000010000013b0000000001010433000000000101043300000000060504330000000067060434000000010000013b0000800902000039000000000305001900000000050000194bfc44050000040f000000000301034f000000010120018f000300000003035500000000020300190000006002200270000000010000013b00000000020380190000006002200210000000000112019f000000010000013b0000000000730435000000250700002900000000007604350000001a06000029000000000065043500000000001404350000001c010000290000000000210435002500840030003d000000010000013b0000004404300039000000000014043500000024013000390000001a04000029000000000041043500000084013000390000000000210435000000400100043d002200000001001d000000010000013b000000000c02004b000000000c000019000000000c084019000000010000013b0000000001020433000000000015043500000000010204330000000002000019000000010000013b0000002402100069000000030110021000000100011000890000000043020434002400000004001d000000000313022f00000000011301cf0000000000120435000000010000013b00000026020000290000001f02200039000000200300008a000000000232016f0000002502200029000000010000013b00000005012002100000001c01100029000000000101043300000020021000390000000002020433000000010000013b0000000000840435000000260800002900000000008704350000000000160435000000000025043500000025010000290000000000310435002600840040003d000000010000013b00210000000b001d00200000000a001d002200000009035300230000000f001d000000010000013b000000000503001900000000060000194bfc00340000040f000000000101004b000000010000013b0000001a04000029000000000046043500000040033000390000000003030433000000000403004b0000000004000019000000010400c039000000000443004b000000010000013b000000000a96004b000000000700a019000000000696013f000000010000013b0000001f0210008c00000000020000190000000002032019000000010000013b000000400120003900000000010104330000001a0b0000290000002302b0006b000000010000013b000000fc07700039000000ff0770018f001f00000007001d0000001b0770008a000000020770008c000000010000013b0000001f0530008c00000000050000190000000005042019000000010000013b0000002604000029000001400340003900000000002304350000012002400039000000010000013b0000004404300039000000000014043500000024013000390000001904000029000000000041043500000084013000390000000000210435000000400100043d000000010000013b0000004404300039000000000014043500000024013000390000001a04000029000000000041043500000084013000390000000000210435000000400100043d000000010000013b000000000dc2004b000000000d000019000000000d0820190000000002c2013f000000010000013b000000400400043d001700440040003d0000002402400039001c00000004001d0000000404400039000000010000013b000000400400043d001700440040003d0000002402400039001b00000004001d0000000404400039000000010000013b0000000002020433002400000002001d00000000120104344bfc43d70000040f0000002602000029000000010000013b000000400100043d0000004002100039000000400020043f00000020021000390000006003000039000000010000013b00000000007504350000002602000029000000400520003900000040064000390000000006060433000000000065043500000060054000390000000005050433000000010000013b000000400200003900000000010000194bfc43d70000040f000000000101041a000000010000013b00000000001004350000012f01000039000000200010043f000000400200003900000000010000194bfc43d70000040f0000001f02000029000000000021041b000000010000013b000000400300043d002200440030003d0000002402300039002600000003001d0000000403300039000000010000013b0000000000670435000000400600003900000000006404350000000000120435000000010000013b000000200aa000390000000000ed04350000000000ca0435000000010bb000390000004007700039000000010000013b000000400090043f0000000009780436000000200aa00039000000000b7a0019000000260bb0006c000000010000013b000000400500043d00000020065000390000000008860019000000400080043f000000220770035f00000000004504350000001f0840018f0000000509400272000000010000013b0000000004240019000000000004043500000000023200190000000002020433000000010000013b000000400050043f00000000053204360000000006340019000000000116004b000000010000013b000000400600043d002500c40060003d000000a404600039000000840760003900000064086000390000004409600039000000240a600039000000040c600039000000010000013b000000000101043300000020011000390000000001010433000000000101004b000000010000013b0000000001010433001e00000001001d0000000021010434001c00000002001d000000000201004b000000010000013b000003e8431000c900000000411300d9000003e80110008c000000010000013b000000050ba00210000000000cb60019000000000bb7034f000000000b0b043b0000000000bc0435000000010aa00039000000000b9a004b000000010000013b00000000001c04350000000000ba043500000000002904350000000000380435000000a00100003900000000001704350000000000040435000000010000013b000000260300002900000024043000690000002006000039000000220200002900000000050300194bfc00340000040f000000000101004b000000010000013b000000000503004b00000000050000190000000005064019000000010000013b000000260500002900000025035000690000004404300039000000000305001900000000060000194bfc000d0000040f000000000101004b000000010000013b000000000103801900000040011002100000004002200039000000010000013b000027103230011a0000002504200069000000250340006c00000000030000190000000103002039000000000303004b000000000400c019000000010000013b0000001d432000b90000001d543000fa000000000224004b000000010000013b0000000502100210000000000324034f000000000303043b000000a00220003900000000003204350000000101100039000000000251004b000000010000013b000000220300002900000026043000690000002006000039000000240200002900000000050300194bfc00340000040f000000000101004b000000010000013b000027104240011a0000000005230049000000000435004b00000000040000190000000104002039000000000404004b000000000500c019000000010000013b000000000203043300000000230204340000001f0430008c000000010000013b000000400400043d0000004002400039000000400020043f0000002002400039000000000032043500000018050000290000000000540435000000010000013b0000000002020433000000200220003900000000020204330000000001010433000000200110003900000000010104330000000001210019000000010000013b0000000000120435000000400100043d0000000002120049000000010000013b000000000085043500000040022000390000000002020433000000000302004b0000000003000019000000010300c039000000000332004b000000010000013b000000000982004b000000000600a019000000000282013f000000010000013b000000050ed00210000000000fe90019000000000eeb034f000000000e0e043b0000000000ef0435000000010dd00039000000000ecd004b000000010000013b000000000712004b00000000070000190000000007064019000000010000013b000000000763004b000000000400a019000000000363013f000000010000013b000000000513004b00000000050000190000000005044019000000010000013b0000003f0530008c00000000050000190000000005042019000000010000013b0000001f0310008c00000000030000190000000003022019000000010000013b000100000003001f00030000000103550000000001020019000000000001042d000000400500043d0000004004500039000000400040043f0000002004500039000000000034043500000000006504350000000067060434000000010000013b0000000003340019000000200430003900000000022400490000002401100039000000000021043500000026010000290000000001010433000000010000013b000000000816004b00000000080000190000000008074019000000010000013b00000000010104330000000021010434002200000002001d0000000012010434002600000002001d00000000010104330000001702000029000000010000013b00000000010104330000000012010434001800000002001d0000000001010433001d00000001001d002500000000001d002600000000001d000000010000013b0000004000a0043f0000001a09000029000000000079043500000006097002100000000009980019000000000994004b000000010000013b000000260b0000290000000009b7004b00000000090000190000000009084019000000010000013b0000000503200210000000000439034f000000000404043b000000a00330003900000000004304350000000102200039000000010000013b00000026020000290000001f02200039000000200300008a000000000232016f00000025022000290000002303000029000000010000013b00000026020000290000001f02200039000000200300008a000000000232016f00000025022000290000002203000029000000010000013b0000002602000029000000c003200039000000400030043f000000006304043400000000053204360000000003060433000000010000013b000000000c7300490000003f0dc0008c000000000d000019000000000d092019000000010000013b000000260500002900000025045000290000000000040435000000010000013b0000002605000029000000a002500039000000400020043f000000003204043400000000052504360000000002030433000000010000013b00000026050000290000000000450435000000250400002900000000004304350000001a030000290000000000320435000000010000013b000000400cb000390000004000c0043f00000000dc060434000000010000013b00000000030000194bfc43cc0000040f00000040034000390000000003030433000000400400043d002500640040003d00000044054000390000002406400039000000010000013b000000000076043500000000050504330000006406300039000000150800002900000000008604350000000065050434000000010000013b00000000007604350000001a06000029000000000065043500000000001404350000001c010000290000000000210435000000010000013b000000000206043300000000450204340000003f0650008c000000010000013b000000000206043300000000240204340000001f0540008c000000010000013b000000000206043300000000350204340000003f0650008c000000010000013b00000084022000394bfc43c30000040f00000001020000390000002006000039000000200530008a000000010000013b0000000000de04350000000009c90436000000010bb000390000004008800039000000010000013b000000000cb8004b000000000900a0190000000008b8013f000000010000013b0000000000140435002500000004001d00000004014000390000000000210435000000400100043d002600000001001d000000010000013b0000000502700210000000400400043d00000000024200190000002002200039002500000004001d000000000542004b000000010000013b000000000202043300000000030204330000001b0200002900000000020204330000000024020434000000000334013f000000010000013b0000000505700210000000400200043d00000000052500190000002005500039002500000002001d000000000825004b000000010000013b000000400100043d0000004002100039000000400020043f0000002002100039000000010000013b0000000000120435000000400300043d00000000013200490000000001130436000000010000013b000000250300002900000026023000690000008404200039000000010000013b0000002606000029000000000016043500000000002504350000000000340435000000400100043d002600000001001d000000010000013b0000001b030000290000000003030433000000000303043300000000020204330000000002020433000000000232013f000000010000013b0000000509700210000000400b00043d0000000009b90019000000200a900039001a0000000b001d0000000009ba004b000000010000013b0000003f02600039000000200300008a000000000232016f000000400700043d0000000002270019000000000972004b000000010000013b000000400800043d00000000098900190000002009900039000000000a89004b000000010000013b00000000008604350000002008700039000000220880035f000000000808043b000000010000013b0000000000ef0435000000000ada0436000000010cc000390000004009900039000000010000013b000000000102001900000000020400190000000004000019000000000503001900000000060000194bfc000d0000040f000000010000013b0000004006500039000000400060043f000000220740035f000000000707043b000000010000013b0000003f07600039000000200300008a000000000937016f000000400700043d0000000009970019000000000a79004b000000010000013b4bfc43ed0000040f000000c902000039000000000202041a002000000002001d000000ca02000039000000000202041a001f00000002001d002100000001001d000000010000013b0000000000260435000004be029000390000000000120435000000400300043d00000000013200490000000001130436000004de02900039002200000002001d000000400020043f00000000020304334bfc43d70000040f0000002202000029000000010000013b0000000000260435000004be029000390000000000120435000000400300043d00000000013200490000000001130436000004de02900039002400000002001d000000400020043f00000000020304334bfc43d70000040f0000002402000029000000010000013b00000000004304350000000404300039000000600600003900000000006404350000000004050433000000010000013b00000000002904350000000000a8043500000000001704350000000000360435000000c0010000390000000000140435000000010000013b00004bfc0000043200004bfd0001042e00004bfe00010430000000000000000000000000000000000000000000000000000000000000000000000000ffffffff8da5cb5b00000000000000000000000000000000000000000000000000000000d6ca6ab70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d6ca6ab700000000000000000000000000000000000000000000000000000000e2864fe300000000000000000000000000000000000000000000000000000000e99a3f8000000000000000000000000000000000000000000000000000000000eae3ad6f00000000000000000000000000000000000000000000000000000000f2fde38b8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000001000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0ffffffffffffffffffffffff000000000000000000000000000000000000000064647265737300000000000000000000000000000000000000000000000000004f776e61626c653a206e6577206f776e657220697320746865207a65726f206108c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffff0000000000000000000000000000000000000000000000000001000000000000a8af9093caa9beb61d20432227c66258ceef926f21879b80f3adf22a4d19f131000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff0000000000000000000000000000000000000000000000010000000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffde0000000000000000000000000000000000000000000000000ffffffffffffffc0000000000000000000000000000000000000000000000000ffffffffffffff7f000000000000000000000000000000000000000000000000fffffffffffffee0796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132452a0dc408cb0d27ffc3b3caff933a5208040a53a9dbecd8d89cad2c0d40e00cdb6f72e915676cfc289da13bc4ece054fd17b1df6d77ffc4a60510718c236b08477ed43b8020849b755512278536c3766a3b4ab547519949a75f483372493f8d1806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b839a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f19010000000000000000000000000000000000000000000000000000000000001626ba7e000000000000000000000000000000000000000000000000000000006174696f6e206572726f72000000000000000000000000000000000000000000636f6e7472616374206f72646572207369676e6174757265207665726966696345434453413a20696e76616c6964207369676e6174757265206c656e677468007fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1756500000000000000000000000000000000000000000000000000000000000045434453413a20696e76616c6964207369676e6174757265202773272076616c1f0000000000000000000000000000000000000000000000000000000000000019457468657265756d205369676e6564204d6573736167653a0a33320000000045434453413a20696e76616c6964207369676e6174757265202776272076616c6f720000000000000000000000000000000000000000000000000000000000006f72646572207369676e617475726520766572696669636174696f6e206572726e6f206d616b657200000000000000000000000000000000000000000000000045434453413a20696e76616c6964207369676e617475726500000000000000006c656400000000000000000000000000000000000000000000000000000000006c6566744f726465722e74616b657220766572696669636174696f6e20666169696c65640000000000000000000000000000000000000000000000000000000072696768744f726465722e74616b657220766572696669636174696f6e2066616e6f742061206d616b6572000000000000000000000000000000000000000000302073616c742063616e27742062652075736564000000000000000000000000fffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff4c23426600000000000000000000000000000000000000000000000000000000e8d9861dbc9c663ed3accd261bbe2fe01e0d3d9e5f51fa38523b265c7757a93a70bba4f904a93ba5c1af3a1bb602bc9c058551dbe963dfe0b6cb5bc11c5fea9effffffffffff000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000008da5cb5b00000000000000000000000000000000000000000000000000000000b0e21e8a00000000000000000000000000000000000000000000000000000000b39deb4600000000000000000000000000000000000000000000000000000000b74c8e9a00000000000000000000000000000000000000000000000000000000bc158c2da4b009cc442411b602eaf94bc0579b6abdb8fd90b4ef5b9426e270038906bd03d2bf91075f105d0fd80328da28e20ebdad1c1261839711183bc29a44cbe6c72f30c642f1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c642f1000000000000000000000000000000000000000000000000000000003be899220000000000000000000000000000000000000000000000000000000067d49a3b000000000000000000000000000000000000000000000000000000006d8f069400000000000000000000000000000000000000000000000000000000715018a68ae85d8400000000000000000000000000000000000000000000000000000000aaaebeba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffe04b5aced933c0c9a88aeac3f0b3b72c5aaf75df8ebaf53225773248c4c31535934f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572000000000000000000000000000000000000000000000000000000000c53c51c000000000000000000000000000000000000000000000000000000000d5f7d35000000000000000000000000000000000000000000000000000000001372a6250000000000000000000000000000000000000000000000000000000020158c44000000000000000000000000000000000000000000000000000000002d0335abffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff45786368616e6765000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000045786368616e67654d6574615632000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000036c25de3e541d5d970f66e4210d728721220fff5c077cc6cd008b3a0c62adab74532fa16f071d6234e30e1a1e69b9806f04095edf37a1ca7a25c8d6af7861cc030a684095c937b5aa064dcf94f9903a7d808e3efb22d8389dbd43080ad4ed3d5973bb640000000000000000000000000000000000000000000000000000000004b5822151ea34b7c8d9e37c3e466bcecb631efe6a9f26a4a4054110a93dd316f4f726465722073746172742076616c69646174696f6e206661696c65640000004f7264657220656e642076616c69646174696f6e206661696c656400000000006d616b6572206973206e6f742074782073656e6465720000000000000000000073ad2146000000000000000000000000000000000000000000000000000000006d3f7cb00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000006e6f7420666f756e64204941737365744d61746368657200000000000000000023d235ef000000000000000000000000000000000000000000000000000000004ade54ca00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffa00000000000000000000000000000000000000001000000000000000000000000556e6b6e6f776e204f726465722064617461207479706500000000000000000066696c6c52696768743a20756e61626c6520746f2066696c6c00000000000000726f756e64696e67206572726f72000000000000000000000000000000000000956cd63ee4cdcd81fda5f0ec7c6c36dceda99e1b412f4a650a5d26055dc3c4500000000000000000000000000000000000000000ffffffffffffffffffffffff54bc0cf1000000000000000000000000000000000000000000000000000000009c1c2ee900000000000000000000000000000000000000000000000000000000f242432a00000000000000000000000000000000000000000000000000000000776062c300000000000000000000000000000000000000000000000000000000a9059cbb000000000000000000000000000000000000000000000000000000006572633230207472616e73666572206661696c65640000000000000000000000f709b9060000000000000000000000000000000000000000000000000000000042842e0e000000000000000000000000000000000000000000000000000000001cdfaa4000000000000000000000000000000000000000000000000000000000d8f960c100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff60000000000000000000000000000000000000000000000000ffffffffffffff409ca7dc7a00000000000000000000000000000000000000000000000000000000526f79616c746965732061726520746f6f206869676820283e3530252900000053756d207061796f75747320427073206e6f7420657175616c203130302500006e6f7420656e6f7567682065746800000000000000000000000000000000000073666572000000000000000000000000000000000000000000000000000000007472616e736665725061796f7574733a206e6f7468696e6720746f207472616e7700000000000000000000000000000000000000000000000000000000000000536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7472616e73666572206661696c656400000000000000000000000000000000006572633732312076616c7565206572726f720000000000000000000000000000536166654d6174683a206164646974696f6e206f766572666c6f7700000000006f726967696e2066656520697320746f6f2062696700000000000000000000006e6f7468696e6720746f2066696c6c000000000000000000000000000000000066696c6c4c6566743a20756e61626c6520746f2066696c6c00000000000000006469766973696f6e206279207a65726f00000000000000000000000000000000536166654d6174683a207375627472616374696f6e206f766572666c6f77000061737365747320646f6e2774206d617463680000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff8000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff57726f6e672066756e6374696f6e5369676e6174757265000000000000000000726529000000000000000000000000000000000000000000000000000000000064726573732066726f6d2c62797465732066756e6374696f6e5369676e6174754d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616468000000000000000000000000000000000000000000000000000000000000005369676e657220616e64207369676e617475726520646f206e6f74206d6174635845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b46756e6374696f6e2063616c6c206e6f74207375636365737366756c00000000496e76616c6964207369676e61747572650000000000000000000000000000000000000200000000000000000000000000000040000001000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000fffffffffffffffffffffffffffffffe0200000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000097c15ce2f27d6a0b37e7c1887c51e2f45cd21a5fe5796741a07cb62ec742793b

Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.