ETH Price: $3,115.17 (-1.35%)

Contract

0x97c92E24AD06f227bDe161Bc3268040498Ebc96D
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0x60a06040185786232023-11-15 16:57:59370 days ago1700067479IN
 Create: RareMinter
0 ETH0.1654169445.38403058

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RareMinter

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 29 : RareMinter.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;

import {IERC721} from "openzeppelin-contracts/token/ERC721/IERC721.sol";
import {Initializable} from "openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol";
import {OwnableUpgradeable} from "openzeppelin-contracts-upgradeable/access/OwnableUpgradeable.sol";
import {ReentrancyGuardUpgradeable} from "openzeppelin-contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import {UUPSUpgradeable} from "openzeppelin-contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

import {MarketConfig} from "../utils/structs/MarketConfig.sol";
import {MarketUtils} from "../utils/MarketUtils.sol";
import {IERC721Mint} from "./IERC721Mint.sol";
import {IRareMinter} from "./IRareMinter.sol";

/// @author SuperRareLabs Inc.
/// @title RareMinter
/// @notice The logic for all functions related to the RareMinter.
contract RareMinter is Initializable, IRareMinter, OwnableUpgradeable, ReentrancyGuardUpgradeable, UUPSUpgradeable {
  using MarketUtils for MarketConfig.Config;
  using MarketConfig for MarketConfig.Config;

  //////////////////////////////////////////////////////////////////////////
  //                      Private Storage
  //////////////////////////////////////////////////////////////////////////

  // Config for the market actions
  MarketConfig.Config private marketConfig;

  // Mapping of contract address to direct sale config
  mapping(address => DirectSaleConfig) private directSaleConfigs;

  // Mapping of contract address to allow list config
  mapping(address => AllowListConfig) private contractAllowlistRoots;

  // Mapping of contract address to the mint limit for limiting mints per address
  mapping(address => uint256) private contractMintLimit;

  // Mapping of contract address to address to total mints
  mapping(address => mapping(address => uint256)) private contractMintsPerAddress;

  // Mapping of contract address to the mint limit for limiting mints per address
  mapping(address => uint256) private contractTxLimit;

  // Mapping of contract address to address to total mints
  mapping(address => mapping(address => uint256)) private contractTxsPerAddress;

  //////////////////////////////////////////////////////////////////////////
  //                      Initializer
  //////////////////////////////////////////////////////////////////////////
  function initialize(
    address _networkBeneficiary,
    address _marketplaceSettings,
    address _spaceOperatorRegistry,
    address _royaltyEngine,
    address _payments,
    address _approvedTokenRegistry,
    address _stakingSettings,
    address _stakingRegistry
  ) external initializer {
    marketConfig = MarketConfig.generateMarketConfig(
      _networkBeneficiary,
      _marketplaceSettings,
      _spaceOperatorRegistry,
      _royaltyEngine,
      _payments,
      _approvedTokenRegistry,
      _stakingSettings,
      _stakingRegistry
    );
    __Ownable_init();
  }

  //////////////////////////////////////////////////////////////////////////
  //                      External Read Functions
  //////////////////////////////////////////////////////////////////////////
  function getDirectSaleConfig(address _contractAddress) external view returns (DirectSaleConfig memory) {
    return directSaleConfigs[_contractAddress];
  }

  function getContractAllowListConfig(address _contractAddress) external view returns (AllowListConfig memory) {
    return contractAllowlistRoots[_contractAddress];
  }

  function getContractMintLimit(address _contractAddress) external view returns (uint256) {
    return contractMintLimit[_contractAddress];
  }

  function getContractMintsPerAddress(address _contractAddress, address _address) external view returns (uint256) {
    return contractMintsPerAddress[_contractAddress][_address];
  }

  function getContractTxLimit(address _contractAddress) external view returns (uint256) {
    return contractTxLimit[_contractAddress];
  }

  function getContractTxsPerAddress(address _contractAddress, address _address) external view returns (uint256) {
    return contractTxsPerAddress[_contractAddress][_address];
  }

  //////////////////////////////////////////////////////////////////////////
  //                      External Write Functions
  //////////////////////////////////////////////////////////////////////////
  function prepareMintDirectSale(
    address _contractAddress,
    address _currencyAddress,
    uint256 _price,
    uint256 _startTime,
    uint256 _maxMints,
    address payable[] calldata _splitRecipients,
    uint8[] calldata _splitRatios
  ) external {
    require(
      OwnableUpgradeable(_contractAddress).owner() == msg.sender,
      "prepareMintDirectSale::Only mint contract owner can prepare the mint"
    );
    directSaleConfigs[_contractAddress] = DirectSaleConfig(
      msg.sender,
      _currencyAddress,
      _price,
      _startTime,
      _maxMints,
      _splitRecipients,
      _splitRatios
    );
    emit PrepareMintDirectSale(
      _contractAddress,
      _currencyAddress,
      msg.sender,
      _price,
      _startTime,
      _maxMints,
      _splitRecipients,
      _splitRatios
    );
  }

  function setContractAllowListConfig(bytes32 _root, uint256 _endTimestamp, address _contractAddress) external {
    require(
      msg.sender == OwnableUpgradeable(_contractAddress).owner(),
      "setContractAllowListConfig::Only contract owner can set"
    );
    contractAllowlistRoots[_contractAddress] = AllowListConfig(_root, _endTimestamp);
    emit SetContractAllowListConfig(_root, _endTimestamp, _contractAddress);
  }

  function setContractMintLimit(address _contractAddress, uint256 _limit) external {
    require(
      msg.sender == OwnableUpgradeable(_contractAddress).owner(),
      "setContractMintLimit::Only contract owner can set"
    );
    contractMintLimit[_contractAddress] = _limit;
    emit ContractMintLimitSet(_contractAddress, _limit);
  }

  function setContractTxLimit(address _contractAddress, uint256 _limit) external {
    require(
      msg.sender == OwnableUpgradeable(_contractAddress).owner(),
      "setContractTxLimit::Only contract owner can set"
    );
    contractTxLimit[_contractAddress] = _limit;
    emit ContractTxLimitSet(_contractAddress, _limit);
  }

  function mintDirectSale(
    address _contractAddress,
    address _currencyAddress,
    uint256 _price,
    uint8 _numMints,
    bytes32[] calldata _proof
  ) external payable nonReentrant {
    DirectSaleConfig memory directSaleConfig = directSaleConfigs[_contractAddress];
    // Perform checks
    _enforceContractAllowList(_contractAddress, msg.sender, _proof);
    // Num Mint Check
    require(_numMints > 0, "mintDirectSale::Mints must be greater than 0");

    // Contract mint limit check
    require(
      contractMintLimit[_contractAddress] == 0 ||
        contractMintsPerAddress[_contractAddress][msg.sender] + _numMints <= contractMintLimit[_contractAddress],
      "mintDirectSale::Exceeded mint limit for address"
    );

    // Transaction Limit Check
    require(
      contractTxLimit[_contractAddress] == 0 ||
        contractTxsPerAddress[_contractAddress][msg.sender] + 1 <= contractTxLimit[_contractAddress],
      "mintDirectSale::Exceeded transaction limit for address"
    );

    // Max Mints Check
    require(
      directSaleConfig.maxMints == 0 || _numMints <= directSaleConfig.maxMints,
      "mintDirectSale::Mints must be less than maxMint if enabled"
    );
    // Start Time Check
    require(directSaleConfig.startTime <= block.timestamp, "mintDirectSale::Sale has not started");

    // Configured Check
    require(directSaleConfig.seller != address(0), "mintDirectSale::Contract not prepared for direct sale");

    // Price Check
    require(_price == directSaleConfig.price, "mintDirectSale::Price does not match required price");

    // Approved Currency Check
    marketConfig.checkIfCurrencyIsApproved(_currencyAddress);

    // Currency Match Check
    require(
      directSaleConfig.currencyAddress == _currencyAddress,
      "mintDirectSale::Currency does not match required currency"
    );

    uint256 totalPrice = _numMints * _price;
    // Check amount
    if (directSaleConfig.price != 0) {
      uint256 requiredAmount = totalPrice + marketConfig.marketplaceSettings.calculateMarketplaceFee(totalPrice);
      MarketUtils.checkAmountAndTransfer(_currencyAddress, requiredAmount);
    }

    // If Enabled, update mint count
    if (contractMintLimit[_contractAddress] > 0) {
      contractMintsPerAddress[_contractAddress][msg.sender] += _numMints;
    }

    // If Enabled, update tx count
    if (contractTxLimit[_contractAddress] > 0) {
      contractTxsPerAddress[_contractAddress][msg.sender] += 1;
    }

    // Perform Mint
    uint256 tokenIdStart = IERC721Mint(_contractAddress).mintTo(msg.sender); // get first Token Id in range of mint
    try marketConfig.marketplaceSettings.markERC721Token(_contractAddress, tokenIdStart, true) {} catch {}
    for (uint256 i = 1; i < _numMints; i++) {
      // Start with offset of 1 since already minted first
      IERC721Mint(_contractAddress).mintTo(msg.sender);
      try marketConfig.marketplaceSettings.markERC721Token(_contractAddress, tokenIdStart + i, true) {} catch {}
    }

    // Perform payout
    if (directSaleConfig.price != 0) {
      marketConfig.payout(
        _contractAddress,
        tokenIdStart,
        _currencyAddress,
        totalPrice,
        directSaleConfig.seller,
        directSaleConfig.splitRecipients,
        directSaleConfig.splitRatios
      );
    }

    emit MintDirectSale(
      _contractAddress,
      directSaleConfig.seller,
      msg.sender,
      tokenIdStart,
      tokenIdStart + _numMints - 1,
      _currencyAddress,
      _price
    );
  }

  //////////////////////////////////////////////////////////////////////////
  //                      Internal UUPS Functions
  //////////////////////////////////////////////////////////////////////////
  /// @inheritdoc UUPSUpgradeable
  function _authorizeUpgrade(address) internal override onlyOwner {}

  //////////////////////////////////////////////////////////////////////////
  //                      Admin Write Functions
  //////////////////////////////////////////////////////////////////////////
  function setNetworkBeneficiary(address _networkBeneficiary) external onlyOwner {
    marketConfig.updateNetworkBeneficiary(_networkBeneficiary);
  }

  function setMarketplaceSettings(address _marketplaceSettings) external onlyOwner {
    marketConfig.updateMarketplaceSettings(_marketplaceSettings);
  }

  function setSpaceOperatorRegistry(address _spaceOperatorRegistry) external onlyOwner {
    marketConfig.updateSpaceOperatorRegistry(_spaceOperatorRegistry);
  }

  function setRoyaltyEngine(address _royaltyEngine) external onlyOwner {
    marketConfig.updateRoyaltyEngine(_royaltyEngine);
  }

  function setPayments(address _payments) external onlyOwner {
    marketConfig.updatePayments(_payments);
  }

  function setApprovedTokenRegistry(address _approvedTokenRegistry) external onlyOwner {
    marketConfig.updateApprovedTokenRegistry(_approvedTokenRegistry);
  }

  //////////////////////////////////////////////////////////////////////////
  //                      Internal Write Functions
  //////////////////////////////////////////////////////////////////////////
  /// @notice Checks to see if the address is on the contract allow list
  /// @param _contractAddress address The address of the ERC721 contract
  /// @param _address address The address of to be checked against the allow list
  function _enforceContractAllowList(
    address _contractAddress,
    address _address,
    bytes32[] memory _proof
  ) internal view {
    bytes32 root = contractAllowlistRoots[_contractAddress].root;

    // disabled, everyone is allowed
    if (root == bytes32(0)) {
      return;
    }
    // allow list is expired, everyone is allowed
    if (block.timestamp >= contractAllowlistRoots[_contractAddress].endTimestamp) {
      return;
    }
    require(
      _verifyProof(keccak256(abi.encodePacked(_address)), root, _proof),
      "_enforceAllowListed::Address not on allow list"
    );
  }

  /// @notice Verify a proof of inclusion
  /// @param _leaf bytes32 The leaf to verify
  /// @param _proof bytes32[] The proof to verify
  function _verifyProof(bytes32 _leaf, bytes32 _root, bytes32[] memory _proof) internal view returns (bool) {
    bytes32 currentHash = _leaf;

    for (uint256 i = 0; i < _proof.length; i++) {
      currentHash = _parentHash(currentHash, _proof[i]);
    }

    return currentHash == _root;
  }

  /// @notice Calculate the parent hash of two nodes
  /// @param a bytes32 The first node
  /// @param b bytes32 The second node
  function _parentHash(bytes32 a, bytes32 b) internal pure returns (bytes32) {
    return a <= b ? keccak256(abi.encodePacked(a, b)) : keccak256(abi.encodePacked(b, a));
  }
}

File 2 of 29 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

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

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

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

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

File 3 of 29 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.2;

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

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     * @custom:oz-retyped-from bool
     */
    uint8 private _initialized;

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

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint8 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
     * constructor.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        bool isTopLevelCall = !_initializing;
        require(
            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
            "Initializable: contract is already initialized"
        );
        _initialized = 1;
        if (isTopLevelCall) {
            _initializing = true;
        }
        _;
        if (isTopLevelCall) {
            _initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: setting the version to 255 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint8 version) {
        require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
        _initialized = version;
        _initializing = true;
        _;
        _initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        require(!_initializing, "Initializable: contract is initializing");
        if (_initialized != type(uint8).max) {
            _initialized = type(uint8).max;
            emit Initialized(type(uint8).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint8) {
        return _initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _initializing;
    }
}

File 4 of 29 : OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";

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

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

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

    function __Ownable_init_unchained() internal onlyInitializing {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

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

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

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

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}

File 5 of 29 : ReentrancyGuardUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuardUpgradeable is Initializable {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    function __ReentrancyGuard_init() internal onlyInitializing {
        __ReentrancyGuard_init_unchained();
    }

    function __ReentrancyGuard_init_unchained() internal onlyInitializing {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}

File 6 of 29 : UUPSUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)

pragma solidity ^0.8.0;

import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
import "./Initializable.sol";

/**
 * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
 * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
 *
 * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
 * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
 * `UUPSUpgradeable` with a custom implementation of upgrades.
 *
 * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
 *
 * _Available since v4.1._
 */
abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
    function __UUPSUpgradeable_init() internal onlyInitializing {
    }

    function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
    }
    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
    address private immutable __self = address(this);

    /**
     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is
     * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
     * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
     * fail.
     */
    modifier onlyProxy() {
        require(address(this) != __self, "Function must be called through delegatecall");
        require(_getImplementation() == __self, "Function must be called through active proxy");
        _;
    }

    /**
     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be
     * callable on the implementing contract but not through proxies.
     */
    modifier notDelegated() {
        require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
        _;
    }

    /**
     * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
     * implementation. It is used to validate the implementation's compatibility when performing an upgrade.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
     */
    function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
        return _IMPLEMENTATION_SLOT;
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     *
     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
     */
    function upgradeTo(address newImplementation) public virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
     * encoded in `data`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     *
     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
     */
    function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallUUPS(newImplementation, data, true);
    }

    /**
     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
     * {upgradeTo} and {upgradeToAndCall}.
     *
     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
     *
     * ```solidity
     * function _authorizeUpgrade(address) internal override onlyOwner {}
     * ```
     */
    function _authorizeUpgrade(address newImplementation) internal virtual;

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

File 7 of 29 : MarketConfig.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IApprovedTokenRegistry} from "rareprotocol/aux/registry/interfaces/IApprovedTokenRegistry.sol";
import {IStakingSettings} from "rareprotocol/aux/marketplace/IStakingSettings.sol";
import {IMarketplaceSettings} from "rareprotocol/aux/marketplace/IMarketplaceSettings.sol";
import {ISpaceOperatorRegistry} from "rareprotocol/aux/registry/interfaces/ISpaceOperatorRegistry.sol";
import {IPayments} from "rareprotocol/aux/payments/IPayments.sol";
import {IRoyaltyEngineV1} from "royalty-registry/IRoyaltyEngineV1.sol";

import {IRareStakingRegistry} from "../../staking/registry/IRareStakingRegistry.sol";

library MarketConfig {
  struct Config {
    address networkBeneficiary;
    IMarketplaceSettings marketplaceSettings;
    ISpaceOperatorRegistry spaceOperatorRegistry;
    IRoyaltyEngineV1 royaltyEngine;
    IPayments payments;
    IApprovedTokenRegistry approvedTokenRegistry;
    IStakingSettings stakingSettings;
    IRareStakingRegistry stakingRegistry;
  }
  event NetworkBeneficiaryUpdated(address indexed newNetworkBeneficiary);
  event MarketplaceSettingsUpdated(address indexed newMarketplaceSettings);
  event SpaceOperatorRegistryUpdated(address indexed newSpaceOperatorRegistry);
  event RoyaltyEngineUpdated(address indexed newRoyaltyEngine);
  event PaymentsUpdated(address indexed newPayments);
  event ApprovedTokenRegistryUpdated(address indexed newApprovedTokenRegistry);
  event StakingSettingsUpdated(address indexed newStakingSettings);
  event StakingRegistryUpdated(address indexed newStakingRegistry);

  function generateMarketConfig(
    address _networkBeneficiary,
    address _marketplaceSettings,
    address _spaceOperatorRegistry,
    address _royaltyEngine,
    address _payments,
    address _approvedTokenRegistry,
    address _stakingSettings,
    address _stakingRegistry
  ) public pure returns (Config memory) {
    require(_networkBeneficiary != address(0), "generateMarketConfig::Network beneficiary address cannot be zero");
    require(_marketplaceSettings != address(0), "generateMarketConfig::Marketplace settings address cannot be zero");
    require(_spaceOperatorRegistry != address(0), "generateMarketConfig::Space operator registry address cannot be zero");
    require(_royaltyEngine != address(0), "generateMarketConfig::Royalty engine address cannot be zero");
    require(_payments != address(0), "generateMarketConfig::Payments address cannot be zero");
    require(_approvedTokenRegistry != address(0), "generateMarketConfig::Approved token registry address cannot be zero");
    require(_stakingSettings != address(0), "generateMarketConfig::Staking settings address cannot be zero");
    require(_stakingRegistry != address(0), "generateMarketConfig::Staking registry address cannot be zero");
    return
      MarketConfig.Config(
        _networkBeneficiary,
        IMarketplaceSettings(_marketplaceSettings),
        ISpaceOperatorRegistry(_spaceOperatorRegistry),
        IRoyaltyEngineV1(_royaltyEngine),
        IPayments(_payments),
        IApprovedTokenRegistry(_approvedTokenRegistry),
        IStakingSettings(_stakingSettings),
        IRareStakingRegistry(_stakingRegistry)
      );
  }

  function updateNetworkBeneficiary(Config storage _config, address _networkBeneficiary) public {
    _config.networkBeneficiary = _networkBeneficiary;
    emit NetworkBeneficiaryUpdated(_networkBeneficiary);
  }

  function updateMarketplaceSettings(Config storage _config, address _marketplaceSettings) public {
    _config.marketplaceSettings = IMarketplaceSettings(_marketplaceSettings);
    emit MarketplaceSettingsUpdated(_marketplaceSettings);
  }

  function updateSpaceOperatorRegistry(Config storage _config, address _spaceOperatorRegistry) public {
    _config.spaceOperatorRegistry = ISpaceOperatorRegistry(_spaceOperatorRegistry);
    emit SpaceOperatorRegistryUpdated(_spaceOperatorRegistry);
  }

  function updateRoyaltyEngine(Config storage _config, address _royaltyEngine) public {
    _config.royaltyEngine = IRoyaltyEngineV1(_royaltyEngine);
    emit RoyaltyEngineUpdated(_royaltyEngine);
  }

  function updatePayments(Config storage _config, address _payments) public {
    _config.payments = IPayments(_payments);
    emit PaymentsUpdated(_payments);
  }

  function updateApprovedTokenRegistry(Config storage _config, address _approvedTokenRegistry) public {
    _config.approvedTokenRegistry = IApprovedTokenRegistry(_approvedTokenRegistry);
    emit ApprovedTokenRegistryUpdated(_approvedTokenRegistry);
  }

  function updateStakingSettings(Config storage _config, address _stakingSettings) public {
    _config.stakingSettings = IStakingSettings(_stakingSettings);
    emit StakingSettingsUpdated(_stakingSettings);
  }

  function updateStakingRegistry(Config storage _config, address _stakingRegistry) public {
    _config.stakingRegistry = IRareStakingRegistry(_stakingRegistry);
    emit StakingRegistryUpdated(_stakingRegistry);
  }
}

File 8 of 29 : MarketUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol";
import {IERC721} from "openzeppelin-contracts/token/ERC721/IERC721.sol";
import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
import {IPayments} from "rareprotocol/aux/payments/IPayments.sol";
import {MarketConfig} from "./structs/MarketConfig.sol";

library MarketUtils {
  using SafeERC20 for IERC20;

  /// @notice Checks to see if the currenccy address is eth or an approved erc20 token.
  /// @param _currencyAddress Address of currency (Zero address if eth).
  function checkIfCurrencyIsApproved(MarketConfig.Config storage _config, address _currencyAddress) internal view {
    require(
      _currencyAddress == address(0) || _config.approvedTokenRegistry.isApprovedToken(_currencyAddress),
      "Not approved currency"
    );
  }

  /// @notice Checks to see if the msg sender owns the token.
  /// @param _originContract Contract address of the token being checked.
  /// @param _tokenId Token Id of the asset.
  function senderMustBeTokenOwner(address _originContract, uint256 _tokenId) internal view {
    IERC721 erc721 = IERC721(_originContract);
    require(erc721.ownerOf(_tokenId) == msg.sender, "sender must be the token owner");
  }

  /// @notice Checks to see if the owner of the token has the marketplace approved.
  /// @param _addr Being checked if they've approved for all
  /// @param _originContract Contract address of the token being checked.
  function addressMustHaveMarketplaceApprovedForNFT(address _addr, address _originContract) internal view {
    IERC721 erc721 = IERC721(_originContract);
    require(erc721.isApprovedForAll(_addr, address(this)), "owner must have approved contract");
  }

  /// @notice Verifies that the splits supplied are valid.
  /// @dev A valid split has the same number of splits and ratios.
  /// @dev There can only be a max of 5 parties split with.
  /// @dev Total of the ratios should be 100 which is relative.
  /// @param _splitAddrs The addresses the amount is being split with.
  /// @param _splitRatios The ratios each address in _splits is getting.
  function checkSplits(address payable[] calldata _splitAddrs, uint8[] calldata _splitRatios) internal pure {
    require(_splitAddrs.length > 0, "checkSplits::Must have at least 1 split");
    require(_splitAddrs.length <= 5, "checkSplits::Split exceeded max size");
    require(_splitAddrs.length == _splitRatios.length, "checkSplits::Splits and ratios must be equal");
    uint256 totalRatio = 0;

    for (uint256 i = 0; i < _splitRatios.length; i++) {
      totalRatio += _splitRatios[i];
    }

    require(totalRatio == 100, "checkSplits::Total must be equal to 100");
  }

  /// @notice Checks to see if the sender has approved the marketplace to move tokens.
  /// @dev This is for offers/buys/bids and the allowance of erc20 tokens.
  /// @dev Returns on zero address because no allowance is needed for eth.
  /// @param _currency The address of the currency being checked.
  /// @param _amount The total amount being checked.
  function senderMustHaveMarketplaceApproved(address _currency, uint256 _amount) internal view {
    if (_currency == address(0)) {
      return;
    }

    IERC20 erc20 = IERC20(_currency);

    require(erc20.allowance(msg.sender, address(this)) >= _amount, "sender needs to approve marketplace for currency");
  }

  /// @notice Checks the user has the correct amount and transfers to the marketplace.
  /// @dev If the currency used is eth (zero address) the msg value is checked.
  /// @dev If eth isnt used and eth is sent we revert the txn.
  /// @dev We need to check this contracts balance before and after the transfer to ensure no fee.
  /// @param _currencyAddress Currency address being checked and transfered.
  /// @param _amount Total amount of currency.
  function checkAmountAndTransfer(address _currencyAddress, uint256 _amount) internal {
    if (_currencyAddress == address(0)) {
      require(msg.value == _amount, "not enough eth sent");
      return;
    }

    require(msg.value == 0, "msg.value should be 0 when not using eth");

    IERC20 erc20 = IERC20(_currencyAddress);
    uint256 balanceBefore = erc20.balanceOf(address(this));

    erc20.safeTransferFrom(msg.sender, address(this), _amount);

    uint256 balanceAfter = erc20.balanceOf(address(this));

    require(balanceAfter - balanceBefore == _amount, "not enough tokens transfered");
  }

  /// @notice Refunds an address the designated amount.
  /// @dev Return if amount being refunded is zero.
  /// @dev Forwards to payment contract if eth is being refunded.
  /// @param _currencyAddress Address of currency being refunded.
  /// @param _amount Amount being refunded.
  /// @param _marketplaceFee Marketplace Fee (percentage) paid by _recipient.
  /// @param _recipient Address amount is being refunded to.
  function refund(
    MarketConfig.Config storage _config,
    address _currencyAddress,
    uint256 _amount,
    uint256 _marketplaceFee,
    address _recipient
  ) internal {
    if (_amount == 0) {
      return;
    }

    uint256 requiredAmount = _amount + ((_amount * _marketplaceFee) / 100);

    if (_currencyAddress == address(0)) {
      (bool success, bytes memory data) = address(_config.payments).call{value: requiredAmount}(
        abi.encodeWithSignature("refund(address,uint256)", _recipient, requiredAmount)
      );

      require(success, string(data));
      return;
    }

    IERC20 erc20 = IERC20(_currencyAddress);
    erc20.safeTransfer(_recipient, requiredAmount);
  }

  /// @notice Sends a payout to all the necessary parties.
  /// @dev Note that _splitAddrs and _splitRatios are not checked for validity. Make sure supplied values are correct by using _checkSplits. 
  /// @dev Sends payments to the network, royalty if applicable, and splits for the rest.
  /// @dev Forwards payments to the payment contract if payout is happening in eth.
  /// @dev Total amount of ratios should be 100 and is relative to the total ratio left.
  /// @param _originContract Contract address of asset triggering a payout.
  /// @param _tokenId Token Id of the asset.
  /// @param _currencyAddress Address of currency being paid out.
  /// @param _amount Total amount to be paid out.
  /// @param _seller Address of the person selling the asset.
  /// @param _splitAddrs Addresses that funds need to be split against.
  /// @param _splitRatios Ratios for split pertaining to each address.
  function payout(
    MarketConfig.Config storage _config,
    address _originContract,
    uint256 _tokenId,
    address _currencyAddress,
    uint256 _amount,
    address _seller,
    address payable[] memory _splitAddrs,
    uint8[] memory _splitRatios
  ) internal {
    require(_splitAddrs.length == _splitRatios.length, "Number of split addresses and ratios must be equal.");

    /*
        The overall flow for payouts is:
            1. Payout marketplace fee
            2. Primary/Secondary Payouts
                a. Primary -> If space sale, query space operator registry for platform comission and payout
                              Else query marketplace setting for primary sale comission and payout
                b. Secondary -> Query global royalty registry for recipients and amounts and payout
            3. Calculate the amount for each _splitAddr based on remaining amount and payout
         */

    uint256 remainingAmount = _amount;

    // Marketplace fee
    uint256 marketplaceFee = _config.marketplaceSettings.calculateMarketplaceFee(_amount);

    address payable[] memory mktFeeRecip = new address payable[](2);
    mktFeeRecip[0] = payable(_config.networkBeneficiary);
    mktFeeRecip[1] = payable(_config.stakingRegistry.getRewardAccumulatorAddressForUser(_seller));
    mktFeeRecip[1] = mktFeeRecip[1] == address(0) ? payable(_config.networkBeneficiary) : mktFeeRecip[1];
    uint256[] memory mktFee = new uint256[](2);
    mktFee[0] = _config.stakingSettings.calculateMarketplacePayoutFee(_amount);
    mktFee[1] = _config.stakingSettings.calculateStakingFee(_amount);

    performPayouts(_config, _currencyAddress, marketplaceFee, mktFeeRecip, mktFee);

    if (!_config.marketplaceSettings.hasERC721TokenSold(_originContract, _tokenId)) {
      uint256[] memory platformFee = new uint256[](1);
      address payable[] memory platformRecip = new address payable[](1);
      platformRecip[0] = mktFeeRecip[0];

      if (_config.spaceOperatorRegistry.isApprovedSpaceOperator(_seller)) {
        uint256 platformCommission = _config.spaceOperatorRegistry.getPlatformCommission(_seller);

        remainingAmount = remainingAmount - ((_amount * platformCommission) / 100);

        platformFee[0] = (_amount * platformCommission) / 100;

        performPayouts(_config, _currencyAddress, platformFee[0], platformRecip, platformFee);
      } else {
        uint256 platformCommission = _config.marketplaceSettings.getERC721ContractPrimarySaleFeePercentage(
          _originContract
        );

        remainingAmount = remainingAmount - ((_amount * platformCommission) / 100);

        platformFee[0] = (_amount * platformCommission) / 100;

        performPayouts(_config, _currencyAddress, platformFee[0], platformRecip, platformFee);
      }
    } else {
      (address payable[] memory receivers, uint256[] memory royalties) = _config.royaltyEngine.getRoyalty(
        _originContract,
        _tokenId,
        _amount
      );

      uint256 totalRoyalties = 0;

      for (uint256 i = 0; i < royalties.length; i++) {
        totalRoyalties += royalties[i];
      }

      remainingAmount -= totalRoyalties;
      performPayouts(_config, _currencyAddress, totalRoyalties, receivers, royalties);
    }

    uint256[] memory remainingAmts = new uint256[](_splitAddrs.length);

    uint256 totalSplit = 0;

    for (uint256 i = 0; i < _splitAddrs.length; i++) {
      remainingAmts[i] = (remainingAmount * _splitRatios[i]) / 100;
      totalSplit += (remainingAmount * _splitRatios[i]) / 100;
    }
    performPayouts(_config, _currencyAddress, totalSplit, _splitAddrs, remainingAmts);
  }

  function performPayouts(
    MarketConfig.Config storage _config,
    address _currencyAddress,
    uint256 _amount,
    address payable[] memory _recipients,
    uint256[] memory _amounts
  ) internal {
    if (_currencyAddress == address(0)) {
      (bool success, bytes memory data) = address(_config.payments).call{value: _amount}(
        abi.encodeWithSelector(IPayments.payout.selector, _recipients, _amounts)
      );

      require(success, string(data));
    } else {
      IERC20 erc20 = IERC20(_currencyAddress);

      for (uint256 i = 0; i < _recipients.length; i++) {
        erc20.safeTransfer(_recipients[i], _amounts[i]);
      }
    }
  }
}

File 9 of 29 : IERC721Mint.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @author SuperRare Labs Inc.
/// @title IERC721Mint
/// @notice Interface for Minting ERC721
interface IERC721Mint {
  /**
   * @notice Mint a new token to the specified receiver.
   * @param _receiver The address of the token receiver.
   * @return uint256 Token Id of the new token.
   */
  function mintTo(address _receiver) external returns (uint256);
}

File 10 of 29 : IRareMinter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @author SuperRare Labs Inc.
/// @title IRareMinter
/// @notice Interface for the RareMinter
interface IRareMinter {
  //////////////////////////////////////////////////////////////////////////
  //                      Structs
  //////////////////////////////////////////////////////////////////////////
  /// @notice Direct sale config
  struct DirectSaleConfig {
    address seller;
    address currencyAddress;
    uint256 price;
    uint256 startTime;
    uint256 maxMints;
    address payable[] splitRecipients;
    uint8[] splitRatios;
  }

  /// @notice Allow list config
  struct AllowListConfig {
    bytes32 root;
    uint256 endTimestamp;
  }

  //////////////////////////////////////////////////////////////////////////
  //                      Events
  //////////////////////////////////////////////////////////////////////////
  /// @notice Event emitted when a contract is prepared for direct sale
  event PrepareMintDirectSale(
    address indexed _contractAddress,
    address indexed _currency,
    address indexed _seller,
    uint256 _price,
    uint256 _startTime,
    uint256 _maxMints,
    address payable[] splitRecipients,
    uint8[] splitRatios
  );

  /// @notice Event emitted when a contract is prepared for direct sale
  event MintDirectSale(
    address indexed _contractAddress,
    address indexed _seller,
    address indexed _buyer,
    uint256 _tokenIdStart,
    uint256 _tokenIdEnd,
    address _currency,
    uint256 _price
  );

  /// @notice Event emitted when a contract is set to an allow list config
  event SetContractAllowListConfig(bytes32 indexed _root, uint256 _endTimestamp, address indexed _contractAddress);

  /// @notice Event emitted when a contract is set to a mint limit
  event ContractMintLimitSet(address indexed contractAddress, uint256 limit);

  /// @notice Event emitted when a contract is set to a tx limit
  event ContractTxLimitSet(address indexed contractAddress, uint256 limit);

  //////////////////////////////////////////////////////////////////////////
  //                        External Read Functions
  //////////////////////////////////////////////////////////////////////////

  /// @notice Gets the direct sale config for a contract
  /// @param _contractAddress address The address of the ERC721 contract
  /// @return DirectSaleConfig The direct sale config
  function getDirectSaleConfig(address _contractAddress) external view returns (DirectSaleConfig memory);

  /// @notice Gets the allow list config for a contract
  /// @param _contractAddress address The address of the ERC721 contract
  /// @return AllowListConfig The allow list config
  function getContractAllowListConfig(address _contractAddress) external view returns (AllowListConfig memory);

  /// @notice Gets the mint limit for a contract
  /// @param _contractAddress address The address of the ERC721 contract
  /// @return uint256 The mint limit
  function getContractMintLimit(address _contractAddress) external view returns (uint256);

  /// @notice Gets the number of mints per address for a contract
  /// @param _contractAddress address The address of the ERC721 contract
  /// @param _address address The address of the account to get the mints for
  function getContractMintsPerAddress(address _contractAddress, address _address) external view returns (uint256);

  /// @notice Gets the tx limit for a contract
  /// @param _contractAddress address The address of the ERC721 contract
  function getContractTxLimit(address _contractAddress) external view returns (uint256);

  /// @notice Gets the number of txs per address for a contract
  /// @param _contractAddress address The address of the ERC721 contract
  /// @param _address address The address of the account to get the txs for
  function getContractTxsPerAddress(address _contractAddress, address _address) external view returns (uint256);

  //////////////////////////////////////////////////////////////////////////
  //                        External Write Functions
  //////////////////////////////////////////////////////////////////////////

  /// @notice Prepares a minting contract for direct sales
  /// @param _contractAddress address The address of the ERC721 contract
  /// @param _currencyAddress address The address of the currency to accept
  /// @param _maxMints uint256 The max number of tokens to mint per transaction
  /// @param _price uint256 The price to mint each token
  /// @param _splitRecipients address payable[] The addresses to split the sale with
  /// @param _splitRatios uint8[] The ratios to split the sale with
  function prepareMintDirectSale(
    address _contractAddress,
    address _currencyAddress,
    uint256 _price,
    uint256 _startTime,
    uint256 _maxMints,
    address payable[] calldata _splitRecipients,
    uint8[] calldata _splitRatios
  ) external;

  /// @notice Mints a token to the buyer
  /// @param _contractAddress address The address of the ERC721 contract
  /// @param _currencyAddress address The address of the currency
  /// @param _price uint256 The price to mint
  /// @param _numMints uint8 The number of tokens to be minted
  /// @param _proof bytes32[] The merkle proof for the allowlist if applicable, otherwise empty array
  function mintDirectSale(
    address _contractAddress,
    address _currencyAddress,
    uint256 _price,
    uint8 _numMints,
    bytes32[] calldata _proof
  ) external payable;

  /// @notice Sets the allow list config for a contract
  /// @param _root bytes32 The root of the merkle tree
  /// @param _endTimestamp uint256 The timestamp when the allow list ends
  /// @param _contractAddress address The address of the ERC721 contract
  function setContractAllowListConfig(bytes32 _root, uint256 _endTimestamp, address _contractAddress) external;

  /// @notice Sets the mint limit for a contract
  /// @param _contractAddress address The address of the ERC721 contract
  /// @param _limit uint256 The limit to set
  function setContractMintLimit(address _contractAddress, uint256 _limit) external;

  /// @notice Sets the tx limit for a contract
  /// @param _contractAddress address The address of the ERC721 contract
  /// @param _limit uint256 The limit to set
  function setContractTxLimit(address _contractAddress, uint256 _limit) external;
}

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

pragma solidity ^0.8.0;

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

File 12 of 29 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/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.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

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

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

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // 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
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 13 of 29 : ContextUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";

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

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

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

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

File 14 of 29 : draft-IERC1822Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
 * proxy whose upgrades are fully controlled by the current implementation.
 */
interface IERC1822ProxiableUpgradeable {
    /**
     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
     * address.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy.
     */
    function proxiableUUID() external view returns (bytes32);
}

File 15 of 29 : ERC1967UpgradeUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)

pragma solidity ^0.8.2;

import "../beacon/IBeaconUpgradeable.sol";
import "../../interfaces/IERC1967Upgradeable.sol";
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/StorageSlotUpgradeable.sol";
import "../utils/Initializable.sol";

/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 *
 * _Available since v4.1._
 */
abstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {
    function __ERC1967Upgrade_init() internal onlyInitializing {
    }

    function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
    }
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;

    /**
     * @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 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
        StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
        _upgradeTo(newImplementation);
        if (data.length > 0 || forceCall) {
            AddressUpgradeable.functionDelegateCall(newImplementation, data);
        }
    }

    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
        // Upgrades from old implementations will perform a rollback test. This test requires the new
        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
        // this special case will break upgrade paths from old UUPS implementation to new ones.
        if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {
            _setImplementation(newImplementation);
        } else {
            try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
            } catch {
                revert("ERC1967Upgrade: new implementation is not UUPS");
            }
            _upgradeToAndCall(newImplementation, data, forceCall);
        }
    }

    /**
     * @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 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
        StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @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 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
        require(
            AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
            "ERC1967: beacon implementation is not a contract"
        );
        StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }

    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length > 0 || forceCall) {
            AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
        }
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

File 16 of 29 : IApprovedTokenRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IApprovedTokenRegistry {
    /// @notice Returns if a token has been approved or not.
    /// @param _tokenContract Contract of token being checked.
    /// @return True if the token is allowed, false otherwise.
    function isApprovedToken(address _tokenContract)
        external
        view
        returns (bool);

    /// @notice Adds a token to the list of approved tokens.
    /// @param _tokenContract Contract of token being approved.
    function addApprovedToken(address _tokenContract) external;

    /// @notice Removes a token from the approved tokens list.
    /// @param _tokenContract Contract of token being approved.
    function removeApprovedToken(address _tokenContract) external;

    /// @notice Sets whether all token contracts should be approved.
    /// @param _allTokensApproved Bool denoting if all tokens should be approved.
    function setAllTokensApproved(bool _allTokensApproved) external;
}

File 17 of 29 : IStakingSettings.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title IStakingSettings Settings governing a staking config for a marketplace.
 */
interface IStakingSettings {
    /**
     * @dev Get the staking percentage.
     * @return uint8 wei staking fee percentage.
     */
    function getStakingFeePercentage() external view returns (uint8);

    /**
     * @dev Utility function for calculating the staking fee for given amount of wei.
     * @param _amount uint256 wei amount.
     * @return uint256 wei fee.
     */
    function calculateStakingFee(uint256 _amount)
        external
        view
        returns (uint256);

    /**
     * @dev Utility function for calculating the marketplace payout fee for given amount of wei. marketplaceFee - stakingFee
     * @param _amount uint256 wei amount.
     * @return uint256 wei fee.
     */
    function calculateMarketplacePayoutFee(uint256 _amount)
        external
        view
        returns (uint256);
}

File 18 of 29 : IMarketplaceSettings.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title IMarketplaceSettings Settings governing a marketplace.
 */
interface IMarketplaceSettings {
    /////////////////////////////////////////////////////////////////////////
    // Marketplace Min and Max Values
    /////////////////////////////////////////////////////////////////////////
    /**
     * @dev Get the max value to be used with the marketplace.
     * @return uint256 wei value.
     */
    function getMarketplaceMaxValue() external view returns (uint256);

    /**
     * @dev Get the max value to be used with the marketplace.
     * @return uint256 wei value.
     */
    function getMarketplaceMinValue() external view returns (uint256);

    /////////////////////////////////////////////////////////////////////////
    // Marketplace Fee
    /////////////////////////////////////////////////////////////////////////
    /**
     * @dev Get the marketplace fee percentage.
     * @return uint8 wei fee.
     */
    function getMarketplaceFeePercentage() external view returns (uint8);

    /**
     * @dev Utility function for calculating the marketplace fee for given amount of wei.
     * @param _amount uint256 wei amount.
     * @return uint256 wei fee.
     */
    function calculateMarketplaceFee(uint256 _amount)
        external
        view
        returns (uint256);

    /////////////////////////////////////////////////////////////////////////
    // Primary Sale Fee
    /////////////////////////////////////////////////////////////////////////
    /**
     * @dev Get the primary sale fee percentage for a specific ERC721 contract.
     * @param _contractAddress address ERC721Contract address.
     * @return uint8 wei primary sale fee.
     */
    function getERC721ContractPrimarySaleFeePercentage(address _contractAddress)
        external
        view
        returns (uint8);

    /**
     * @dev Utility function for calculating the primary sale fee for given amount of wei
     * @param _contractAddress address ERC721Contract address.
     * @param _amount uint256 wei amount.
     * @return uint256 wei fee.
     */
    function calculatePrimarySaleFee(address _contractAddress, uint256 _amount)
        external
        view
        returns (uint256);

    /**
     * @dev Check whether the ERC721 token has sold at least once.
     * @param _contractAddress address ERC721Contract address.
     * @param _tokenId uint256 token ID.
     * @return bool of whether the token has sold.
     */
    function hasERC721TokenSold(address _contractAddress, uint256 _tokenId)
        external
        view
        returns (bool);

    /**
     * @dev Mark a token as sold.
     * Requirements:
     *
     * - `_contractAddress` cannot be the zero address.
     * @param _contractAddress address ERC721Contract address.
     * @param _tokenId uint256 token ID.
     * @param _hasSold bool of whether the token should be marked sold or not.
     */
    function markERC721Token(
        address _contractAddress,
        uint256 _tokenId,
        bool _hasSold
    ) external;

    function setERC721ContractPrimarySaleFeePercentage(
        address _contractAddress,
        uint8 _percentage
    ) external;
}

File 19 of 29 : ISpaceOperatorRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @author koloz
/// @title ISpaceOperatorRegistry
/// @notice The interface for the SpaceOperatorRegistry
interface ISpaceOperatorRegistry {
    function getPlatformCommission(address _operator)
        external
        view
        returns (uint8);

    function setPlatformCommission(address _operator, uint8 _commission)
        external;

    function isApprovedSpaceOperator(address _operator)
        external
        view
        returns (bool);

    function setSpaceOperatorApproved(address _operator, bool _approved)
        external;
}

File 20 of 29 : IPayments.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @author koloz
/// @title IPayments
/// @notice Interface for the Payments contract used.
interface IPayments {
    function refund(address _payee, uint256 _amount) external payable;

    function payout(address[] calldata _splits, uint256[] calldata _amounts)
        external
        payable;
}

File 21 of 29 : IRoyaltyEngineV1.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/**
 * @dev Lookup engine interface
 */
interface IRoyaltyEngineV1 is IERC165 {
    /**
     * Get the royalty for a given token (address, id) and value amount.  Does not cache the bps/amounts.  Caches the spec for a given token address
     *
     * @param tokenAddress - The address of the token
     * @param tokenId      - The id of the token
     * @param value        - The value you wish to get the royalty of
     *
     * returns Two arrays of equal length, royalty recipients and the corresponding amount each recipient should get
     */
    function getRoyalty(address tokenAddress, uint256 tokenId, uint256 value)
        external
        returns (address payable[] memory recipients, uint256[] memory amounts);

    /**
     * View only version of getRoyalty
     *
     * @param tokenAddress - The address of the token
     * @param tokenId      - The id of the token
     * @param value        - The value you wish to get the royalty of
     *
     * returns Two arrays of equal length, royalty recipients and the corresponding amount each recipient should get
     */
    function getRoyaltyView(address tokenAddress, uint256 tokenId, uint256 value)
        external
        view
        returns (address payable[] memory recipients, uint256[] memory amounts);
}

File 22 of 29 : IRareStakingRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @author koloz, charlescrain
/// @title IRareStakingRegistry
/// @notice The Staking Registry interface containing all functions, events, etc.
interface IRareStakingRegistry {
  /*//////////////////////////////////////////////////////////////////////////
                              Structs
  //////////////////////////////////////////////////////////////////////////*/

  /// @notice A struct holding the information about the target's staking contract.
  /// @dev Target being staked on is omitted as it's the key in the mapping used.
  struct Info {
    string name;
    string symbol;
    address stakingAddress;
    address rewardAddress;
  }

  /*//////////////////////////////////////////////////////////////////////////
                              Events
  //////////////////////////////////////////////////////////////////////////*/

  /// @notice Emitted via {setDefaultPayee} when the defaultPayee is updated.
  event DefaultPayeeUpdated(address _payee);

  /// @notice Emitted via {setDeflationaryPercentage} when the deflationaryPercentage is updated.
  event DeflationaryPercentageUpdated(uint256 _percentage);

  /// @notice Emitted via {setDiscountPercentage} when the discountedPercent is updated.
  event DiscountPercentageUpdated(uint256 _percentage);

  /// @notice Emitted via {setPeriodLength} when the periodLength is updated.
  event PeriodLengthUpdated(uint256 _periodLength);

  /// @notice Emitted via {setReverseRegistrar} when the ENS reverse registrar is updated.
  event ReverseRegistrarUpdated(address _percentage);

  /// @notice Emitted via {setResolver} when the ENS resolver is updated.
  event ResolverUpdated(address _resolver);

  /// @notice Emitted via {setSwapPool} when a new swap pool has been set.
  event SetSwapPool(address _uniswapPool, address _token);

  /*//////////////////////////////////////////////////////////////////////////
                            Custom Errors
  //////////////////////////////////////////////////////////////////////////*/

  /// @notice Emitted when guarded functions are called by users without the necessary permissions.
  error Unauthorized();

  /// @notice Emitted via {setSwapPool} if the pool doesn't match the token and pairs with WETH.
  error InvalidPool();

  /// @notice Emitted via {setStakingAddress} if the user already has a staking address.
  error StakingContractAlreadyExists();

  /// @notice Emitted when Zero address provided where it is not allowed.
  error ZeroAddressUnsupported();

  /// @notice Error emitted in {transferRareFrom} when a user performs an action that requires moving $RARE but has not made enough allowance for the registry.
  error InsufficientRareAllowance();

  /// @notice Emitted when a percentage is beyond the specified limit.
  error PercentageBeyondLimit();

  /// @notice Emitted when a Period Length is beyond the specified limit.
  error PeriodLengthBeyondLimit();

  /// @notice Emitted when renouncing the admin role and no other account has the role.
  error RenouncingAdmin();

  /*//////////////////////////////////////////////////////////////////////////
                          External Write Functions
  //////////////////////////////////////////////////////////////////////////*/

  /// @notice Increase amount staked when a user stakes.
  /// @param _staker The user who is staking.
  /// @param _stakedOn The user who is being staked on.
  /// @param _amount The amount of $RARE that has been staked.
  function increaseAmountStaked(
    address _staker,
    address _stakedOn,
    uint256 _amount
  ) external;

  /// @notice Decrease the amount staked when a user unstakes.
  /// @param _staker The user who is unstaking.
  /// @param _stakedOn The user who was being staked on.
  /// @param _amount The amount of $RARE that has been unstaked.
  function decreaseAmountStaked(
    address _staker,
    address _stakedOn,
    uint256 _amount
  ) external;

  /// @notice Set staking addresses for a target.
  /// @param _user Address of the target whose staking address is being set.
  /// @param _stakingAddress Address of the staking pool contract.
  /// @param _rewardSwapAddress Address of the reward swap contract.
  function setStakingAddresses(
    address _user,
    address _stakingAddress,
    address _rewardSwapAddress
  ) external;

  /// @notice Set the default payee.
  /// @param _payee Address of the account to be the new default payee.
  function setDefaultPayee(address _payee) external;

  /// @notice Set the reward swap discount percentage.
  /// @param _percentage The new discount percentage.
  function setDiscountPercentage(uint256 _percentage) external;

  /// @notice Set the unstake deflationary percentage.
  /// @param _percentage The new deflactionary percentage.
  function setDeflationaryPercentage(uint256 _percentage) external;

  /// @notice Set the round period length time.
  /// @param _periodLength The new period start.
  function setPeriodLength(uint256 _periodLength) external;

  /// @notice Set the ENS reverse registrar address.
  /// @param _reverseRegistrar The new period start.
  function setReverseRegistrar(address _reverseRegistrar) external;

  /// @notice Set the ENS resolver address.
  /// @param _resolver The new period start.
  function setResolver(address _resolver) external;

  /// @notice Set the uniswap pool address for the given ERC20 token.
  /// @param _uniswapPool Address of  uniswap pool.
  /// @param _token Address of  ERC20 contract.
  function setSwapPool(address _uniswapPool, address _token) external;

  /// @notice Pools to transfer $RARE tokens, usually into pools. This is so users only need to approve the registry when staking or performing reward swaps.
  /// @param _from Address to transfer the tokens from.
  /// @param _to Address to transfer the tokens to.
  /// @param _amount uint256 amount to transfer.
  function transferRareFrom(
    address _from,
    address _to,
    uint256 _amount
  ) external;

  /*//////////////////////////////////////////////////////////////////////////
                          External Read Functions
  //////////////////////////////////////////////////////////////////////////*/

  /// @notice Get the address for sending rewards if there are no stakers.
  /// @return address to send rewards to.
  function getDefaultPayee() external view returns (address);

  /// @notice Get the swap pool address for the ERC20 token.
  /// @return address of the swap pool associated with the token.
  function getSwapPool(address _token) external view returns (address);

  /// @notice Retrieve the address of $RARE.
  /// @return address Address of $RARE (the staking token to be used).
  function getRareAddress() external view returns (address);

  /// @notice Retrieve the address of Wrapped Ethereum.
  /// @return address Address of Wrapped Ethereum.
  function getWethAddress() external view returns (address);

  /// @notice Get reward swap discount percentage.
  /// @return uint256  discount percentage.
  function getDiscountPercentage() external view returns (uint256);

  /// @notice Get the unstake deflationary percentage.
  /// @return uint256 deflationary percentage.
  function getDeflationaryPercentage() external view returns (uint256);

  /// @notice Get the round period length.
  /// @return uint256 period length.
  function getPeriodLength() external view returns (uint256);

  /// @notice Retrieves the staking info for a given user.
  /// @param _user Address of user being queried.
  /// @return Info struct containing name, symbol, staking address, and reward accumulator address.
  function getStakingInfoForUser(address _user) external view returns (Info memory);

  /// @notice Retrieves the staking address for a given user.
  /// @param _user Address of user being queried.
  /// @return address staking address.
  function getStakingAddressForUser(address _user) external view returns (address);

  /// @notice Retrieves the reward accumulator address for a given user.
  /// @param _user Address of user being queried.
  /// @return address Reward accumulator address.
  function getRewardAccumulatorAddressForUser(address _user) external view returns (address);

  /// @notice Retrieves the total amount of rare staked by a given user.
  /// @param _user Address of the user staking.
  /// @return uint256 Amount of rare the user is staking.
  function getTotalAmountStakedByUser(address _user) external view returns (uint256);

  /// @notice Retrieves the total amount of rare being staked on a given user.
  /// @param _user Address of the user being staked on.
  /// @return uint256 Amount of rare being staked on the user.
  function getTotalAmountStakedOnUser(address _user) external view returns (uint256);

  /// @notice Query the users for the following staking addresseses.
  /// @param _stakingAddrs Addresses of staking contracts being queried.
  function getUsersForStakingAddresses(address[] calldata _stakingAddrs) external view returns (address[] memory);

  /// @notice Bytes32 representation of the role used for setting the staking address of a user.
  /// @return bytes32 value of the staking info setter role.
  function STAKING_INFO_SETTER_ROLE() external view returns (bytes32);

  /// @notice Bytes32 representation of the admin role for granting the ability to set amount staked for a single user/total amount staked on a user.
  /// @return bytes32 value of the staking stat setter admin role.
  function STAKING_STAT_SETTER_ADMIN_ROLE() external view returns (bytes32);

  /// @notice Bytes32 representation of the role used for updating the amount being staked on a user/amount a user is staking globally.
  /// @return bytes32 value of the stat setter role.
  function STAKING_STAT_SETTER_ROLE() external view returns (bytes32);

  /// @notice Bytes32 representation of the role used for period length, deflationary percentages, and the default payee.
  /// @return bytes32 value of the staking config setter role.
  function STAKING_CONFIG_SETTER_ROLE() external view returns (bytes32);

  /// @notice Bytes32 representation of the role used for updating the ENS resolvers.
  /// @return bytes32 value of the ens setter role.
  function ENS_SETTER_ROLE() external view returns (bytes32);

  /// @notice Bytes32 representation of the role used for updating uniswap pools.
  /// @return bytes32 value of the swap pool setter role.
  function SWAP_POOL_SETTER_ROLE() external view returns (bytes32);
}

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

File 24 of 29 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to
     * 0 before setting it to a non-zero value.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}

File 25 of 29 : IBeaconUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)

pragma solidity ^0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeaconUpgradeable {
    /**
     * @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);
}

File 26 of 29 : IERC1967Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
 *
 * _Available since v4.8.3._
 */
interface IERC1967Upgradeable {
    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

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

    /**
     * @dev Emitted when the beacon is changed.
     */
    event BeaconUpgraded(address indexed beacon);
}

File 27 of 29 : StorageSlotUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
 * _Available since v4.9 for `string`, `bytes`._
 */
library StorageSlotUpgradeable {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}

File 28 of 29 : IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 29 of 29 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/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.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

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

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

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // 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
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/=lib/openzeppelin-contracts/",
    "@ensdomains/ens-contracts/=lib/ens-contracts/contracts/",
    "ds-test/=lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
    "royalty-registry-solidity/=lib/royalty-registry-solidity/contracts/",
    "royalty-registry/=lib/royalty-registry-solidity/contracts/",
    "solmate/=lib/solmate/src/",
    "rareprotocol/assets/=lib/assets/src/",
    "rareprotocol/aux/=lib/aux/src/",
    "ensdomains/ens-contracts/=lib/ensdomains/ens-contracts/contracts/",
    "@ensdomains/buffer/=lib/buffer/",
    "arachnid/solidity-stringutils/=lib/solidity-stringutils/",
    "@uniswap/v3-core/=lib/v3-core/contracts/",
    "@uniswap/v3-core/contracts/=lib/v3-core/contracts/",
    "@uniswap/v3-periphery/=lib/v3-periphery/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {
    "src/utils/structs/MarketConfig.sol": {
      "MarketConfig": "0x44A0Dfc025913919618C69E1Ad393409D279a2e0"
    }
  }
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"limit","type":"uint256"}],"name":"ContractMintLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"limit","type":"uint256"}],"name":"ContractTxLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_contractAddress","type":"address"},{"indexed":true,"internalType":"address","name":"_seller","type":"address"},{"indexed":true,"internalType":"address","name":"_buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"_tokenIdStart","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_tokenIdEnd","type":"uint256"},{"indexed":false,"internalType":"address","name":"_currency","type":"address"},{"indexed":false,"internalType":"uint256","name":"_price","type":"uint256"}],"name":"MintDirectSale","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":"address","name":"_contractAddress","type":"address"},{"indexed":true,"internalType":"address","name":"_currency","type":"address"},{"indexed":true,"internalType":"address","name":"_seller","type":"address"},{"indexed":false,"internalType":"uint256","name":"_price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_maxMints","type":"uint256"},{"indexed":false,"internalType":"address payable[]","name":"splitRecipients","type":"address[]"},{"indexed":false,"internalType":"uint8[]","name":"splitRatios","type":"uint8[]"}],"name":"PrepareMintDirectSale","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_root","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_endTimestamp","type":"uint256"},{"indexed":true,"internalType":"address","name":"_contractAddress","type":"address"}],"name":"SetContractAllowListConfig","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"address","name":"_contractAddress","type":"address"}],"name":"getContractAllowListConfig","outputs":[{"components":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"}],"internalType":"struct IRareMinter.AllowListConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contractAddress","type":"address"}],"name":"getContractMintLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contractAddress","type":"address"},{"internalType":"address","name":"_address","type":"address"}],"name":"getContractMintsPerAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contractAddress","type":"address"}],"name":"getContractTxLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contractAddress","type":"address"},{"internalType":"address","name":"_address","type":"address"}],"name":"getContractTxsPerAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contractAddress","type":"address"}],"name":"getDirectSaleConfig","outputs":[{"components":[{"internalType":"address","name":"seller","type":"address"},{"internalType":"address","name":"currencyAddress","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"maxMints","type":"uint256"},{"internalType":"address payable[]","name":"splitRecipients","type":"address[]"},{"internalType":"uint8[]","name":"splitRatios","type":"uint8[]"}],"internalType":"struct IRareMinter.DirectSaleConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_networkBeneficiary","type":"address"},{"internalType":"address","name":"_marketplaceSettings","type":"address"},{"internalType":"address","name":"_spaceOperatorRegistry","type":"address"},{"internalType":"address","name":"_royaltyEngine","type":"address"},{"internalType":"address","name":"_payments","type":"address"},{"internalType":"address","name":"_approvedTokenRegistry","type":"address"},{"internalType":"address","name":"_stakingSettings","type":"address"},{"internalType":"address","name":"_stakingRegistry","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contractAddress","type":"address"},{"internalType":"address","name":"_currencyAddress","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint8","name":"_numMints","type":"uint8"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"mintDirectSale","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contractAddress","type":"address"},{"internalType":"address","name":"_currencyAddress","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_startTime","type":"uint256"},{"internalType":"uint256","name":"_maxMints","type":"uint256"},{"internalType":"address payable[]","name":"_splitRecipients","type":"address[]"},{"internalType":"uint8[]","name":"_splitRatios","type":"uint8[]"}],"name":"prepareMintDirectSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_approvedTokenRegistry","type":"address"}],"name":"setApprovedTokenRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_root","type":"bytes32"},{"internalType":"uint256","name":"_endTimestamp","type":"uint256"},{"internalType":"address","name":"_contractAddress","type":"address"}],"name":"setContractAllowListConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contractAddress","type":"address"},{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setContractMintLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contractAddress","type":"address"},{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setContractTxLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_marketplaceSettings","type":"address"}],"name":"setMarketplaceSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_networkBeneficiary","type":"address"}],"name":"setNetworkBeneficiary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_payments","type":"address"}],"name":"setPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_royaltyEngine","type":"address"}],"name":"setRoyaltyEngine","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_spaceOperatorRegistry","type":"address"}],"name":"setSpaceOperatorRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}]

60a06040523060805234801561001457600080fd5b506080516140f561004c600039600081816107b1015281816107f1015281816109c601528181610a060152610a9901526140f56000f3fe60806040526004361061014b5760003560e01c806378c19898116100b6578063af231a581161006f578063af231a581461040c578063ca774e681461042c578063d647ed3c14610473578063e4e87e3b14610486578063f2fde38b146104a6578063fa5312c8146104c657600080fd5b806378c19898146103375780637f358230146103575780638a29e2de146103775780638da5cb5b146103975780639dbef5d1146103bf578063a01fa6a9146103df57600080fd5b80633492e5a8116101085780633492e5a81461029a5780633659cfe6146102ba5780634cf5f910146102da5780634f1ef286146102fa57806352d1902d1461030d578063715018a61461032257600080fd5b806304c1ff07146101505780630fc635b3146101d3578063176ab440146101f557806321ede0321461021557806323946f1f146102355780632da45e8e1461027a575b600080fd5b34801561015c57600080fd5b506101b361016b3660046135d7565b6040805180820190915260008082526020820152506001600160a01b031660009081526101046020908152604091829020825180840190935280548352600101549082015290565b604080518251815260209283015192810192909252015b60405180910390f35b3480156101df57600080fd5b506101f36101ee3660046135f4565b6104fd565b005b34801561020157600080fd5b506101f36102103660046135d7565b61065d565b34801561022157600080fd5b506101f36102303660046135d7565b6106db565b34801561024157600080fd5b5061026c6102503660046135d7565b6001600160a01b03166000908152610105602052604090205490565b6040519081526020016101ca565b34801561028657600080fd5b5061026c61029536600461362d565b61072a565b3480156102a657600080fd5b506101f36102b53660046135d7565b610758565b3480156102c657600080fd5b506101f36102d53660046135d7565b6107a7565b3480156102e657600080fd5b506101f36102f5366004613666565b610886565b6101f36103083660046136d9565b6109bc565b34801561031957600080fd5b5061026c610a8c565b34801561032e57600080fd5b506101f3610b3f565b34801561034357600080fd5b506101f36103523660046137cd565b610b53565b34801561036357600080fd5b506101f36103723660046135d7565b610dfa565b34801561038357600080fd5b506101f3610392366004613881565b610e49565b3480156103a357600080fd5b506033546040516001600160a01b0390911681526020016101ca565b3480156103cb57600080fd5b506101f36103da366004613666565b6110c6565b3480156103eb57600080fd5b506103ff6103fa3660046135d7565b6111ee565b6040516101ca9190613968565b34801561041857600080fd5b506101f36104273660046135d7565b611373565b34801561043857600080fd5b5061026c61044736600461362d565b6001600160a01b0391821660009081526101066020908152604080832093909416825291909152205490565b6101f3610481366004613a2a565b6113c2565b34801561049257600080fd5b506101f36104a13660046135d7565b611d82565b3480156104b257600080fd5b506101f36104c13660046135d7565b611dd1565b3480156104d257600080fd5b5061026c6104e13660046135d7565b6001600160a01b03166000908152610107602052604090205490565b806001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561053b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055f9190613aaf565b6001600160a01b0316336001600160a01b0316146105ea5760405162461bcd60e51b815260206004820152603760248201527f736574436f6e7472616374416c6c6f774c697374436f6e6669673a3a4f6e6c7960448201527f20636f6e7472616374206f776e65722063616e2073657400000000000000000060648201526084015b60405180910390fd5b60408051808201825284815260208082018581526001600160a01b038516600081815261010484528590209351845590516001909301929092559151848152909185917fff2ce9a528a62cad638cc9f5bccd36a62ecfa9aa0b1ab82c98957cb3498b4b67910160405180910390a3505050565b610665611e47565b604051632c55921b60e01b815260fb60048201526001600160a01b03821660248201527344a0dfc025913919618c69e1ad393409d279a2e090632c55921b906044015b60006040518083038186803b1580156106c057600080fd5b505af41580156106d4573d6000803e3d6000fd5b5050505050565b6106e3611e47565b60405163ebda042b60e01b815260fb60048201526001600160a01b03821660248201527344a0dfc025913919618c69e1ad393409d279a2e09063ebda042b906044016106a8565b6001600160a01b03808316600090815261010860209081526040808320938516835292905220545b92915050565b610760611e47565b60405163dec30e3360e01b815260fb60048201526001600160a01b03821660248201527344a0dfc025913919618c69e1ad393409d279a2e09063dec30e33906044016106a8565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036107ef5760405162461bcd60e51b81526004016105e190613acc565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610838600080516020614079833981519152546001600160a01b031690565b6001600160a01b03161461085e5760405162461bcd60e51b81526004016105e190613b18565b61086781611ea1565b6040805160008082526020820190925261088391839190611ea9565b50565b816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e89190613aaf565b6001600160a01b0316336001600160a01b0316146109625760405162461bcd60e51b815260206004820152603160248201527f736574436f6e74726163744d696e744c696d69743a3a4f6e6c7920636f6e74726044820152701858dd081bdddb995c8818d85b881cd95d607a1b60648201526084016105e1565b6001600160a01b0382166000818152610105602052604090819020839055517fa9d9d6bd10e1caf4891001b6ccccdad5384a544c63cc903d40182c0a5a139cd9906109b09084815260200190565b60405180910390a25050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610a045760405162461bcd60e51b81526004016105e190613acc565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610a4d600080516020614079833981519152546001600160a01b031690565b6001600160a01b031614610a735760405162461bcd60e51b81526004016105e190613b18565b610a7c82611ea1565b610a8882826001611ea9565b5050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b2c5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016105e1565b5060008051602061407983398151915290565b610b47611e47565b610b516000612019565b565b336001600160a01b0316896001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bbf9190613aaf565b6001600160a01b031614610c495760405162461bcd60e51b8152602060048201526044602482018190527f707265706172654d696e7444697265637453616c653a3a4f6e6c79206d696e74908201527f20636f6e7472616374206f776e65722063616e207072657061726520746865206064820152631b5a5b9d60e21b608482015260a4016105e1565b6040518060e00160405280336001600160a01b03168152602001896001600160a01b03168152602001888152602001878152602001868152602001858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505090825250604080516020858102828101820190935285825292830192909186918691829185019084908082843760009201829052509390945250506001600160a01b03808d1682526101036020908152604092839020855181549084166001600160a01b03199182161782558683015160018301805491909516911617909255918401516002820155606084015160038201556080840151600482015560a08401518051919350610d6e9260058501929101906134ab565b5060c08201518051610d8a916006840191602090910190613510565b50905050336001600160a01b0316886001600160a01b03168a6001600160a01b03167f36de0d2c8eec9296de665d70b6b6e55d8c29bfa7a36e0178e805ef54725d9f5c8a8a8a8a8a8a8a604051610de79796959493929190613b64565b60405180910390a4505050505050505050565b610e02611e47565b604051630cf1420760e21b815260fb60048201526001600160a01b03821660248201527344a0dfc025913919618c69e1ad393409d279a2e0906333c5081c906044016106a8565b600054610100900460ff1615808015610e695750600054600160ff909116105b80610e835750303b158015610e83575060005460ff166001145b610ee65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016105e1565b6000805460ff191660011790558015610f09576000805461ff0019166101001790555b6040516323e95fa960e01b81526001600160a01b03808b166004830152808a16602483015280891660448301528088166064830152808716608483015280861660a483015280851660c4830152831660e48201527344a0dfc025913919618c69e1ad393409d279a2e0906323e95fa9906101040161010060405180830381865af4158015610f9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbf9190613c1c565b805160fb80546001600160a01b03199081166001600160a01b0393841617909155602083015160fc80548316918416919091179055604083015160fd80548316918416919091179055606083015160fe80548316918416919091179055608083015160ff8054831691841691909117905560a08301516101008054831691841691909117905560c08301516101018054831691841691909117905560e0909201516101028054909316911617905561107561206b565b80156110bb576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611104573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111289190613aaf565b6001600160a01b0316336001600160a01b0316146111a05760405162461bcd60e51b815260206004820152602f60248201527f736574436f6e747261637454784c696d69743a3a4f6e6c7920636f6e7472616360448201526e1d081bdddb995c8818d85b881cd95d608a1b60648201526084016105e1565b6001600160a01b0382166000818152610107602052604090819020839055517f5c8158ce792c8da34f9a8974acdb882c2c9cecc225c4ccf3c4a119aa2c726070906109b09084815260200190565b6112406040518060e0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160608152602001606081525090565b6001600160a01b0380831660009081526101036020908152604091829020825160e0810184528154851681526001820154909416848301526002810154848401526003810154606085015260048101546080850152600581018054845181850281018501909552808552919360a08601939092908301828280156112ed57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112cf575b505050505081526020016006820180548060200260200160405190810160405280929190818152602001828054801561136357602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116113345790505b5050505050815250509050919050565b61137b611e47565b60405163c70c56c760e01b815260fb60048201526001600160a01b03821660248201527344a0dfc025913919618c69e1ad393409d279a2e09063c70c56c7906044016106a8565b6113ca61209a565b6001600160a01b03808716600090815261010360209081526040808320815160e0810183528154861681526001820154909516858401526002810154858301526003810154606086015260048101546080860152600581018054835181860281018601909452808452949594919360a0860193929083018282801561147857602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161145a575b50505050508152602001600682018054806020026020016040519081016040528092919081815260200182805480156114ee57602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116114bf5790505b505050505081525050905061153787338585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506120f392505050565b60008460ff161161159f5760405162461bcd60e51b815260206004820152602c60248201527f6d696e7444697265637453616c653a3a4d696e7473206d75737420626520677260448201526b06561746572207468616e20360a41b60648201526084016105e1565b6001600160a01b03871660009081526101056020526040902054158061160057506001600160a01b038716600090815261010560209081526040808320546101068352818420338552909252909120546115fd9060ff871690613cfc565b11155b6116645760405162461bcd60e51b815260206004820152602f60248201527f6d696e7444697265637453616c653a3a4578636565646564206d696e74206c6960448201526e6d697420666f72206164647265737360881b60648201526084016105e1565b6001600160a01b0387166000908152610107602052604090205415806116c257506001600160a01b038716600090815261010760209081526040808320546101088352818420338552909252909120546116bf906001613cfc565b11155b61172d5760405162461bcd60e51b815260206004820152603660248201527f6d696e7444697265637453616c653a3a4578636565646564207472616e73616360448201527574696f6e206c696d697420666f72206164647265737360501b60648201526084016105e1565b60808101511580611745575080608001518460ff1611155b6117b75760405162461bcd60e51b815260206004820152603a60248201527f6d696e7444697265637453616c653a3a4d696e7473206d757374206265206c6560448201527f7373207468616e206d61784d696e7420696620656e61626c656400000000000060648201526084016105e1565b42816060015111156118175760405162461bcd60e51b8152602060048201526024808201527f6d696e7444697265637453616c653a3a53616c6520686173206e6f74207374616044820152631c9d195960e21b60648201526084016105e1565b80516001600160a01b031661188c5760405162461bcd60e51b815260206004820152603560248201527f6d696e7444697265637453616c653a3a436f6e7472616374206e6f7420707265604482015274706172656420666f72206469726563742073616c6560581b60648201526084016105e1565b806040015185146118fb5760405162461bcd60e51b815260206004820152603360248201527f6d696e7444697265637453616c653a3a507269636520646f6573206e6f74206d6044820152726174636820726571756972656420707269636560681b60648201526084016105e1565b61190660fb876121ea565b856001600160a01b031681602001516001600160a01b0316146119915760405162461bcd60e51b815260206004820152603960248201527f6d696e7444697265637453616c653a3a43757272656e637920646f6573206e6f60448201527f74206d617463682072657175697265642063757272656e63790000000000000060648201526084016105e1565b60006119a08660ff8716613d0f565b90508160400151600014611a345760fc546040516361fe24a960e11b8152600481018390526000916001600160a01b03169063c3fc495290602401602060405180830381865afa1580156119f8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1c9190613d26565b611a269083613cfc565b9050611a3288826122af565b505b6001600160a01b0388166000908152610105602052604090205415611a90576001600160a01b0388166000908152610106602090815260408083203384529091528120805460ff88169290611a8a908490613cfc565b90915550505b6001600160a01b0388166000908152610107602052604090205415611aea576001600160a01b0388166000908152610108602090815260408083203384529091528120805460019290611ae4908490613cfc565b90915550505b60405163755edd1760e01b81523360048201526000906001600160a01b038a169063755edd17906024016020604051808303816000875af1158015611b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b579190613d26565b60fc54604051635a3c652d60e01b81526001600160a01b038c811660048301526024820184905260016044830152929350911690635a3c652d90606401600060405180830381600087803b158015611bae57600080fd5b505af1925050508015611bbf575060015b5060015b8660ff16811015611cc65760405163755edd1760e01b81523360048201526001600160a01b038b169063755edd17906024016020604051808303816000875af1158015611c14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c389190613d26565b5060fc546001600160a01b0316635a3c652d8b611c558486613cfc565b6040516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482015260016044820152606401600060405180830381600087803b158015611ca257600080fd5b505af1925050508015611cb3575060015b5080611cbe81613d3f565b915050611bc3565b50604083015115611cf157825160a084015160c0850151611cf19260fb928d9286928e9289926124aa565b825133906001600160a01b03908116908b167f3bbd73fed0f94290f16db112f6b7113697c2502dd42aa0ddf8f971472523f100846001611d3460ff8d1683613cfc565b611d3e9190613d58565b6040805192835260208301919091526001600160a01b038e1690820152606081018c905260800160405180910390a4505050611d7a6001606555565b505050505050565b611d8a611e47565b6040516386e5800760e01b815260fb60048201526001600160a01b03821660248201527344a0dfc025913919618c69e1ad393409d279a2e0906386e58007906044016106a8565b611dd9611e47565b6001600160a01b038116611e3e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105e1565b61088381612019565b6033546001600160a01b03163314610b515760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105e1565b610883611e47565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611ee157611edc83612db4565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611f3b575060408051601f3d908101601f19168201909252611f3891810190613d26565b60015b611f9e5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016105e1565b600080516020614079833981519152811461200d5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016105e1565b50611edc838383612e50565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166120925760405162461bcd60e51b81526004016105e190613d6b565b610b51612e75565b6002606554036120ec5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105e1565b6002606555565b6001600160a01b03831660009081526101046020526040902054806121185750505050565b6001600160a01b0384166000908152610104602052604090206001015442106121415750505050565b6040516bffffffffffffffffffffffff19606085901b16602082015261218190603401604051602081830303815290604052805190602001208284612ea5565b6121e45760405162461bcd60e51b815260206004820152602e60248201527f5f656e666f726365416c6c6f774c69737465643a3a41646472657373206e6f7460448201526d081bdb88185b1b1bddc81b1a5cdd60921b60648201526084016105e1565b50505050565b6001600160a01b038116158061226b57506005820154604051632d5ad3d560e01b81526001600160a01b03838116600483015290911690632d5ad3d590602401602060405180830381865afa158015612247573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226b9190613db6565b610a885760405162461bcd60e51b81526020600482015260156024820152744e6f7420617070726f7665642063757272656e637960581b60448201526064016105e1565b6001600160a01b03821661230257803414610a885760405162461bcd60e51b81526020600482015260136024820152721b9bdd08195b9bdd59da08195d1a081cd95b9d606a1b60448201526064016105e1565b34156123615760405162461bcd60e51b815260206004820152602860248201527f6d73672e76616c75652073686f756c642062652030207768656e206e6f7420756044820152670e6d2dcce40cae8d60c31b60648201526084016105e1565b6040516370a0823160e01b815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156123aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ce9190613d26565b90506123e56001600160a01b038316333086612ef5565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561242c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124509190613d26565b90508361245d8383613d58565b146106d45760405162461bcd60e51b815260206004820152601c60248201527f6e6f7420656e6f75676820746f6b656e73207472616e7366657265640000000060448201526064016105e1565b80518251146125175760405162461bcd60e51b815260206004820152603360248201527f4e756d626572206f662073706c69742061646472657373657320616e642072616044820152723a34b7b99036bab9ba1031329032b8bab0b61760691b60648201526084016105e1565b60018801546040516361fe24a960e11b81526004810186905285916000916001600160a01b039091169063c3fc495290602401602060405180830381865afa158015612567573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258b9190613d26565b604080516002808252606082018352929350600092909160208301908036833750508c5482519293506001600160a01b0316918391506000906125d0576125d0613dd8565b6001600160a01b03928316602091820292909201015260078c015460405163e286ef3360e01b8152888316600482015291169063e286ef3390602401602060405180830381865afa158015612629573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264d9190613aaf565b8160018151811061266057612660613dd8565b60200260200101906001600160a01b031690816001600160a01b03168152505060006001600160a01b03168160018151811061269e5761269e613dd8565b60200260200101516001600160a01b0316146126d457806001815181106126c7576126c7613dd8565b60200260200101516126e0565b8a546001600160a01b03165b816001815181106126f3576126f3613dd8565b6001600160a01b039290921660209283029190910182015260408051600280825260608201835260009391929091830190803683370190505060068d01546040516303fdde1160e21b8152600481018b90529192506001600160a01b031690630ff7784490602401602060405180830381865afa158015612778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061279c9190613d26565b816000815181106127af576127af613dd8565b602090810291909101015260068c015460405163470d6ed960e11b8152600481018a90526001600160a01b0390911690638e1addb290602401602060405180830381865afa158015612805573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128299190613d26565b8160018151811061283c5761283c613dd8565b6020026020010181815250506128558c8a858585612f60565b60018c0154604051631446f21360e21b81526001600160a01b038d81166004830152602482018d90529091169063511bc84c90604401602060405180830381865afa1580156128a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128cc9190613db6565b612bad576040805160018082528183019092526000916020808301908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090508360008151811061292857612928613dd8565b60200260200101518160008151811061294357612943613dd8565b6001600160a01b03928316602091820292909201015260028f0154604051635dc22eff60e01b81528b83166004820152911690635dc22eff90602401602060405180830381865afa15801561299c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c09190613db6565b15612abf5760028e0154604051632260494f60e01b81526001600160a01b038b811660048301526000921690632260494f90602401602060405180830381865afa158015612a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a369190613dee565b60ff1690506064612a47828d613d0f565b612a519190613e0b565b612a5b9088613d58565b96506064612a69828d613d0f565b612a739190613e0b565b83600081518110612a8657612a86613dd8565b602002602001018181525050612ab98f8d85600081518110612aaa57612aaa613dd8565b60200260200101518587612f60565b50612ba6565b60018e015460405163b28a7bad60e01b81526001600160a01b038f81166004830152600092169063b28a7bad90602401602060405180830381865afa158015612b0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b309190613dee565b60ff1690506064612b41828d613d0f565b612b4b9190613e0b565b612b559088613d58565b96506064612b63828d613d0f565b612b6d9190613e0b565b83600081518110612b8057612b80613dd8565b602002602001018181525050612ba48f8d85600081518110612aaa57612aaa613dd8565b505b5050612c9d565b60038c0154604051637a99dc0160e11b81526001600160a01b038d81166004830152602482018d9052604482018b9052600092839291169063f533b802906064016000604051808303816000875af1158015612c0d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c359190810190613ebc565b915091506000805b8251811015612c7f57828181518110612c5857612c58613dd8565b602002602001015182612c6b9190613cfc565b915080612c7781613d3f565b915050612c3d565b50612c8a8188613d58565b9650612c998f8d838686612f60565b5050505b6000865167ffffffffffffffff811115612cb957612cb9613692565b604051908082528060200260200182016040528015612ce2578160200160208202803683370190505b5090506000805b8851811015612d96576064888281518110612d0657612d06613dd8565b602002602001015160ff1688612d1c9190613d0f565b612d269190613e0b565b838281518110612d3857612d38613dd8565b6020026020010181815250506064888281518110612d5857612d58613dd8565b602002602001015160ff1688612d6e9190613d0f565b612d789190613e0b565b612d829083613cfc565b915080612d8e81613d3f565b915050612ce9565b50612da48e8c838b86612f60565b5050505050505050505050505050565b6001600160a01b0381163b612e215760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016105e1565b60008051602061407983398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b612e59836130c7565b600082511180612e665750805b15611edc576121e48383613107565b600054610100900460ff16612e9c5760405162461bcd60e51b81526004016105e190613d6b565b610b5133612019565b600083815b8351811015612eea57612ed682858381518110612ec957612ec9613dd8565b6020026020010151613133565b915080612ee281613d3f565b915050612eaa565b509092149392505050565b6040516001600160a01b03808516602483015283166044820152606481018290526121e49085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613199565b6001600160a01b03841661304f57600485015460405160009182916001600160a01b0390911690869063c176e63960e01b90612fa29088908890602401613f81565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612fe09190614029565b60006040518083038185875af1925050503d806000811461301d576040519150601f19603f3d011682016040523d82523d6000602084013e613022565b606091505b50915091508181906130475760405162461bcd60e51b81526004016105e19190614045565b5050506106d4565b8360005b83518110156130be576130ac84828151811061307157613071613dd8565b602002602001015184838151811061308b5761308b613dd8565b6020026020010151846001600160a01b031661326e9092919063ffffffff16565b806130b681613d3f565b915050613053565b50505050505050565b6130d081612db4565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061312c83836040518060600160405280602781526020016140996027913961329e565b9392505050565b60008183111561316c5760408051602081018490529081018490526060016040516020818303038152906040528051906020012061312c565b50604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60006131ee826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166133169092919063ffffffff16565b905080516000148061320f57508080602001905181019061320f9190613db6565b611edc5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016105e1565b6040516001600160a01b038316602482015260448101829052611edc90849063a9059cbb60e01b90606401612f29565b6060600080856001600160a01b0316856040516132bb9190614029565b600060405180830381855af49150503d80600081146132f6576040519150601f19603f3d011682016040523d82523d6000602084013e6132fb565b606091505b509150915061330c8683838761332d565b9695505050505050565b606061332584846000856133a6565b949350505050565b6060831561339c578251600003613395576001600160a01b0385163b6133955760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105e1565b5081613325565b6133258383613481565b6060824710156134075760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016105e1565b600080866001600160a01b031685876040516134239190614029565b60006040518083038185875af1925050503d8060008114613460576040519150601f19603f3d011682016040523d82523d6000602084013e613465565b606091505b50915091506134768783838761332d565b979650505050505050565b8151156134915781518083602001fd5b8060405162461bcd60e51b81526004016105e19190614045565b828054828255906000526020600020908101928215613500579160200282015b8281111561350057825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906134cb565b5061350c9291506135ad565b5090565b82805482825590600052602060002090601f016020900481019282156135005791602002820160005b8382111561357757835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302613539565b80156135a45782816101000a81549060ff0219169055600101602081600001049283019260010302613577565b505061350c9291505b5b8082111561350c57600081556001016135ae565b6001600160a01b038116811461088357600080fd5b6000602082840312156135e957600080fd5b813561312c816135c2565b60008060006060848603121561360957600080fd5b83359250602084013591506040840135613622816135c2565b809150509250925092565b6000806040838503121561364057600080fd5b823561364b816135c2565b9150602083013561365b816135c2565b809150509250929050565b6000806040838503121561367957600080fd5b8235613684816135c2565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156136d1576136d1613692565b604052919050565b600080604083850312156136ec57600080fd5b82356136f7816135c2565b915060208381013567ffffffffffffffff8082111561371557600080fd5b818601915086601f83011261372957600080fd5b81358181111561373b5761373b613692565b61374d601f8201601f191685016136a8565b9150808252878482850101111561376357600080fd5b80848401858401376000848284010152508093505050509250929050565b60008083601f84011261379357600080fd5b50813567ffffffffffffffff8111156137ab57600080fd5b6020830191508360208260051b85010111156137c657600080fd5b9250929050565b600080600080600080600080600060e08a8c0312156137eb57600080fd5b89356137f6816135c2565b985060208a0135613806816135c2565b975060408a0135965060608a0135955060808a0135945060a08a013567ffffffffffffffff8082111561383857600080fd5b6138448d838e01613781565b909650945060c08c013591508082111561385d57600080fd5b5061386a8c828d01613781565b915080935050809150509295985092959850929598565b600080600080600080600080610100898b03121561389e57600080fd5b88356138a9816135c2565b975060208901356138b9816135c2565b965060408901356138c9816135c2565b955060608901356138d9816135c2565b945060808901356138e9816135c2565b935060a08901356138f9816135c2565b925060c0890135613909816135c2565b915060e0890135613919816135c2565b809150509295985092959890939650565b600081518084526020808501945080840160005b8381101561395d57815160ff168752958201959082019060010161393e565b509495945050505050565b60006020808352610100830160018060a01b03808651168386015280838701511660408601526040860151606086015260608601516080860152608086015160a086015260a086015160e060c0870152828151808552610120880191508583019450600092505b808310156139f1578451841682529385019360019290920191908501906139cf565b5060c0880151878203601f190160e08901529450613a0f818661392a565b98975050505050505050565b60ff8116811461088357600080fd5b60008060008060008060a08789031215613a4357600080fd5b8635613a4e816135c2565b95506020870135613a5e816135c2565b9450604087013593506060870135613a7581613a1b565b9250608087013567ffffffffffffffff811115613a9157600080fd5b613a9d89828a01613781565b979a9699509497509295939492505050565b600060208284031215613ac157600080fd5b815161312c816135c2565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b600060a082018983526020898185015288604085015260a060608501528187835260c08501905088925060005b88811015613bbf578335613ba4816135c2565b6001600160a01b031682529282019290820190600101613b91565b508481036080860152858152810191508560005b86811015613bfb578135613be681613a1b565b60ff1684529282019290820190600101613bd3565b50919b9a5050505050505050505050565b8051613c17816135c2565b919050565b6000610100808385031215613c3057600080fd5b6040519081019067ffffffffffffffff82118183101715613c5357613c53613692565b8160405283519150613c64826135c2565b818152613c7360208501613c0c565b6020820152613c8460408501613c0c565b6040820152613c9560608501613c0c565b6060820152613ca660808501613c0c565b6080820152613cb760a08501613c0c565b60a0820152613cc860c08501613c0c565b60c0820152613cd960e08501613c0c565b60e0820152949350505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561075257610752613ce6565b808202811582820484141761075257610752613ce6565b600060208284031215613d3857600080fd5b5051919050565b600060018201613d5157613d51613ce6565b5060010190565b8181038181111561075257610752613ce6565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215613dc857600080fd5b8151801515811461312c57600080fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e0057600080fd5b815161312c81613a1b565b600082613e2857634e487b7160e01b600052601260045260246000fd5b500490565b600067ffffffffffffffff821115613e4757613e47613692565b5060051b60200190565b600082601f830112613e6257600080fd5b81516020613e77613e7283613e2d565b6136a8565b82815260059290921b84018101918181019086841115613e9657600080fd5b8286015b84811015613eb15780518352918301918301613e9a565b509695505050505050565b60008060408385031215613ecf57600080fd5b825167ffffffffffffffff80821115613ee757600080fd5b818501915085601f830112613efb57600080fd5b81516020613f0b613e7283613e2d565b82815260059290921b84018101918181019089841115613f2a57600080fd5b948201945b83861015613f51578551613f42816135c2565b82529482019490820190613f2f565b91880151919650909350505080821115613f6a57600080fd5b50613f7785828601613e51565b9150509250929050565b604080825283519082018190526000906020906060840190828701845b82811015613fc35781516001600160a01b031684529284019290840190600101613f9e565b5050508381038285015284518082528583019183019060005b81811015613ff857835183529284019291840191600101613fdc565b5090979650505050505050565b60005b83811015614020578181015183820152602001614008565b50506000910152565b6000825161403b818460208701614005565b9190910192915050565b6020815260008251806020840152614064816040850160208701614005565b601f01601f1916919091016040019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220ef0b71db6534f219accc034663d81d3861071560ac70b8fddf90a8f5f676a2a064736f6c63430008120033

Deployed Bytecode

0x60806040526004361061014b5760003560e01c806378c19898116100b6578063af231a581161006f578063af231a581461040c578063ca774e681461042c578063d647ed3c14610473578063e4e87e3b14610486578063f2fde38b146104a6578063fa5312c8146104c657600080fd5b806378c19898146103375780637f358230146103575780638a29e2de146103775780638da5cb5b146103975780639dbef5d1146103bf578063a01fa6a9146103df57600080fd5b80633492e5a8116101085780633492e5a81461029a5780633659cfe6146102ba5780634cf5f910146102da5780634f1ef286146102fa57806352d1902d1461030d578063715018a61461032257600080fd5b806304c1ff07146101505780630fc635b3146101d3578063176ab440146101f557806321ede0321461021557806323946f1f146102355780632da45e8e1461027a575b600080fd5b34801561015c57600080fd5b506101b361016b3660046135d7565b6040805180820190915260008082526020820152506001600160a01b031660009081526101046020908152604091829020825180840190935280548352600101549082015290565b604080518251815260209283015192810192909252015b60405180910390f35b3480156101df57600080fd5b506101f36101ee3660046135f4565b6104fd565b005b34801561020157600080fd5b506101f36102103660046135d7565b61065d565b34801561022157600080fd5b506101f36102303660046135d7565b6106db565b34801561024157600080fd5b5061026c6102503660046135d7565b6001600160a01b03166000908152610105602052604090205490565b6040519081526020016101ca565b34801561028657600080fd5b5061026c61029536600461362d565b61072a565b3480156102a657600080fd5b506101f36102b53660046135d7565b610758565b3480156102c657600080fd5b506101f36102d53660046135d7565b6107a7565b3480156102e657600080fd5b506101f36102f5366004613666565b610886565b6101f36103083660046136d9565b6109bc565b34801561031957600080fd5b5061026c610a8c565b34801561032e57600080fd5b506101f3610b3f565b34801561034357600080fd5b506101f36103523660046137cd565b610b53565b34801561036357600080fd5b506101f36103723660046135d7565b610dfa565b34801561038357600080fd5b506101f3610392366004613881565b610e49565b3480156103a357600080fd5b506033546040516001600160a01b0390911681526020016101ca565b3480156103cb57600080fd5b506101f36103da366004613666565b6110c6565b3480156103eb57600080fd5b506103ff6103fa3660046135d7565b6111ee565b6040516101ca9190613968565b34801561041857600080fd5b506101f36104273660046135d7565b611373565b34801561043857600080fd5b5061026c61044736600461362d565b6001600160a01b0391821660009081526101066020908152604080832093909416825291909152205490565b6101f3610481366004613a2a565b6113c2565b34801561049257600080fd5b506101f36104a13660046135d7565b611d82565b3480156104b257600080fd5b506101f36104c13660046135d7565b611dd1565b3480156104d257600080fd5b5061026c6104e13660046135d7565b6001600160a01b03166000908152610107602052604090205490565b806001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561053b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055f9190613aaf565b6001600160a01b0316336001600160a01b0316146105ea5760405162461bcd60e51b815260206004820152603760248201527f736574436f6e7472616374416c6c6f774c697374436f6e6669673a3a4f6e6c7960448201527f20636f6e7472616374206f776e65722063616e2073657400000000000000000060648201526084015b60405180910390fd5b60408051808201825284815260208082018581526001600160a01b038516600081815261010484528590209351845590516001909301929092559151848152909185917fff2ce9a528a62cad638cc9f5bccd36a62ecfa9aa0b1ab82c98957cb3498b4b67910160405180910390a3505050565b610665611e47565b604051632c55921b60e01b815260fb60048201526001600160a01b03821660248201527344a0dfc025913919618c69e1ad393409d279a2e090632c55921b906044015b60006040518083038186803b1580156106c057600080fd5b505af41580156106d4573d6000803e3d6000fd5b5050505050565b6106e3611e47565b60405163ebda042b60e01b815260fb60048201526001600160a01b03821660248201527344a0dfc025913919618c69e1ad393409d279a2e09063ebda042b906044016106a8565b6001600160a01b03808316600090815261010860209081526040808320938516835292905220545b92915050565b610760611e47565b60405163dec30e3360e01b815260fb60048201526001600160a01b03821660248201527344a0dfc025913919618c69e1ad393409d279a2e09063dec30e33906044016106a8565b6001600160a01b037f00000000000000000000000097c92e24ad06f227bde161bc3268040498ebc96d1630036107ef5760405162461bcd60e51b81526004016105e190613acc565b7f00000000000000000000000097c92e24ad06f227bde161bc3268040498ebc96d6001600160a01b0316610838600080516020614079833981519152546001600160a01b031690565b6001600160a01b03161461085e5760405162461bcd60e51b81526004016105e190613b18565b61086781611ea1565b6040805160008082526020820190925261088391839190611ea9565b50565b816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e89190613aaf565b6001600160a01b0316336001600160a01b0316146109625760405162461bcd60e51b815260206004820152603160248201527f736574436f6e74726163744d696e744c696d69743a3a4f6e6c7920636f6e74726044820152701858dd081bdddb995c8818d85b881cd95d607a1b60648201526084016105e1565b6001600160a01b0382166000818152610105602052604090819020839055517fa9d9d6bd10e1caf4891001b6ccccdad5384a544c63cc903d40182c0a5a139cd9906109b09084815260200190565b60405180910390a25050565b6001600160a01b037f00000000000000000000000097c92e24ad06f227bde161bc3268040498ebc96d163003610a045760405162461bcd60e51b81526004016105e190613acc565b7f00000000000000000000000097c92e24ad06f227bde161bc3268040498ebc96d6001600160a01b0316610a4d600080516020614079833981519152546001600160a01b031690565b6001600160a01b031614610a735760405162461bcd60e51b81526004016105e190613b18565b610a7c82611ea1565b610a8882826001611ea9565b5050565b6000306001600160a01b037f00000000000000000000000097c92e24ad06f227bde161bc3268040498ebc96d1614610b2c5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016105e1565b5060008051602061407983398151915290565b610b47611e47565b610b516000612019565b565b336001600160a01b0316896001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bbf9190613aaf565b6001600160a01b031614610c495760405162461bcd60e51b8152602060048201526044602482018190527f707265706172654d696e7444697265637453616c653a3a4f6e6c79206d696e74908201527f20636f6e7472616374206f776e65722063616e207072657061726520746865206064820152631b5a5b9d60e21b608482015260a4016105e1565b6040518060e00160405280336001600160a01b03168152602001896001600160a01b03168152602001888152602001878152602001868152602001858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505090825250604080516020858102828101820190935285825292830192909186918691829185019084908082843760009201829052509390945250506001600160a01b03808d1682526101036020908152604092839020855181549084166001600160a01b03199182161782558683015160018301805491909516911617909255918401516002820155606084015160038201556080840151600482015560a08401518051919350610d6e9260058501929101906134ab565b5060c08201518051610d8a916006840191602090910190613510565b50905050336001600160a01b0316886001600160a01b03168a6001600160a01b03167f36de0d2c8eec9296de665d70b6b6e55d8c29bfa7a36e0178e805ef54725d9f5c8a8a8a8a8a8a8a604051610de79796959493929190613b64565b60405180910390a4505050505050505050565b610e02611e47565b604051630cf1420760e21b815260fb60048201526001600160a01b03821660248201527344a0dfc025913919618c69e1ad393409d279a2e0906333c5081c906044016106a8565b600054610100900460ff1615808015610e695750600054600160ff909116105b80610e835750303b158015610e83575060005460ff166001145b610ee65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016105e1565b6000805460ff191660011790558015610f09576000805461ff0019166101001790555b6040516323e95fa960e01b81526001600160a01b03808b166004830152808a16602483015280891660448301528088166064830152808716608483015280861660a483015280851660c4830152831660e48201527344a0dfc025913919618c69e1ad393409d279a2e0906323e95fa9906101040161010060405180830381865af4158015610f9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbf9190613c1c565b805160fb80546001600160a01b03199081166001600160a01b0393841617909155602083015160fc80548316918416919091179055604083015160fd80548316918416919091179055606083015160fe80548316918416919091179055608083015160ff8054831691841691909117905560a08301516101008054831691841691909117905560c08301516101018054831691841691909117905560e0909201516101028054909316911617905561107561206b565b80156110bb576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611104573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111289190613aaf565b6001600160a01b0316336001600160a01b0316146111a05760405162461bcd60e51b815260206004820152602f60248201527f736574436f6e747261637454784c696d69743a3a4f6e6c7920636f6e7472616360448201526e1d081bdddb995c8818d85b881cd95d608a1b60648201526084016105e1565b6001600160a01b0382166000818152610107602052604090819020839055517f5c8158ce792c8da34f9a8974acdb882c2c9cecc225c4ccf3c4a119aa2c726070906109b09084815260200190565b6112406040518060e0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160608152602001606081525090565b6001600160a01b0380831660009081526101036020908152604091829020825160e0810184528154851681526001820154909416848301526002810154848401526003810154606085015260048101546080850152600581018054845181850281018501909552808552919360a08601939092908301828280156112ed57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112cf575b505050505081526020016006820180548060200260200160405190810160405280929190818152602001828054801561136357602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116113345790505b5050505050815250509050919050565b61137b611e47565b60405163c70c56c760e01b815260fb60048201526001600160a01b03821660248201527344a0dfc025913919618c69e1ad393409d279a2e09063c70c56c7906044016106a8565b6113ca61209a565b6001600160a01b03808716600090815261010360209081526040808320815160e0810183528154861681526001820154909516858401526002810154858301526003810154606086015260048101546080860152600581018054835181860281018601909452808452949594919360a0860193929083018282801561147857602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161145a575b50505050508152602001600682018054806020026020016040519081016040528092919081815260200182805480156114ee57602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116114bf5790505b505050505081525050905061153787338585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506120f392505050565b60008460ff161161159f5760405162461bcd60e51b815260206004820152602c60248201527f6d696e7444697265637453616c653a3a4d696e7473206d75737420626520677260448201526b06561746572207468616e20360a41b60648201526084016105e1565b6001600160a01b03871660009081526101056020526040902054158061160057506001600160a01b038716600090815261010560209081526040808320546101068352818420338552909252909120546115fd9060ff871690613cfc565b11155b6116645760405162461bcd60e51b815260206004820152602f60248201527f6d696e7444697265637453616c653a3a4578636565646564206d696e74206c6960448201526e6d697420666f72206164647265737360881b60648201526084016105e1565b6001600160a01b0387166000908152610107602052604090205415806116c257506001600160a01b038716600090815261010760209081526040808320546101088352818420338552909252909120546116bf906001613cfc565b11155b61172d5760405162461bcd60e51b815260206004820152603660248201527f6d696e7444697265637453616c653a3a4578636565646564207472616e73616360448201527574696f6e206c696d697420666f72206164647265737360501b60648201526084016105e1565b60808101511580611745575080608001518460ff1611155b6117b75760405162461bcd60e51b815260206004820152603a60248201527f6d696e7444697265637453616c653a3a4d696e7473206d757374206265206c6560448201527f7373207468616e206d61784d696e7420696620656e61626c656400000000000060648201526084016105e1565b42816060015111156118175760405162461bcd60e51b8152602060048201526024808201527f6d696e7444697265637453616c653a3a53616c6520686173206e6f74207374616044820152631c9d195960e21b60648201526084016105e1565b80516001600160a01b031661188c5760405162461bcd60e51b815260206004820152603560248201527f6d696e7444697265637453616c653a3a436f6e7472616374206e6f7420707265604482015274706172656420666f72206469726563742073616c6560581b60648201526084016105e1565b806040015185146118fb5760405162461bcd60e51b815260206004820152603360248201527f6d696e7444697265637453616c653a3a507269636520646f6573206e6f74206d6044820152726174636820726571756972656420707269636560681b60648201526084016105e1565b61190660fb876121ea565b856001600160a01b031681602001516001600160a01b0316146119915760405162461bcd60e51b815260206004820152603960248201527f6d696e7444697265637453616c653a3a43757272656e637920646f6573206e6f60448201527f74206d617463682072657175697265642063757272656e63790000000000000060648201526084016105e1565b60006119a08660ff8716613d0f565b90508160400151600014611a345760fc546040516361fe24a960e11b8152600481018390526000916001600160a01b03169063c3fc495290602401602060405180830381865afa1580156119f8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1c9190613d26565b611a269083613cfc565b9050611a3288826122af565b505b6001600160a01b0388166000908152610105602052604090205415611a90576001600160a01b0388166000908152610106602090815260408083203384529091528120805460ff88169290611a8a908490613cfc565b90915550505b6001600160a01b0388166000908152610107602052604090205415611aea576001600160a01b0388166000908152610108602090815260408083203384529091528120805460019290611ae4908490613cfc565b90915550505b60405163755edd1760e01b81523360048201526000906001600160a01b038a169063755edd17906024016020604051808303816000875af1158015611b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b579190613d26565b60fc54604051635a3c652d60e01b81526001600160a01b038c811660048301526024820184905260016044830152929350911690635a3c652d90606401600060405180830381600087803b158015611bae57600080fd5b505af1925050508015611bbf575060015b5060015b8660ff16811015611cc65760405163755edd1760e01b81523360048201526001600160a01b038b169063755edd17906024016020604051808303816000875af1158015611c14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c389190613d26565b5060fc546001600160a01b0316635a3c652d8b611c558486613cfc565b6040516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482015260016044820152606401600060405180830381600087803b158015611ca257600080fd5b505af1925050508015611cb3575060015b5080611cbe81613d3f565b915050611bc3565b50604083015115611cf157825160a084015160c0850151611cf19260fb928d9286928e9289926124aa565b825133906001600160a01b03908116908b167f3bbd73fed0f94290f16db112f6b7113697c2502dd42aa0ddf8f971472523f100846001611d3460ff8d1683613cfc565b611d3e9190613d58565b6040805192835260208301919091526001600160a01b038e1690820152606081018c905260800160405180910390a4505050611d7a6001606555565b505050505050565b611d8a611e47565b6040516386e5800760e01b815260fb60048201526001600160a01b03821660248201527344a0dfc025913919618c69e1ad393409d279a2e0906386e58007906044016106a8565b611dd9611e47565b6001600160a01b038116611e3e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105e1565b61088381612019565b6033546001600160a01b03163314610b515760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105e1565b610883611e47565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611ee157611edc83612db4565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611f3b575060408051601f3d908101601f19168201909252611f3891810190613d26565b60015b611f9e5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016105e1565b600080516020614079833981519152811461200d5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016105e1565b50611edc838383612e50565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166120925760405162461bcd60e51b81526004016105e190613d6b565b610b51612e75565b6002606554036120ec5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105e1565b6002606555565b6001600160a01b03831660009081526101046020526040902054806121185750505050565b6001600160a01b0384166000908152610104602052604090206001015442106121415750505050565b6040516bffffffffffffffffffffffff19606085901b16602082015261218190603401604051602081830303815290604052805190602001208284612ea5565b6121e45760405162461bcd60e51b815260206004820152602e60248201527f5f656e666f726365416c6c6f774c69737465643a3a41646472657373206e6f7460448201526d081bdb88185b1b1bddc81b1a5cdd60921b60648201526084016105e1565b50505050565b6001600160a01b038116158061226b57506005820154604051632d5ad3d560e01b81526001600160a01b03838116600483015290911690632d5ad3d590602401602060405180830381865afa158015612247573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226b9190613db6565b610a885760405162461bcd60e51b81526020600482015260156024820152744e6f7420617070726f7665642063757272656e637960581b60448201526064016105e1565b6001600160a01b03821661230257803414610a885760405162461bcd60e51b81526020600482015260136024820152721b9bdd08195b9bdd59da08195d1a081cd95b9d606a1b60448201526064016105e1565b34156123615760405162461bcd60e51b815260206004820152602860248201527f6d73672e76616c75652073686f756c642062652030207768656e206e6f7420756044820152670e6d2dcce40cae8d60c31b60648201526084016105e1565b6040516370a0823160e01b815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156123aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ce9190613d26565b90506123e56001600160a01b038316333086612ef5565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561242c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124509190613d26565b90508361245d8383613d58565b146106d45760405162461bcd60e51b815260206004820152601c60248201527f6e6f7420656e6f75676820746f6b656e73207472616e7366657265640000000060448201526064016105e1565b80518251146125175760405162461bcd60e51b815260206004820152603360248201527f4e756d626572206f662073706c69742061646472657373657320616e642072616044820152723a34b7b99036bab9ba1031329032b8bab0b61760691b60648201526084016105e1565b60018801546040516361fe24a960e11b81526004810186905285916000916001600160a01b039091169063c3fc495290602401602060405180830381865afa158015612567573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258b9190613d26565b604080516002808252606082018352929350600092909160208301908036833750508c5482519293506001600160a01b0316918391506000906125d0576125d0613dd8565b6001600160a01b03928316602091820292909201015260078c015460405163e286ef3360e01b8152888316600482015291169063e286ef3390602401602060405180830381865afa158015612629573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264d9190613aaf565b8160018151811061266057612660613dd8565b60200260200101906001600160a01b031690816001600160a01b03168152505060006001600160a01b03168160018151811061269e5761269e613dd8565b60200260200101516001600160a01b0316146126d457806001815181106126c7576126c7613dd8565b60200260200101516126e0565b8a546001600160a01b03165b816001815181106126f3576126f3613dd8565b6001600160a01b039290921660209283029190910182015260408051600280825260608201835260009391929091830190803683370190505060068d01546040516303fdde1160e21b8152600481018b90529192506001600160a01b031690630ff7784490602401602060405180830381865afa158015612778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061279c9190613d26565b816000815181106127af576127af613dd8565b602090810291909101015260068c015460405163470d6ed960e11b8152600481018a90526001600160a01b0390911690638e1addb290602401602060405180830381865afa158015612805573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128299190613d26565b8160018151811061283c5761283c613dd8565b6020026020010181815250506128558c8a858585612f60565b60018c0154604051631446f21360e21b81526001600160a01b038d81166004830152602482018d90529091169063511bc84c90604401602060405180830381865afa1580156128a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128cc9190613db6565b612bad576040805160018082528183019092526000916020808301908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090508360008151811061292857612928613dd8565b60200260200101518160008151811061294357612943613dd8565b6001600160a01b03928316602091820292909201015260028f0154604051635dc22eff60e01b81528b83166004820152911690635dc22eff90602401602060405180830381865afa15801561299c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c09190613db6565b15612abf5760028e0154604051632260494f60e01b81526001600160a01b038b811660048301526000921690632260494f90602401602060405180830381865afa158015612a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a369190613dee565b60ff1690506064612a47828d613d0f565b612a519190613e0b565b612a5b9088613d58565b96506064612a69828d613d0f565b612a739190613e0b565b83600081518110612a8657612a86613dd8565b602002602001018181525050612ab98f8d85600081518110612aaa57612aaa613dd8565b60200260200101518587612f60565b50612ba6565b60018e015460405163b28a7bad60e01b81526001600160a01b038f81166004830152600092169063b28a7bad90602401602060405180830381865afa158015612b0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b309190613dee565b60ff1690506064612b41828d613d0f565b612b4b9190613e0b565b612b559088613d58565b96506064612b63828d613d0f565b612b6d9190613e0b565b83600081518110612b8057612b80613dd8565b602002602001018181525050612ba48f8d85600081518110612aaa57612aaa613dd8565b505b5050612c9d565b60038c0154604051637a99dc0160e11b81526001600160a01b038d81166004830152602482018d9052604482018b9052600092839291169063f533b802906064016000604051808303816000875af1158015612c0d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c359190810190613ebc565b915091506000805b8251811015612c7f57828181518110612c5857612c58613dd8565b602002602001015182612c6b9190613cfc565b915080612c7781613d3f565b915050612c3d565b50612c8a8188613d58565b9650612c998f8d838686612f60565b5050505b6000865167ffffffffffffffff811115612cb957612cb9613692565b604051908082528060200260200182016040528015612ce2578160200160208202803683370190505b5090506000805b8851811015612d96576064888281518110612d0657612d06613dd8565b602002602001015160ff1688612d1c9190613d0f565b612d269190613e0b565b838281518110612d3857612d38613dd8565b6020026020010181815250506064888281518110612d5857612d58613dd8565b602002602001015160ff1688612d6e9190613d0f565b612d789190613e0b565b612d829083613cfc565b915080612d8e81613d3f565b915050612ce9565b50612da48e8c838b86612f60565b5050505050505050505050505050565b6001600160a01b0381163b612e215760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016105e1565b60008051602061407983398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b612e59836130c7565b600082511180612e665750805b15611edc576121e48383613107565b600054610100900460ff16612e9c5760405162461bcd60e51b81526004016105e190613d6b565b610b5133612019565b600083815b8351811015612eea57612ed682858381518110612ec957612ec9613dd8565b6020026020010151613133565b915080612ee281613d3f565b915050612eaa565b509092149392505050565b6040516001600160a01b03808516602483015283166044820152606481018290526121e49085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613199565b6001600160a01b03841661304f57600485015460405160009182916001600160a01b0390911690869063c176e63960e01b90612fa29088908890602401613f81565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612fe09190614029565b60006040518083038185875af1925050503d806000811461301d576040519150601f19603f3d011682016040523d82523d6000602084013e613022565b606091505b50915091508181906130475760405162461bcd60e51b81526004016105e19190614045565b5050506106d4565b8360005b83518110156130be576130ac84828151811061307157613071613dd8565b602002602001015184838151811061308b5761308b613dd8565b6020026020010151846001600160a01b031661326e9092919063ffffffff16565b806130b681613d3f565b915050613053565b50505050505050565b6130d081612db4565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061312c83836040518060600160405280602781526020016140996027913961329e565b9392505050565b60008183111561316c5760408051602081018490529081018490526060016040516020818303038152906040528051906020012061312c565b50604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60006131ee826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166133169092919063ffffffff16565b905080516000148061320f57508080602001905181019061320f9190613db6565b611edc5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016105e1565b6040516001600160a01b038316602482015260448101829052611edc90849063a9059cbb60e01b90606401612f29565b6060600080856001600160a01b0316856040516132bb9190614029565b600060405180830381855af49150503d80600081146132f6576040519150601f19603f3d011682016040523d82523d6000602084013e6132fb565b606091505b509150915061330c8683838761332d565b9695505050505050565b606061332584846000856133a6565b949350505050565b6060831561339c578251600003613395576001600160a01b0385163b6133955760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105e1565b5081613325565b6133258383613481565b6060824710156134075760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016105e1565b600080866001600160a01b031685876040516134239190614029565b60006040518083038185875af1925050503d8060008114613460576040519150601f19603f3d011682016040523d82523d6000602084013e613465565b606091505b50915091506134768783838761332d565b979650505050505050565b8151156134915781518083602001fd5b8060405162461bcd60e51b81526004016105e19190614045565b828054828255906000526020600020908101928215613500579160200282015b8281111561350057825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906134cb565b5061350c9291506135ad565b5090565b82805482825590600052602060002090601f016020900481019282156135005791602002820160005b8382111561357757835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302613539565b80156135a45782816101000a81549060ff0219169055600101602081600001049283019260010302613577565b505061350c9291505b5b8082111561350c57600081556001016135ae565b6001600160a01b038116811461088357600080fd5b6000602082840312156135e957600080fd5b813561312c816135c2565b60008060006060848603121561360957600080fd5b83359250602084013591506040840135613622816135c2565b809150509250925092565b6000806040838503121561364057600080fd5b823561364b816135c2565b9150602083013561365b816135c2565b809150509250929050565b6000806040838503121561367957600080fd5b8235613684816135c2565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156136d1576136d1613692565b604052919050565b600080604083850312156136ec57600080fd5b82356136f7816135c2565b915060208381013567ffffffffffffffff8082111561371557600080fd5b818601915086601f83011261372957600080fd5b81358181111561373b5761373b613692565b61374d601f8201601f191685016136a8565b9150808252878482850101111561376357600080fd5b80848401858401376000848284010152508093505050509250929050565b60008083601f84011261379357600080fd5b50813567ffffffffffffffff8111156137ab57600080fd5b6020830191508360208260051b85010111156137c657600080fd5b9250929050565b600080600080600080600080600060e08a8c0312156137eb57600080fd5b89356137f6816135c2565b985060208a0135613806816135c2565b975060408a0135965060608a0135955060808a0135945060a08a013567ffffffffffffffff8082111561383857600080fd5b6138448d838e01613781565b909650945060c08c013591508082111561385d57600080fd5b5061386a8c828d01613781565b915080935050809150509295985092959850929598565b600080600080600080600080610100898b03121561389e57600080fd5b88356138a9816135c2565b975060208901356138b9816135c2565b965060408901356138c9816135c2565b955060608901356138d9816135c2565b945060808901356138e9816135c2565b935060a08901356138f9816135c2565b925060c0890135613909816135c2565b915060e0890135613919816135c2565b809150509295985092959890939650565b600081518084526020808501945080840160005b8381101561395d57815160ff168752958201959082019060010161393e565b509495945050505050565b60006020808352610100830160018060a01b03808651168386015280838701511660408601526040860151606086015260608601516080860152608086015160a086015260a086015160e060c0870152828151808552610120880191508583019450600092505b808310156139f1578451841682529385019360019290920191908501906139cf565b5060c0880151878203601f190160e08901529450613a0f818661392a565b98975050505050505050565b60ff8116811461088357600080fd5b60008060008060008060a08789031215613a4357600080fd5b8635613a4e816135c2565b95506020870135613a5e816135c2565b9450604087013593506060870135613a7581613a1b565b9250608087013567ffffffffffffffff811115613a9157600080fd5b613a9d89828a01613781565b979a9699509497509295939492505050565b600060208284031215613ac157600080fd5b815161312c816135c2565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b600060a082018983526020898185015288604085015260a060608501528187835260c08501905088925060005b88811015613bbf578335613ba4816135c2565b6001600160a01b031682529282019290820190600101613b91565b508481036080860152858152810191508560005b86811015613bfb578135613be681613a1b565b60ff1684529282019290820190600101613bd3565b50919b9a5050505050505050505050565b8051613c17816135c2565b919050565b6000610100808385031215613c3057600080fd5b6040519081019067ffffffffffffffff82118183101715613c5357613c53613692565b8160405283519150613c64826135c2565b818152613c7360208501613c0c565b6020820152613c8460408501613c0c565b6040820152613c9560608501613c0c565b6060820152613ca660808501613c0c565b6080820152613cb760a08501613c0c565b60a0820152613cc860c08501613c0c565b60c0820152613cd960e08501613c0c565b60e0820152949350505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561075257610752613ce6565b808202811582820484141761075257610752613ce6565b600060208284031215613d3857600080fd5b5051919050565b600060018201613d5157613d51613ce6565b5060010190565b8181038181111561075257610752613ce6565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215613dc857600080fd5b8151801515811461312c57600080fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e0057600080fd5b815161312c81613a1b565b600082613e2857634e487b7160e01b600052601260045260246000fd5b500490565b600067ffffffffffffffff821115613e4757613e47613692565b5060051b60200190565b600082601f830112613e6257600080fd5b81516020613e77613e7283613e2d565b6136a8565b82815260059290921b84018101918181019086841115613e9657600080fd5b8286015b84811015613eb15780518352918301918301613e9a565b509695505050505050565b60008060408385031215613ecf57600080fd5b825167ffffffffffffffff80821115613ee757600080fd5b818501915085601f830112613efb57600080fd5b81516020613f0b613e7283613e2d565b82815260059290921b84018101918181019089841115613f2a57600080fd5b948201945b83861015613f51578551613f42816135c2565b82529482019490820190613f2f565b91880151919650909350505080821115613f6a57600080fd5b50613f7785828601613e51565b9150509250929050565b604080825283519082018190526000906020906060840190828701845b82811015613fc35781516001600160a01b031684529284019290840190600101613f9e565b5050508381038285015284518082528583019183019060005b81811015613ff857835183529284019291840191600101613fdc565b5090979650505050505050565b60005b83811015614020578181015183820152602001614008565b50506000910152565b6000825161403b818460208701614005565b9190910192915050565b6020815260008251806020840152614064816040850160208701614005565b601f01601f1916919091016040019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220ef0b71db6534f219accc034663d81d3861071560ac70b8fddf90a8f5f676a2a064736f6c63430008120033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
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  ]

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.