ETH Price: $3,225.51 (-3.71%)

Contract

0x29226ce3ca83BD04F5F60824C63e6F762E71e160

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

> 10 Internal Transactions found.

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
1057970812023-06-19 16:42:19580 days ago1687192939
0x29226ce3...62E71e160
0 ETH
1057961922023-06-19 16:12:41580 days ago1687191161
0x29226ce3...62E71e160
0 ETH
1057961912023-06-19 16:12:39580 days ago1687191159
0x29226ce3...62E71e160
0 ETH
1057961852023-06-19 16:12:27580 days ago1687191147
0x29226ce3...62E71e160
0 ETH
1057961842023-06-19 16:12:25580 days ago1687191145
0x29226ce3...62E71e160
0 ETH
1057961662023-06-19 16:11:49580 days ago1687191109
0x29226ce3...62E71e160
0 ETH
1057946742023-06-19 15:22:05580 days ago1687188125
0x29226ce3...62E71e160
0 ETH
1057946742023-06-19 15:22:05580 days ago1687188125
0x29226ce3...62E71e160
0 ETH
1057946742023-06-19 15:22:05580 days ago1687188125
0x29226ce3...62E71e160
0 ETH
1057946742023-06-19 15:22:05580 days ago1687188125
0x29226ce3...62E71e160
0 ETH
1057946742023-06-19 15:22:05580 days ago1687188125
0x29226ce3...62E71e160
0 ETH
1057946742023-06-19 15:22:05580 days ago1687188125
0x29226ce3...62E71e160
0 ETH
1057946742023-06-19 15:22:05580 days ago1687188125
0x29226ce3...62E71e160
0 ETH
1057946742023-06-19 15:22:05580 days ago1687188125
0x29226ce3...62E71e160
0 ETH
1057946742023-06-19 15:22:05580 days ago1687188125
0x29226ce3...62E71e160
0 ETH
1057894862023-06-19 12:29:09580 days ago1687177749
0x29226ce3...62E71e160
0 ETH
1057894722023-06-19 12:28:41580 days ago1687177721
0x29226ce3...62E71e160
0 ETH
1057894662023-06-19 12:28:29580 days ago1687177709
0x29226ce3...62E71e160
0 ETH
1057894632023-06-19 12:28:23580 days ago1687177703
0x29226ce3...62E71e160
0 ETH
1057889902023-06-19 12:12:37580 days ago1687176757
0x29226ce3...62E71e160
0 ETH
1057882182023-06-19 11:46:53580 days ago1687175213
0x29226ce3...62E71e160
0 ETH
1057881742023-06-19 11:45:25580 days ago1687175125
0x29226ce3...62E71e160
0 ETH
1057881402023-06-19 11:44:17580 days ago1687175057
0x29226ce3...62E71e160
0 ETH
1057881052023-06-19 11:43:07580 days ago1687174987
0x29226ce3...62E71e160
0 ETH
1057881022023-06-19 11:43:01580 days ago1687174981
0x29226ce3...62E71e160
0 ETH
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
HolographDropERC721

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 999999 runs

Other Settings:
default evmVersion
File 1 of 26 : HolographDropERC721.sol
// SPDX-License-Identifier: UNLICENSED
/*

                         ┌───────────┐
                         │ HOLOGRAPH │
                         └───────────┘
╔═════════════════════════════════════════════════════════════╗
║                                                             ║
║                            / ^ \                            ║
║                            ~~*~~            ¸               ║
║                         [ '<>:<>' ]         │░░░            ║
║               ╔╗           _/"\_           ╔╣               ║
║             ┌─╬╬─┐          """          ┌─╬╬─┐             ║
║          ┌─┬┘ ╠╣ └┬─┐       \_/       ┌─┬┘ ╠╣ └┬─┐          ║
║       ┌─┬┘ │  ╠╣  │ └┬─┐           ┌─┬┘ │  ╠╣  │ └┬─┐       ║
║    ┌─┬┘ │  │  ╠╣  │  │ └┬─┐     ┌─┬┘ │  │  ╠╣  │  │ └┬─┐    ║
║ ┌─┬┘ │  │  │  ╠╣  │  │  │ └┬┐ ┌┬┘ │  │  │  ╠╣  │  │  │ └┬─┐ ║
╠┬┘ │  │  │  │  ╠╣  │  │  │  │└¤┘│  │  │  │  ╠╣  │  │  │  │ └┬╣
║│  │  │  │  │  ╠╣  │  │  │  │   │  │  │  │  ╠╣  │  │  │  │  │║
╠╩══╩══╩══╩══╩══╬╬══╩══╩══╩══╩═══╩══╩══╩══╩══╬╬══╩══╩══╩══╩══╩╣
╠┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╣
║               ╠╣                           ╠╣               ║
║               ╠╣                           ╠╣               ║
║    ,          ╠╣     ,        ,'      *    ╠╣               ║
║~~~~~^~~~~~~~~┌╬╬┐~~~^~~~~~~~~^^~~~~~~~~^~~┌╬╬┐~~~~~~~^~~~~~~║
╚══════════════╩╩╩╩═════════════════════════╩╩╩╩══════════════╝
     - one protocol, one bridge = infinite possibilities -


 ***************************************************************

 DISCLAIMER: U.S Patent Pending

 LICENSE: Holograph Limited Public License (H-LPL)

 https://holograph.xyz/licenses/h-lpl/1.0.0

 This license governs use of the accompanying software. If you
 use the software, you accept this license. If you do not accept
 the license, you are not permitted to use the software.

 1. Definitions

 The terms "reproduce," "reproduction," "derivative works," and
 "distribution" have the same meaning here as under U.S.
 copyright law. A "contribution" is the original software, or
 any additions or changes to the software. A "contributor" is
 any person that distributes its contribution under this
 license. "Licensed patents" are a contributor’s patent claims
 that read directly on its contribution.

 2. Grant of Rights

 A) Copyright Grant- Subject to the terms of this license,
 including the license conditions and limitations in sections 3
 and 4, each contributor grants you a non-exclusive, worldwide,
 royalty-free copyright license to reproduce its contribution,
 prepare derivative works of its contribution, and distribute
 its contribution or any derivative works that you create.
 B) Patent Grant- Subject to the terms of this license,
 including the license conditions and limitations in section 3,
 each contributor grants you a non-exclusive, worldwide,
 royalty-free license under its licensed patents to make, have
 made, use, sell, offer for sale, import, and/or otherwise
 dispose of its contribution in the software or derivative works
 of the contribution in the software.

 3. Conditions and Limitations

 A) No Trademark License- This license does not grant you rights
 to use any contributors’ name, logo, or trademarks.
 B) If you bring a patent claim against any contributor over
 patents that you claim are infringed by the software, your
 patent license from such contributor is terminated with
 immediate effect.
 C) If you distribute any portion of the software, you must
 retain all copyright, patent, trademark, and attribution
 notices that are present in the software.
 D) If you distribute any portion of the software in source code
 form, you may do so only under this license by including a
 complete copy of this license with your distribution. If you
 distribute any portion of the software in compiled or object
 code form, you may only do so under a license that complies
 with this license.
 E) The software is licensed “as-is.” You bear all risks of
 using it. The contributors give no express warranties,
 guarantees, or conditions. You may have additional consumer
 rights under your local laws which this license cannot change.
 To the extent permitted under your local laws, the contributors
 exclude all implied warranties, including those of
 merchantability, fitness for a particular purpose and
 non-infringement.

 4. (F) Platform Limitation- The licenses granted in sections
 2.A & 2.B extend only to the software or derivative works that
 you create that run on a Holograph system product.

 ***************************************************************

*/

pragma solidity 0.8.13;

import {ERC721H} from "../../abstract/ERC721H.sol";
import {NonReentrant} from "../../abstract/NonReentrant.sol";

import {HolographERC721Interface} from "../../interface/HolographERC721Interface.sol";
import {HolographerInterface} from "../../interface/HolographerInterface.sol";
import {HolographInterface} from "../../interface/HolographInterface.sol";

import {AddressMintDetails} from "../struct/AddressMintDetails.sol";
import {Configuration} from "../struct/Configuration.sol";
import {DropsInitializer} from "../struct/DropsInitializer.sol";
import {SaleDetails} from "../struct/SaleDetails.sol";
import {SalesConfiguration} from "../struct/SalesConfiguration.sol";

import {Address} from "../library/Address.sol";
import {MerkleProof} from "../library/MerkleProof.sol";

import {IMetadataRenderer} from "../interface/IMetadataRenderer.sol";
import {IOperatorFilterRegistry} from "../interface/IOperatorFilterRegistry.sol";
import {IHolographDropERC721} from "../interface/IHolographDropERC721.sol";

import {IDropsPriceOracle} from "../interface/IDropsPriceOracle.sol";

/**
 * @dev This contract subscribes to the following HolographERC721 events:
 *       - beforeSafeTransfer
 *       - beforeTransfer
 *       - onIsApprovedForAll
 *       - customContractURI
 *
 *       Do not enable or subscribe to any other events unless you modified your source code for them.
 */
contract HolographDropERC721 is NonReentrant, ERC721H, IHolographDropERC721 {
  /**
   * CONTRACT VARIABLES
   * all variables, without custom storage slots, are defined here
   */

  /**
   * @dev bytes32(uint256(keccak256('eip1967.Holograph.osRegistryEnabled')) - 1)
   */
  bytes32 constant _osRegistryEnabledSlot = 0x5c835f3b6bd322d9a084ffdeac746df2b96cce308e7f0612f4ff4f9c490734cc;

  /**
   * @dev Address of the operator filter registry
   */
  IOperatorFilterRegistry public constant openseaOperatorFilterRegistry =
    IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);

  /**
   * @dev Address of the price oracle proxy
   */
  IDropsPriceOracle public constant dropsPriceOracle = IDropsPriceOracle(0xA3Db09EEC42BAfF7A50fb8F9aF90A0e035Ef3302);

  /**
   * @dev Internal reference used for minting incremental token ids.
   */
  uint224 private _currentTokenId;

  /**
   * @dev HOLOGRAPH transfer helper address for auto-approval
   */
  address public erc721TransferHelper;

  /**
   * @dev Address of the market filter registry
   */
  address public marketFilterAddress;

  /**
   * @notice Configuration for NFT minting contract storage
   */
  Configuration public config;

  /**
   * @notice Sales configuration
   */
  SalesConfiguration public salesConfig;

  /**
   * @dev Mapping for presale mint counts by address to allow public mint limit
   */
  mapping(address => uint256) public presaleMintsByAddress;

  /**
   * @dev Mapping for presale mint counts by address to allow public mint limit
   */
  mapping(address => uint256) public totalMintsByAddress;

  /**
   * CUSTOM ERRORS
   */

  /**
   * @notice Thrown when there is no active market filter address supported for the current chain
   * @dev Used for enabling and disabling filter for the given chain.
   */
  error MarketFilterAddressNotSupportedForChain();

  /**
   * MODIFIERS
   */

  /**
   * @notice Allows user to mint tokens at a quantity
   */
  modifier canMintTokens(uint256 quantity) {
    if (config.editionSize != 0 && quantity + _currentTokenId > config.editionSize) {
      revert Mint_SoldOut();
    }

    _;
  }

  /**
   * @notice Presale active
   */
  modifier onlyPresaleActive() {
    if (!_presaleActive()) {
      revert Presale_Inactive();
    }

    _;
  }

  /**
   * @notice Public sale active
   */
  modifier onlyPublicSaleActive() {
    if (!_publicSaleActive()) {
      revert Sale_Inactive();
    }

    _;
  }

  /**
   * CONTRACT INITIALIZERS
   * init function is used instead of constructor
   */

  /**
   * @dev Constructor is left empty and init is used instead
   */
  constructor() {}

  /**
   * @notice Used internally to initialize the contract instead of through a constructor
   * @dev This function is called by the deployer/factory when creating a contract
   * @param initPayload abi encoded payload to use for contract initilaization
   */
  function init(bytes memory initPayload) external override returns (bytes4) {
    require(!_isInitialized(), "HOLOGRAPH: already initialized");

    DropsInitializer memory initializer = abi.decode(initPayload, (DropsInitializer));

    erc721TransferHelper = initializer.erc721TransferHelper;
    if (initializer.marketFilterAddress != address(0)) {
      marketFilterAddress = initializer.marketFilterAddress;
    }

    // Setup the owner role
    _setOwner(initializer.initialOwner);

    // Setup config variables
    config = Configuration({
      metadataRenderer: IMetadataRenderer(initializer.metadataRenderer),
      editionSize: initializer.editionSize,
      royaltyBPS: initializer.royaltyBPS,
      fundsRecipient: initializer.fundsRecipient
    });

    salesConfig = initializer.salesConfiguration;

    // TODO: Need to make sure to initialize the metadata renderer
    if (initializer.metadataRenderer != address(0)) {
      IMetadataRenderer(initializer.metadataRenderer).initializeWithData(initializer.metadataRendererInit);
    }

    if (initializer.enableOpenSeaRoyaltyRegistry && Address.isContract(address(openseaOperatorFilterRegistry))) {
      if (marketFilterAddress == address(0)) {
        // this is a default filter that can be used for OS royalty filtering
        // marketFilterAddress = 0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6;
        // we just register to OS royalties and let OS handle it for us with their default filter contract
        openseaOperatorFilterRegistry.register(address(this));
      } else {
        // allow user to specify custom filtering contract address
        openseaOperatorFilterRegistry.registerAndSubscribe(address(this), marketFilterAddress);
      }
      assembly {
        sstore(_osRegistryEnabledSlot, true)
      }
    }

    setStatus(1);

    return _init(initPayload);
  }

  /**
   * PUBLIC NON STATE CHANGING FUNCTIONS
   * static
   */

  /**
   * @notice Returns the version of the contract
   * @dev Used for contract versioning and validation
   * @return version string representing the version of the contract
   */
  function version() external pure returns (string memory) {
    return "1.0.0";
  }

  function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
    return interfaceId == type(IHolographDropERC721).interfaceId;
  }

  /**
   * PUBLIC NON STATE CHANGING FUNCTIONS
   * dynamic
   */

  function owner() external view override(ERC721H, IHolographDropERC721) returns (address) {
    return _getOwner();
  }

  function isAdmin(address user) external view returns (bool) {
    return (_getOwner() == user);
  }

  function beforeSafeTransfer(
    address _from,
    address /* _to*/,
    uint256 /* _tokenId*/,
    bytes calldata /* _data*/
  ) external view returns (bool) {
    if (
      _from != address(0) && // skip on mints
      _from != msgSender() // skip on transfers from sender
    ) {
      bool osRegistryEnabled;
      assembly {
        osRegistryEnabled := sload(_osRegistryEnabledSlot)
      }
      if (osRegistryEnabled) {
        try openseaOperatorFilterRegistry.isOperatorAllowed(address(this), msgSender()) returns (bool allowed) {
          return allowed;
        } catch {
          revert OperatorNotAllowed(msgSender());
        }
      }
    }
    return true;
  }

  function beforeTransfer(
    address _from,
    address /* _to*/,
    uint256 /* _tokenId*/,
    bytes calldata /* _data*/
  ) external view returns (bool) {
    if (
      _from != address(0) && // skip on mints
      _from != msgSender() // skip on transfers from sender
    ) {
      bool osRegistryEnabled;
      assembly {
        osRegistryEnabled := sload(_osRegistryEnabledSlot)
      }
      if (osRegistryEnabled) {
        try openseaOperatorFilterRegistry.isOperatorAllowed(address(this), msgSender()) returns (bool allowed) {
          return allowed;
        } catch {
          revert OperatorNotAllowed(msgSender());
        }
      }
    }
    return true;
  }

  function onIsApprovedForAll(address /* _wallet*/, address _operator) external view returns (bool approved) {
    approved = (erc721TransferHelper != address(0) && _operator == erc721TransferHelper);
  }

  /**
   * @notice Sale details
   * @return SaleDetails sale information details
   */
  function saleDetails() external view returns (SaleDetails memory) {
    return
      SaleDetails({
        publicSaleActive: _publicSaleActive(),
        presaleActive: _presaleActive(),
        publicSalePrice: salesConfig.publicSalePrice,
        publicSaleStart: salesConfig.publicSaleStart,
        publicSaleEnd: salesConfig.publicSaleEnd,
        presaleStart: salesConfig.presaleStart,
        presaleEnd: salesConfig.presaleEnd,
        presaleMerkleRoot: salesConfig.presaleMerkleRoot,
        totalMinted: _currentTokenId,
        maxSupply: config.editionSize,
        maxSalePurchasePerAddress: salesConfig.maxSalePurchasePerAddress
      });
  }

  /**
   * @dev Number of NFTs the user has minted per address
   * @param minter to get counts for
   */
  function mintedPerAddress(address minter) external view returns (AddressMintDetails memory) {
    return
      AddressMintDetails({
        presaleMints: presaleMintsByAddress[minter],
        publicMints: totalMintsByAddress[minter] - presaleMintsByAddress[minter],
        totalMints: totalMintsByAddress[minter]
      });
  }

  /**
   * @notice Contract URI Getter, proxies to metadataRenderer
   * @return Contract URI
   */
  function contractURI() external view returns (string memory) {
    return config.metadataRenderer.contractURI();
  }

  /**
   * @notice Getter for metadataRenderer contract
   */
  function metadataRenderer() external view returns (IMetadataRenderer) {
    return IMetadataRenderer(config.metadataRenderer);
  }

  /**
   * @notice Convert USD price to current price in native Ether
   */
  function getNativePrice() external view returns (uint256) {
    return _usdToWei(salesConfig.publicSalePrice);
  }

  /**
   * @notice Returns the name of the token through the holographer entrypoint
   */
  function name() external view returns (string memory) {
    return HolographERC721Interface(holographer()).name();
  }

  /**
   * @notice Token URI Getter, proxies to metadataRenderer
   * @param tokenId id of token to get URI for
   * @return Token URI
   */
  function tokenURI(uint256 tokenId) external view returns (string memory) {
    HolographERC721Interface H721 = HolographERC721Interface(holographer());
    require(H721.exists(tokenId), "ERC721: token does not exist");

    return config.metadataRenderer.tokenURI(tokenId);
  }

  /**
   * PUBLIC STATE CHANGING FUNCTIONS
   * available to all
   */

  function multicall(bytes[] memory data) public returns (bytes[] memory results) {
    results = new bytes[](data.length);
    for (uint256 i = 0; i < data.length; i++) {
      results[i] = Address.functionDelegateCall(address(this), abi.encodePacked(data[i], msgSender()));
    }
  }

  /**
   * @dev This allows the user to purchase/mint a edition at the given price in the contract.
   */
  function purchase(
    uint256 quantity
  ) external payable nonReentrant canMintTokens(quantity) onlyPublicSaleActive returns (uint256) {
    uint256 salePrice = _usdToWei(salesConfig.publicSalePrice);

    if (msg.value < salePrice * quantity) {
      revert Purchase_WrongPrice(salesConfig.publicSalePrice * quantity);
    }
    uint256 remainder = msg.value - (salePrice * quantity);

    // If max purchase per address == 0 there is no limit.
    // Any other number, the per address mint limit is that.
    if (
      salesConfig.maxSalePurchasePerAddress != 0 &&
      totalMintsByAddress[msgSender()] + quantity - presaleMintsByAddress[msgSender()] >
      salesConfig.maxSalePurchasePerAddress
    ) {
      revert Purchase_TooManyForAddress();
    }

    _mintNFTs(msgSender(), quantity);

    HolographERC721Interface H721 = HolographERC721Interface(holographer());
    uint256 chainPrepend = H721.sourceGetChainPrepend();
    uint256 firstMintedTokenId = (chainPrepend + uint256(_currentTokenId - quantity)) + 1;

    emit Sale({
      to: msgSender(),
      quantity: quantity,
      pricePerToken: salePrice,
      firstPurchasedTokenId: firstMintedTokenId
    });

    if (remainder > 0) {
      msgSender().call{value: remainder, gas: gasleft() > 210_000 ? 210_000 : gasleft()}("");
    }

    return firstMintedTokenId;
  }

  /**
   * @notice Merkle-tree based presale purchase function
   * @param quantity quantity to purchase
   * @param maxQuantity max quantity that can be purchased via merkle proof #
   * @param pricePerToken price that each token is purchased at
   * @param merkleProof proof for presale mint
   */
  function purchasePresale(
    uint256 quantity,
    uint256 maxQuantity,
    uint256 pricePerToken,
    bytes32[] calldata merkleProof
  ) external payable nonReentrant canMintTokens(quantity) onlyPresaleActive returns (uint256) {
    if (
      !MerkleProof.verify(
        merkleProof,
        salesConfig.presaleMerkleRoot,
        keccak256(
          // address, uint256, uint256
          abi.encode(msgSender(), maxQuantity, pricePerToken)
        )
      )
    ) {
      revert Presale_MerkleNotApproved();
    }

    uint256 weiPricePerToken = _usdToWei(pricePerToken);
    if (msg.value < weiPricePerToken * quantity) {
      revert Purchase_WrongPrice(pricePerToken * quantity);
    }
    uint256 remainder = msg.value - (weiPricePerToken * quantity);

    presaleMintsByAddress[msgSender()] += quantity;
    if (presaleMintsByAddress[msgSender()] > maxQuantity) {
      revert Presale_TooManyForAddress();
    }

    _mintNFTs(msgSender(), quantity);

    HolographERC721Interface H721 = HolographERC721Interface(holographer());
    uint256 chainPrepend = H721.sourceGetChainPrepend();
    uint256 firstMintedTokenId = (chainPrepend + uint256(_currentTokenId - quantity)) + 1;

    emit Sale({
      to: msgSender(),
      quantity: quantity,
      pricePerToken: weiPricePerToken,
      firstPurchasedTokenId: firstMintedTokenId
    });

    if (remainder > 0) {
      msgSender().call{value: remainder, gas: gasleft() > 210_000 ? 210_000 : gasleft()}("");
    }

    return firstMintedTokenId;
  }

  /**
   * PUBLIC STATE CHANGING FUNCTIONS
   * admin only
   */

  /**
   * @notice Proxy to update market filter settings in the main registry contracts
   * @notice Requires admin permissions
   * @param args Calldata args to pass to the registry
   */
  function updateMarketFilterSettings(bytes calldata args) external onlyOwner returns (bytes memory) {
    (bool success, bytes memory ret) = address(openseaOperatorFilterRegistry).call(args);
    if (!success) {
      revert RemoteOperatorFilterRegistryCallFailed();
    }
    bool osRegistryEnabled = openseaOperatorFilterRegistry.isRegistered(address(this));
    assembly {
      sstore(_osRegistryEnabledSlot, osRegistryEnabled)
    }
    return ret;
  }

  /**
   * @notice Manage subscription for marketplace filtering based off royalty payouts.
   * @param enable Enable filtering to non-royalty payout marketplaces
   */
  function manageMarketFilterSubscription(bool enable) external onlyOwner {
    address self = address(this);
    if (marketFilterAddress == address(0)) {
      revert MarketFilterAddressNotSupportedForChain();
    }
    if (!openseaOperatorFilterRegistry.isRegistered(self) && enable) {
      openseaOperatorFilterRegistry.registerAndSubscribe(self, marketFilterAddress);
    } else if (enable) {
      openseaOperatorFilterRegistry.subscribe(self, marketFilterAddress);
    } else {
      openseaOperatorFilterRegistry.unsubscribe(self, false);
      openseaOperatorFilterRegistry.unregister(self);
    }
    bool osRegistryEnabled = openseaOperatorFilterRegistry.isRegistered(address(this));
    assembly {
      sstore(_osRegistryEnabledSlot, osRegistryEnabled)
    }
  }

  function modifyMarketFilterAddress(address newMarketFilterAddress) external onlyOwner {
    marketFilterAddress = newMarketFilterAddress;
  }

  /**
   * @notice Admin mint tokens to a recipient for free
   * @param recipient recipient to mint to
   * @param quantity quantity to mint
   */
  function adminMint(address recipient, uint256 quantity) external onlyOwner canMintTokens(quantity) returns (uint256) {
    _mintNFTs(recipient, quantity);

    return _currentTokenId;
  }

  /**
   * @dev Mints multiple editions to the given list of addresses.
   * @param recipients list of addresses to send the newly minted editions to
   */
  function adminMintAirdrop(
    address[] calldata recipients
  ) external onlyOwner canMintTokens(recipients.length) returns (uint256) {
    unchecked {
      for (uint256 i = 0; i < recipients.length; i++) {
        _mintNFTs(recipients[i], 1);
      }
    }

    return _currentTokenId;
  }

  /**
   * @notice Set a new metadata renderer
   * @param newRenderer new renderer address to use
   * @param setupRenderer data to setup new renderer with
   */
  function setMetadataRenderer(IMetadataRenderer newRenderer, bytes memory setupRenderer) external onlyOwner {
    config.metadataRenderer = newRenderer;

    if (setupRenderer.length > 0) {
      newRenderer.initializeWithData(setupRenderer);
    }

    emit UpdatedMetadataRenderer({sender: msgSender(), renderer: newRenderer});
  }

  /**
   * @dev This sets the sales configuration
   * @param publicSalePrice New public sale price
   * @param maxSalePurchasePerAddress Max # of purchases (public) per address allowed
   * @param publicSaleStart unix timestamp when the public sale starts
   * @param publicSaleEnd unix timestamp when the public sale ends (set to 0 to disable)
   * @param presaleStart unix timestamp when the presale starts
   * @param presaleEnd unix timestamp when the presale ends
   * @param presaleMerkleRoot merkle root for the presale information
   */
  function setSaleConfiguration(
    uint104 publicSalePrice,
    uint32 maxSalePurchasePerAddress,
    uint64 publicSaleStart,
    uint64 publicSaleEnd,
    uint64 presaleStart,
    uint64 presaleEnd,
    bytes32 presaleMerkleRoot
  ) external onlyOwner {
    salesConfig.publicSalePrice = publicSalePrice;
    salesConfig.maxSalePurchasePerAddress = maxSalePurchasePerAddress;
    salesConfig.publicSaleStart = publicSaleStart;
    salesConfig.publicSaleEnd = publicSaleEnd;
    salesConfig.presaleStart = presaleStart;
    salesConfig.presaleEnd = presaleEnd;
    salesConfig.presaleMerkleRoot = presaleMerkleRoot;

    emit SalesConfigChanged(msgSender());
  }

  /**
   * @notice Set a different funds recipient
   * @param newRecipientAddress new funds recipient address
   */
  function setFundsRecipient(address payable newRecipientAddress) external onlyOwner {
    if (newRecipientAddress == address(0)) {
      revert("Funds Recipient cannot be 0 address");
    }
    config.fundsRecipient = newRecipientAddress;
    emit FundsRecipientChanged(newRecipientAddress, msgSender());
  }

  /**
   * @notice This withdraws ETH from the contract to the contract owner.
   */
  function withdraw() external override nonReentrant {
    if (config.fundsRecipient == address(0)) {
      revert("Funds Recipient address not set");
    }
    address sender = msgSender();

    // Get fee amount
    uint256 funds = address(this).balance;
    address payable feeRecipient = payable(
      HolographInterface(HolographerInterface(holographer()).getHolograph()).getTreasury()
    );
    // for now set it to 0 since there is no fee
    uint256 holographFee = 0;

    // Check if withdraw is allowed for sender
    if (sender != config.fundsRecipient && sender != _getOwner() && sender != feeRecipient) {
      revert Access_WithdrawNotAllowed();
    }

    // Payout HOLOGRAPH fee
    if (holographFee > 0) {
      (bool successFee, ) = feeRecipient.call{value: holographFee, gas: 210_000}("");
      if (!successFee) {
        revert Withdraw_FundsSendFailure();
      }
      funds -= holographFee;
    }

    // Payout recipient
    (bool successFunds, ) = config.fundsRecipient.call{value: funds, gas: 210_000}("");
    if (!successFunds) {
      revert Withdraw_FundsSendFailure();
    }

    // Emit event for indexing
    emit FundsWithdrawn(sender, config.fundsRecipient, funds, feeRecipient, holographFee);
  }

  /**
   * @notice Admin function to finalize and open edition sale
   */
  function finalizeOpenEdition() external onlyOwner {
    if (config.editionSize != type(uint64).max) {
      revert Admin_UnableToFinalizeNotOpenEdition();
    }

    config.editionSize = uint64(_currentTokenId);
    emit OpenMintFinalized(msgSender(), config.editionSize);
  }

  /**
   * INTERNAL FUNCTIONS
   * non state changing
   */

  function _presaleActive() internal view returns (bool) {
    return salesConfig.presaleStart <= block.timestamp && salesConfig.presaleEnd > block.timestamp;
  }

  function _publicSaleActive() internal view returns (bool) {
    return salesConfig.publicSaleStart <= block.timestamp && salesConfig.publicSaleEnd > block.timestamp;
  }

  function _usdToWei(uint256 amount) internal view returns (uint256 weiAmount) {
    if (amount == 0) {
      return 0;
    }
    weiAmount = dropsPriceOracle.convertUsdToWei(amount);
  }

  /**
   * INTERNAL FUNCTIONS
   * state changing
   */

  function _mintNFTs(address recipient, uint256 quantity) internal {
    HolographERC721Interface H721 = HolographERC721Interface(holographer());
    uint256 chainPrepend = H721.sourceGetChainPrepend();
    uint224 tokenId = 0;
    for (uint256 i = 0; i < quantity; i++) {
      _currentTokenId += 1;
      while (
        H721.exists(chainPrepend + uint256(_currentTokenId)) || H721.burned(chainPrepend + uint256(_currentTokenId))
      ) {
        _currentTokenId += 1;
      }
      tokenId = _currentTokenId;
      H721.sourceMint(recipient, tokenId);
      // uint256 id = chainPrepend + uint256(tokenId);
    }
  }

  fallback() external payable override {
    assembly {
      // Allocate memory for the error message
      let errorMsg := mload(0x40)

      // Error message: "Function not found", properly padded with zeroes
      mstore(errorMsg, 0x46756e6374696f6e206e6f7420666f756e640000000000000000000000000000)

      // Revert with the error message
      revert(errorMsg, 20) // 20 is the length of the error message in bytes
    }
  }
}

File 2 of 26 : ERC721H.sol
// SPDX-License-Identifier: UNLICENSED
/*

                         ┌───────────┐
                         │ HOLOGRAPH │
                         └───────────┘
╔═════════════════════════════════════════════════════════════╗
║                                                             ║
║                            / ^ \                            ║
║                            ~~*~~            ¸               ║
║                         [ '<>:<>' ]         │░░░            ║
║               ╔╗           _/"\_           ╔╣               ║
║             ┌─╬╬─┐          """          ┌─╬╬─┐             ║
║          ┌─┬┘ ╠╣ └┬─┐       \_/       ┌─┬┘ ╠╣ └┬─┐          ║
║       ┌─┬┘ │  ╠╣  │ └┬─┐           ┌─┬┘ │  ╠╣  │ └┬─┐       ║
║    ┌─┬┘ │  │  ╠╣  │  │ └┬─┐     ┌─┬┘ │  │  ╠╣  │  │ └┬─┐    ║
║ ┌─┬┘ │  │  │  ╠╣  │  │  │ └┬┐ ┌┬┘ │  │  │  ╠╣  │  │  │ └┬─┐ ║
╠┬┘ │  │  │  │  ╠╣  │  │  │  │└¤┘│  │  │  │  ╠╣  │  │  │  │ └┬╣
║│  │  │  │  │  ╠╣  │  │  │  │   │  │  │  │  ╠╣  │  │  │  │  │║
╠╩══╩══╩══╩══╩══╬╬══╩══╩══╩══╩═══╩══╩══╩══╩══╬╬══╩══╩══╩══╩══╩╣
╠┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╣
║               ╠╣                           ╠╣               ║
║               ╠╣                           ╠╣               ║
║    ,          ╠╣     ,        ,'      *    ╠╣               ║
║~~~~~^~~~~~~~~┌╬╬┐~~~^~~~~~~~~^^~~~~~~~~^~~┌╬╬┐~~~~~~~^~~~~~~║
╚══════════════╩╩╩╩═════════════════════════╩╩╩╩══════════════╝
     - one protocol, one bridge = infinite possibilities -


 ***************************************************************

 DISCLAIMER: U.S Patent Pending

 LICENSE: Holograph Limited Public License (H-LPL)

 https://holograph.xyz/licenses/h-lpl/1.0.0

 This license governs use of the accompanying software. If you
 use the software, you accept this license. If you do not accept
 the license, you are not permitted to use the software.

 1. Definitions

 The terms "reproduce," "reproduction," "derivative works," and
 "distribution" have the same meaning here as under U.S.
 copyright law. A "contribution" is the original software, or
 any additions or changes to the software. A "contributor" is
 any person that distributes its contribution under this
 license. "Licensed patents" are a contributor’s patent claims
 that read directly on its contribution.

 2. Grant of Rights

 A) Copyright Grant- Subject to the terms of this license,
 including the license conditions and limitations in sections 3
 and 4, each contributor grants you a non-exclusive, worldwide,
 royalty-free copyright license to reproduce its contribution,
 prepare derivative works of its contribution, and distribute
 its contribution or any derivative works that you create.
 B) Patent Grant- Subject to the terms of this license,
 including the license conditions and limitations in section 3,
 each contributor grants you a non-exclusive, worldwide,
 royalty-free license under its licensed patents to make, have
 made, use, sell, offer for sale, import, and/or otherwise
 dispose of its contribution in the software or derivative works
 of the contribution in the software.

 3. Conditions and Limitations

 A) No Trademark License- This license does not grant you rights
 to use any contributors’ name, logo, or trademarks.
 B) If you bring a patent claim against any contributor over
 patents that you claim are infringed by the software, your
 patent license from such contributor is terminated with
 immediate effect.
 C) If you distribute any portion of the software, you must
 retain all copyright, patent, trademark, and attribution
 notices that are present in the software.
 D) If you distribute any portion of the software in source code
 form, you may do so only under this license by including a
 complete copy of this license with your distribution. If you
 distribute any portion of the software in compiled or object
 code form, you may only do so under a license that complies
 with this license.
 E) The software is licensed “as-is.” You bear all risks of
 using it. The contributors give no express warranties,
 guarantees, or conditions. You may have additional consumer
 rights under your local laws which this license cannot change.
 To the extent permitted under your local laws, the contributors
 exclude all implied warranties, including those of
 merchantability, fitness for a particular purpose and
 non-infringement.

 4. (F) Platform Limitation- The licenses granted in sections
 2.A & 2.B extend only to the software or derivative works that
 you create that run on a Holograph system product.

 ***************************************************************

*/

pragma solidity 0.8.13;

import "../abstract/Initializable.sol";

abstract contract ERC721H is Initializable {
  /**
   * @dev bytes32(uint256(keccak256('eip1967.Holograph.holographer')) - 1)
   */
  bytes32 constant _holographerSlot = 0xe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd;
  /**
   * @dev bytes32(uint256(keccak256('eip1967.Holograph.owner')) - 1)
   */
  bytes32 constant _ownerSlot = 0xb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf772777;

  modifier onlyHolographer() {
    require(msg.sender == holographer(), "ERC721: holographer only");
    _;
  }

  modifier onlyOwner() {
    if (msg.sender == holographer()) {
      require(msgSender() == _getOwner(), "ERC721: owner only function");
    } else {
      require(msg.sender == _getOwner(), "ERC721: owner only function");
    }
    _;
  }

  /**
   * @dev Constructor is left empty and init is used instead
   */
  constructor() {}

  /**
   * @notice Used internally to initialize the contract instead of through a constructor
   * @dev This function is called by the deployer/factory when creating a contract
   * @param initPayload abi encoded payload to use for contract initilaization
   */
  function init(bytes memory initPayload) external virtual override returns (bytes4) {
    return _init(initPayload);
  }

  function _init(bytes memory /* initPayload*/) internal returns (bytes4) {
    require(!_isInitialized(), "ERC721: already initialized");
    address _holographer = msg.sender;
    address currentOwner;
    assembly {
      sstore(_holographerSlot, _holographer)
      currentOwner := sload(_ownerSlot)
    }
    require(currentOwner != address(0), "HOLOGRAPH: owner not set");
    _setInitialized();
    return InitializableInterface.init.selector;
  }

  /**
   * @dev The Holographer passes original msg.sender via calldata. This function extracts it.
   */
  function msgSender() internal pure returns (address sender) {
    assembly {
      sender := calldataload(sub(calldatasize(), 0x20))
    }
  }

  /**
   * @dev Address of Holograph ERC721 standards enforcer smart contract.
   */
  function holographer() internal view returns (address _holographer) {
    assembly {
      _holographer := sload(_holographerSlot)
    }
  }

  function supportsInterface(bytes4) external pure virtual returns (bool) {
    return false;
  }

  /**
   * @dev Address of initial creator/owner of the collection.
   */
  function owner() external view virtual returns (address) {
    return _getOwner();
  }

  function isOwner() external view returns (bool) {
    if (msg.sender == holographer()) {
      return msgSender() == _getOwner();
    } else {
      return msg.sender == _getOwner();
    }
  }

  function isOwner(address wallet) external view returns (bool) {
    return wallet == _getOwner();
  }

  function _getOwner() internal view returns (address ownerAddress) {
    assembly {
      ownerAddress := sload(_ownerSlot)
    }
  }

  function _setOwner(address ownerAddress) internal {
    assembly {
      sstore(_ownerSlot, ownerAddress)
    }
  }

  function withdraw() external virtual onlyOwner {
    payable(_getOwner()).transfer(address(this).balance);
  }

  event FundsReceived(address indexed source, uint256 amount);

  /**
   * @dev This function emits an event to indicate native gas token receipt. Do not rely on this to work.
   *      Please use custom payable functions for accepting native value.
   */
  receive() external payable virtual {
    emit FundsReceived(msgSender(), msg.value);
  }

  /**
   * @dev Return true for any un-implemented event hooks
   */
  fallback() external payable virtual {
    assembly {
      switch eq(sload(_holographerSlot), caller())
      case 1 {
        mstore(0x80, 0x0000000000000000000000000000000000000000000000000000000000000001)
        return(0x80, 0x20)
      }
      default {
        revert(0x00, 0x00)
      }
    }
  }
}

File 3 of 26 : Initializable.sol
// SPDX-License-Identifier: UNLICENSED
/*

                         ┌───────────┐
                         │ HOLOGRAPH │
                         └───────────┘
╔═════════════════════════════════════════════════════════════╗
║                                                             ║
║                            / ^ \                            ║
║                            ~~*~~            ¸               ║
║                         [ '<>:<>' ]         │░░░            ║
║               ╔╗           _/"\_           ╔╣               ║
║             ┌─╬╬─┐          """          ┌─╬╬─┐             ║
║          ┌─┬┘ ╠╣ └┬─┐       \_/       ┌─┬┘ ╠╣ └┬─┐          ║
║       ┌─┬┘ │  ╠╣  │ └┬─┐           ┌─┬┘ │  ╠╣  │ └┬─┐       ║
║    ┌─┬┘ │  │  ╠╣  │  │ └┬─┐     ┌─┬┘ │  │  ╠╣  │  │ └┬─┐    ║
║ ┌─┬┘ │  │  │  ╠╣  │  │  │ └┬┐ ┌┬┘ │  │  │  ╠╣  │  │  │ └┬─┐ ║
╠┬┘ │  │  │  │  ╠╣  │  │  │  │└¤┘│  │  │  │  ╠╣  │  │  │  │ └┬╣
║│  │  │  │  │  ╠╣  │  │  │  │   │  │  │  │  ╠╣  │  │  │  │  │║
╠╩══╩══╩══╩══╩══╬╬══╩══╩══╩══╩═══╩══╩══╩══╩══╬╬══╩══╩══╩══╩══╩╣
╠┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╣
║               ╠╣                           ╠╣               ║
║               ╠╣                           ╠╣               ║
║    ,          ╠╣     ,        ,'      *    ╠╣               ║
║~~~~~^~~~~~~~~┌╬╬┐~~~^~~~~~~~~^^~~~~~~~~^~~┌╬╬┐~~~~~~~^~~~~~~║
╚══════════════╩╩╩╩═════════════════════════╩╩╩╩══════════════╝
     - one protocol, one bridge = infinite possibilities -


 ***************************************************************

 DISCLAIMER: U.S Patent Pending

 LICENSE: Holograph Limited Public License (H-LPL)

 https://holograph.xyz/licenses/h-lpl/1.0.0

 This license governs use of the accompanying software. If you
 use the software, you accept this license. If you do not accept
 the license, you are not permitted to use the software.

 1. Definitions

 The terms "reproduce," "reproduction," "derivative works," and
 "distribution" have the same meaning here as under U.S.
 copyright law. A "contribution" is the original software, or
 any additions or changes to the software. A "contributor" is
 any person that distributes its contribution under this
 license. "Licensed patents" are a contributor’s patent claims
 that read directly on its contribution.

 2. Grant of Rights

 A) Copyright Grant- Subject to the terms of this license,
 including the license conditions and limitations in sections 3
 and 4, each contributor grants you a non-exclusive, worldwide,
 royalty-free copyright license to reproduce its contribution,
 prepare derivative works of its contribution, and distribute
 its contribution or any derivative works that you create.
 B) Patent Grant- Subject to the terms of this license,
 including the license conditions and limitations in section 3,
 each contributor grants you a non-exclusive, worldwide,
 royalty-free license under its licensed patents to make, have
 made, use, sell, offer for sale, import, and/or otherwise
 dispose of its contribution in the software or derivative works
 of the contribution in the software.

 3. Conditions and Limitations

 A) No Trademark License- This license does not grant you rights
 to use any contributors’ name, logo, or trademarks.
 B) If you bring a patent claim against any contributor over
 patents that you claim are infringed by the software, your
 patent license from such contributor is terminated with
 immediate effect.
 C) If you distribute any portion of the software, you must
 retain all copyright, patent, trademark, and attribution
 notices that are present in the software.
 D) If you distribute any portion of the software in source code
 form, you may do so only under this license by including a
 complete copy of this license with your distribution. If you
 distribute any portion of the software in compiled or object
 code form, you may only do so under a license that complies
 with this license.
 E) The software is licensed “as-is.” You bear all risks of
 using it. The contributors give no express warranties,
 guarantees, or conditions. You may have additional consumer
 rights under your local laws which this license cannot change.
 To the extent permitted under your local laws, the contributors
 exclude all implied warranties, including those of
 merchantability, fitness for a particular purpose and
 non-infringement.

 4. (F) Platform Limitation- The licenses granted in sections
 2.A & 2.B extend only to the software or derivative works that
 you create that run on a Holograph system product.

 ***************************************************************

*/

pragma solidity 0.8.13;

import "../interface/InitializableInterface.sol";

/**
 * @title Initializable
 * @author https://github.com/holographxyz
 * @notice Use init instead of constructor
 * @dev This allows for use of init function to make one time initializations without the need for a constructor
 */
abstract contract Initializable is InitializableInterface {
  /**
   * @dev bytes32(uint256(keccak256('eip1967.Holograph.initialized')) - 1)
   */
  bytes32 constant _initializedSlot = 0x4e5f991bca30eca2d4643aaefa807e88f96a4a97398933d572a3c0d973004a01;

  /**
   * @dev Constructor is left empty and init is used instead
   */
  constructor() {}

  /**
   * @notice Used internally to initialize the contract instead of through a constructor
   * @dev This function is called by the deployer/factory when creating a contract
   * @param initPayload abi encoded payload to use for contract initilaization
   */
  function init(bytes memory initPayload) external virtual returns (bytes4);

  function _isInitialized() internal view returns (bool initialized) {
    assembly {
      initialized := sload(_initializedSlot)
    }
  }

  function _setInitialized() internal {
    assembly {
      sstore(_initializedSlot, 0x0000000000000000000000000000000000000000000000000000000000000001)
    }
  }
}

File 4 of 26 : NonReentrant.sol
// SPDX-License-Identifier: UNLICENSED
/*

                         ┌───────────┐
                         │ HOLOGRAPH │
                         └───────────┘
╔═════════════════════════════════════════════════════════════╗
║                                                             ║
║                            / ^ \                            ║
║                            ~~*~~            ¸               ║
║                         [ '<>:<>' ]         │░░░            ║
║               ╔╗           _/"\_           ╔╣               ║
║             ┌─╬╬─┐          """          ┌─╬╬─┐             ║
║          ┌─┬┘ ╠╣ └┬─┐       \_/       ┌─┬┘ ╠╣ └┬─┐          ║
║       ┌─┬┘ │  ╠╣  │ └┬─┐           ┌─┬┘ │  ╠╣  │ └┬─┐       ║
║    ┌─┬┘ │  │  ╠╣  │  │ └┬─┐     ┌─┬┘ │  │  ╠╣  │  │ └┬─┐    ║
║ ┌─┬┘ │  │  │  ╠╣  │  │  │ └┬┐ ┌┬┘ │  │  │  ╠╣  │  │  │ └┬─┐ ║
╠┬┘ │  │  │  │  ╠╣  │  │  │  │└¤┘│  │  │  │  ╠╣  │  │  │  │ └┬╣
║│  │  │  │  │  ╠╣  │  │  │  │   │  │  │  │  ╠╣  │  │  │  │  │║
╠╩══╩══╩══╩══╩══╬╬══╩══╩══╩══╩═══╩══╩══╩══╩══╬╬══╩══╩══╩══╩══╩╣
╠┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╣
║               ╠╣                           ╠╣               ║
║               ╠╣                           ╠╣               ║
║    ,          ╠╣     ,        ,'      *    ╠╣               ║
║~~~~~^~~~~~~~~┌╬╬┐~~~^~~~~~~~~^^~~~~~~~~^~~┌╬╬┐~~~~~~~^~~~~~~║
╚══════════════╩╩╩╩═════════════════════════╩╩╩╩══════════════╝
     - one protocol, one bridge = infinite possibilities -


 ***************************************************************

 DISCLAIMER: U.S Patent Pending

 LICENSE: Holograph Limited Public License (H-LPL)

 https://holograph.xyz/licenses/h-lpl/1.0.0

 This license governs use of the accompanying software. If you
 use the software, you accept this license. If you do not accept
 the license, you are not permitted to use the software.

 1. Definitions

 The terms "reproduce," "reproduction," "derivative works," and
 "distribution" have the same meaning here as under U.S.
 copyright law. A "contribution" is the original software, or
 any additions or changes to the software. A "contributor" is
 any person that distributes its contribution under this
 license. "Licensed patents" are a contributor’s patent claims
 that read directly on its contribution.

 2. Grant of Rights

 A) Copyright Grant- Subject to the terms of this license,
 including the license conditions and limitations in sections 3
 and 4, each contributor grants you a non-exclusive, worldwide,
 royalty-free copyright license to reproduce its contribution,
 prepare derivative works of its contribution, and distribute
 its contribution or any derivative works that you create.
 B) Patent Grant- Subject to the terms of this license,
 including the license conditions and limitations in section 3,
 each contributor grants you a non-exclusive, worldwide,
 royalty-free license under its licensed patents to make, have
 made, use, sell, offer for sale, import, and/or otherwise
 dispose of its contribution in the software or derivative works
 of the contribution in the software.

 3. Conditions and Limitations

 A) No Trademark License- This license does not grant you rights
 to use any contributors’ name, logo, or trademarks.
 B) If you bring a patent claim against any contributor over
 patents that you claim are infringed by the software, your
 patent license from such contributor is terminated with
 immediate effect.
 C) If you distribute any portion of the software, you must
 retain all copyright, patent, trademark, and attribution
 notices that are present in the software.
 D) If you distribute any portion of the software in source code
 form, you may do so only under this license by including a
 complete copy of this license with your distribution. If you
 distribute any portion of the software in compiled or object
 code form, you may only do so under a license that complies
 with this license.
 E) The software is licensed “as-is.” You bear all risks of
 using it. The contributors give no express warranties,
 guarantees, or conditions. You may have additional consumer
 rights under your local laws which this license cannot change.
 To the extent permitted under your local laws, the contributors
 exclude all implied warranties, including those of
 merchantability, fitness for a particular purpose and
 non-infringement.

 4. (F) Platform Limitation- The licenses granted in sections
 2.A & 2.B extend only to the software or derivative works that
 you create that run on a Holograph system product.

 ***************************************************************

*/

pragma solidity 0.8.13;

abstract contract NonReentrant {
  /**
   * @dev bytes32(uint256(keccak256('eip1967.Holograph.reentrant')) - 1)
   */
  bytes32 constant _reentrantSlot = 0x04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a3137279;

  modifier nonReentrant() {
    require(getStatus() != 2, "HOLOGRAPH: reentrant call");
    setStatus(2);
    _;
    setStatus(1);
  }

  constructor() {}

  function getStatus() internal view returns (uint256 status) {
    assembly {
      status := sload(_reentrantSlot)
    }
  }

  function setStatus(uint256 status) internal {
    assembly {
      sstore(_reentrantSlot, status)
    }
  }
}

File 5 of 26 : IDropsPriceOracle.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.13;

interface IDropsPriceOracle {
  function convertUsdToWei(uint256 usdAmount) external view returns (uint256 weiAmount);
}

File 6 of 26 : IHolographDropERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.13;

import {IMetadataRenderer} from "./IMetadataRenderer.sol";

import {AddressMintDetails} from "../struct/AddressMintDetails.sol";
import {SaleDetails} from "../struct/SaleDetails.sol";

/// @notice Interface for HOLOGRAPH Drops contract
interface IHolographDropERC721 {
  // Access errors

  /// @notice Only admin can access this function
  error Access_OnlyAdmin();
  /// @notice Missing the given role or admin access
  error Access_MissingRoleOrAdmin(bytes32 role);
  /// @notice Withdraw is not allowed by this user
  error Access_WithdrawNotAllowed();
  /// @notice Cannot withdraw funds due to ETH send failure.
  error Withdraw_FundsSendFailure();
  /// @notice Mint fee send failure
  error MintFee_FundsSendFailure();

  /// @notice Call to external metadata renderer failed.
  error ExternalMetadataRenderer_CallFailed();

  /// @notice Thrown when the operator for the contract is not allowed
  /// @dev Used when strict enforcement of marketplaces for creator royalties is desired.
  error OperatorNotAllowed(address operator);

  /// @notice Thrown when there is no active market filter DAO address supported for the current chain
  /// @dev Used for enabling and disabling filter for the given chain.
  error MarketFilterDAOAddressNotSupportedForChain();

  /// @notice Used when the operator filter registry external call fails
  /// @dev Used for bubbling error up to clients.
  error RemoteOperatorFilterRegistryCallFailed();

  // Sale/Purchase errors
  /// @notice Sale is inactive
  error Sale_Inactive();
  /// @notice Presale is inactive
  error Presale_Inactive();
  /// @notice Presale merkle root is invalid
  error Presale_MerkleNotApproved();
  /// @notice Wrong price for purchase
  error Purchase_WrongPrice(uint256 correctPrice);
  /// @notice NFT sold out
  error Mint_SoldOut();
  /// @notice Too many purchase for address
  error Purchase_TooManyForAddress();
  /// @notice Too many presale for address
  error Presale_TooManyForAddress();

  // Admin errors
  /// @notice Royalty percentage too high
  error Setup_RoyaltyPercentageTooHigh(uint16 maxRoyaltyBPS);
  /// @notice Invalid admin upgrade address
  error Admin_InvalidUpgradeAddress(address proposedAddress);
  /// @notice Unable to finalize an edition not marked as open (size set to uint64_max_value)
  error Admin_UnableToFinalizeNotOpenEdition();

  /// @notice Event emitted for mint fee payout
  /// @param mintFeeAmount amount of the mint fee
  /// @param mintFeeRecipient recipient of the mint fee
  /// @param success if the payout succeeded
  event MintFeePayout(uint256 mintFeeAmount, address mintFeeRecipient, bool success);

  /// @notice Event emitted for each sale
  /// @param to address sale was made to
  /// @param quantity quantity of the minted nfts
  /// @param pricePerToken price for each token
  /// @param firstPurchasedTokenId first purchased token ID (to get range add to quantity for max)
  event Sale(
    address indexed to,
    uint256 indexed quantity,
    uint256 indexed pricePerToken,
    uint256 firstPurchasedTokenId
  );

  /// @notice Sales configuration has been changed
  /// @dev To access new sales configuration, use getter function.
  /// @param changedBy Changed by user
  event SalesConfigChanged(address indexed changedBy);

  /// @notice Event emitted when the funds recipient is changed
  /// @param newAddress new address for the funds recipient
  /// @param changedBy address that the recipient is changed by
  event FundsRecipientChanged(address indexed newAddress, address indexed changedBy);

  /// @notice Event emitted when the funds are withdrawn from the minting contract
  /// @param withdrawnBy address that issued the withdraw
  /// @param withdrawnTo address that the funds were withdrawn to
  /// @param amount amount that was withdrawn
  /// @param feeRecipient user getting withdraw fee (if any)
  /// @param feeAmount amount of the fee getting sent (if any)
  event FundsWithdrawn(
    address indexed withdrawnBy,
    address indexed withdrawnTo,
    uint256 amount,
    address feeRecipient,
    uint256 feeAmount
  );

  /// @notice Event emitted when an open mint is finalized and further minting is closed forever on the contract.
  /// @param sender address sending close mint
  /// @param numberOfMints number of mints the contract is finalized at
  event OpenMintFinalized(address indexed sender, uint256 numberOfMints);

  /// @notice Event emitted when metadata renderer is updated.
  /// @param sender address of the updater
  /// @param renderer new metadata renderer address
  event UpdatedMetadataRenderer(address sender, IMetadataRenderer renderer);

  /// @notice Admin function to update the sales configuration settings
  /// @param publicSalePrice public sale price in ether
  /// @param maxSalePurchasePerAddress Max # of purchases (public) per address allowed
  /// @param publicSaleStart unix timestamp when the public sale starts
  /// @param publicSaleEnd unix timestamp when the public sale ends (set to 0 to disable)
  /// @param presaleStart unix timestamp when the presale starts
  /// @param presaleEnd unix timestamp when the presale ends
  /// @param presaleMerkleRoot merkle root for the presale information
  function setSaleConfiguration(
    uint104 publicSalePrice,
    uint32 maxSalePurchasePerAddress,
    uint64 publicSaleStart,
    uint64 publicSaleEnd,
    uint64 presaleStart,
    uint64 presaleEnd,
    bytes32 presaleMerkleRoot
  ) external;

  /// @notice External purchase function (payable in eth)
  /// @param quantity to purchase
  /// @return first minted token ID
  function purchase(uint256 quantity) external payable returns (uint256);

  /// @notice External purchase presale function (takes a merkle proof and matches to root) (payable in eth)
  /// @param quantity to purchase
  /// @param maxQuantity can purchase (verified by merkle root)
  /// @param pricePerToken price per token allowed (verified by merkle root)
  /// @param merkleProof input for merkle proof leaf verified by merkle root
  /// @return first minted token ID
  function purchasePresale(
    uint256 quantity,
    uint256 maxQuantity,
    uint256 pricePerToken,
    bytes32[] memory merkleProof
  ) external payable returns (uint256);

  /// @notice Function to return the global sales details for the given drop
  function saleDetails() external view returns (SaleDetails memory);

  /// @notice Function to return the specific sales details for a given address
  /// @param minter address for minter to return mint information for
  function mintedPerAddress(address minter) external view returns (AddressMintDetails memory);

  /// @notice This is the opensea/public owner setting that can be set by the contract admin
  function owner() external view returns (address);

  /// @notice Update the metadata renderer
  /// @param newRenderer new address for renderer
  /// @param setupRenderer data to call to bootstrap data for the new renderer (optional)
  function setMetadataRenderer(IMetadataRenderer newRenderer, bytes memory setupRenderer) external;

  /// @notice This is an admin mint function to mint a quantity to a specific address
  /// @param to address to mint to
  /// @param quantity quantity to mint
  /// @return the id of the first minted NFT
  function adminMint(address to, uint256 quantity) external returns (uint256);

  /// @notice This is an admin mint function to mint a single nft each to a list of addresses
  /// @param to list of addresses to mint an NFT each to
  /// @return the id of the first minted NFT
  function adminMintAirdrop(address[] memory to) external returns (uint256);

  /// @dev Getter for admin role associated with the contract to handle metadata
  /// @return boolean if address is admin
  function isAdmin(address user) external view returns (bool);
}

File 7 of 26 : IMetadataRenderer.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.13;

interface IMetadataRenderer {
  function tokenURI(uint256) external view returns (string memory);

  function contractURI() external view returns (string memory);

  function initializeWithData(bytes memory initData) external;
}

File 8 of 26 : IOperatorFilterRegistry.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.13;

interface IOperatorFilterRegistry {
  function isOperatorAllowed(address registrant, address operator) external view returns (bool);

  function register(address registrant) external;

  function registerAndSubscribe(address registrant, address subscription) external;

  function registerAndCopyEntries(address registrant, address registrantToCopy) external;

  function updateOperator(address registrant, address operator, bool filtered) external;

  function updateOperators(address registrant, address[] calldata operators, bool filtered) external;

  function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external;

  function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external;

  function subscribe(address registrant, address registrantToSubscribe) external;

  function unsubscribe(address registrant, bool copyExistingEntries) external;

  function subscriptionOf(address addr) external returns (address registrant);

  function subscribers(address registrant) external returns (address[] memory);

  function subscriberAt(address registrant, uint256 index) external returns (address);

  function copyEntriesOf(address registrant, address registrantToCopy) external;

  function isOperatorFiltered(address registrant, address operator) external returns (bool);

  function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool);

  function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool);

  function filteredOperators(address addr) external returns (address[] memory);

  function filteredCodeHashes(address addr) external returns (bytes32[] memory);

  function filteredOperatorAt(address registrant, uint256 index) external returns (address);

  function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32);

  function isRegistered(address addr) external returns (bool);

  function codeHashOf(address addr) external returns (bytes32);

  function unregister(address registrant) external;
}

File 9 of 26 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.13;

library Address {
  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 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);
    }
  }

  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 10 of 26 : MerkleProof.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.13;

library MerkleProof {
  /**
   * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
   * defined by `root`. For this, a `proof` must be provided, containing
   * sibling hashes on the branch from the leaf to the root of the tree. Each
   * pair of leaves and each pair of pre-images are assumed to be sorted.
   */
  function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
    return processProof(proof, leaf) == root;
  }

  /**
   * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
   * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
   * hash matches the root of the tree. When processing the proof, the pairs
   * of leafs & pre-images are assumed to be sorted.
   *
   * _Available since v4.4._
   */
  function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
    bytes32 computedHash = leaf;
    for (uint256 i = 0; i < proof.length; i++) {
      bytes32 proofElement = proof[i];
      if (computedHash <= proofElement) {
        // Hash(current computed hash + current element of the proof)
        computedHash = _efficientHash(computedHash, proofElement);
      } else {
        // Hash(current element of the proof + current computed hash)
        computedHash = _efficientHash(proofElement, computedHash);
      }
    }
    return computedHash;
  }

  function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
    assembly {
      mstore(0x00, a)
      mstore(0x20, b)
      value := keccak256(0x00, 0x40)
    }
  }
}

File 11 of 26 : AddressMintDetails.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.13;

/// @notice Return type of specific mint counts and details per address
struct AddressMintDetails {
  /// Number of total mints from the given address
  uint256 totalMints;
  /// Number of presale mints from the given address
  uint256 presaleMints;
  /// Number of public mints from the given address
  uint256 publicMints;
}

File 12 of 26 : Configuration.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.13;

import {IMetadataRenderer} from "../interface/IMetadataRenderer.sol";

/// @notice General configuration for NFT Minting and bookkeeping
struct Configuration {
  /// @dev Metadata renderer (uint160)
  IMetadataRenderer metadataRenderer;
  /// @dev Total size of edition that can be minted (uint160+64 = 224)
  uint64 editionSize;
  /// @dev Royalty amount in bps (uint224+16 = 240)
  uint16 royaltyBPS;
  /// @dev Funds recipient for sale (new slot, uint160)
  address payable fundsRecipient;
}

File 13 of 26 : DropsInitializer.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.13;

import {SalesConfiguration} from "./SalesConfiguration.sol";

/// @param erc721TransferHelper Transfer helper contract
/// @param marketFilterAddress Market filter address - Manage subscription to the for marketplace filtering based off royalty payouts.
/// @param initialOwner User that owns and can mint the edition, gets royalty and sales payouts and can update the base url if needed.
/// @param fundsRecipient Wallet/user that receives funds from sale
/// @param editionSize Number of editions that can be minted in total. If type(uint64).max, unlimited editions can be minted as an open edition.
/// @param royaltyBPS BPS of the royalty set on the contract. Can be 0 for no royalty.
/// @param salesConfiguration The initial SalesConfiguration
/// @param metadataRenderer Renderer contract to use
/// @param metadataRendererInit Renderer data initial contract
struct DropsInitializer {
  address erc721TransferHelper;
  address marketFilterAddress;
  address initialOwner;
  address payable fundsRecipient;
  uint64 editionSize;
  uint16 royaltyBPS;
  bool enableOpenSeaRoyaltyRegistry;
  SalesConfiguration salesConfiguration;
  address metadataRenderer;
  bytes metadataRendererInit;
}

File 14 of 26 : SaleDetails.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.13;

/// @notice Return value for sales details to use with front-ends
struct SaleDetails {
  // Synthesized status variables for sale and presale
  bool publicSaleActive;
  bool presaleActive;
  // Price for public sale
  uint256 publicSalePrice;
  // Timed sale actions for public sale
  uint64 publicSaleStart;
  uint64 publicSaleEnd;
  // Timed sale actions for presale
  uint64 presaleStart;
  uint64 presaleEnd;
  // Merkle root (includes address, quantity, and price data for each entry)
  bytes32 presaleMerkleRoot;
  // Limit public sale to a specific number of mints per wallet
  uint256 maxSalePurchasePerAddress;
  // Information about the rest of the supply
  // Total that have been minted
  uint256 totalMinted;
  // The total supply available
  uint256 maxSupply;
}

File 15 of 26 : SalesConfiguration.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.13;

/// @notice Sales states and configuration
/// @dev Uses 3 storage slots
struct SalesConfiguration {
  /// @dev Public sale price (max ether value > 1000 ether with this value)
  uint104 publicSalePrice;
  /// @notice Purchase mint limit per address (if set to 0 === unlimited mints)
  /// @dev Max purchase number per txn (90+32 = 122)
  uint32 maxSalePurchasePerAddress;
  /// @dev uint64 type allows for dates into 292 billion years
  /// @notice Public sale start timestamp (136+64 = 186)
  uint64 publicSaleStart;
  /// @notice Public sale end timestamp (186+64 = 250)
  uint64 publicSaleEnd;
  /// @notice Presale start timestamp
  /// @dev new storage slot
  uint64 presaleStart;
  /// @notice Presale end timestamp
  uint64 presaleEnd;
  /// @notice Presale merkle root
  bytes32 presaleMerkleRoot;
}

File 16 of 26 : CollectionURI.sol
// SPDX-License-Identifier: UNLICENSED
/*

                         ┌───────────┐
                         │ HOLOGRAPH │
                         └───────────┘
╔═════════════════════════════════════════════════════════════╗
║                                                             ║
║                            / ^ \                            ║
║                            ~~*~~            ¸               ║
║                         [ '<>:<>' ]         │░░░            ║
║               ╔╗           _/"\_           ╔╣               ║
║             ┌─╬╬─┐          """          ┌─╬╬─┐             ║
║          ┌─┬┘ ╠╣ └┬─┐       \_/       ┌─┬┘ ╠╣ └┬─┐          ║
║       ┌─┬┘ │  ╠╣  │ └┬─┐           ┌─┬┘ │  ╠╣  │ └┬─┐       ║
║    ┌─┬┘ │  │  ╠╣  │  │ └┬─┐     ┌─┬┘ │  │  ╠╣  │  │ └┬─┐    ║
║ ┌─┬┘ │  │  │  ╠╣  │  │  │ └┬┐ ┌┬┘ │  │  │  ╠╣  │  │  │ └┬─┐ ║
╠┬┘ │  │  │  │  ╠╣  │  │  │  │└¤┘│  │  │  │  ╠╣  │  │  │  │ └┬╣
║│  │  │  │  │  ╠╣  │  │  │  │   │  │  │  │  ╠╣  │  │  │  │  │║
╠╩══╩══╩══╩══╩══╬╬══╩══╩══╩══╩═══╩══╩══╩══╩══╬╬══╩══╩══╩══╩══╩╣
╠┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╣
║               ╠╣                           ╠╣               ║
║               ╠╣                           ╠╣               ║
║    ,          ╠╣     ,        ,'      *    ╠╣               ║
║~~~~~^~~~~~~~~┌╬╬┐~~~^~~~~~~~~^^~~~~~~~~^~~┌╬╬┐~~~~~~~^~~~~~~║
╚══════════════╩╩╩╩═════════════════════════╩╩╩╩══════════════╝
     - one protocol, one bridge = infinite possibilities -


 ***************************************************************

 DISCLAIMER: U.S Patent Pending

 LICENSE: Holograph Limited Public License (H-LPL)

 https://holograph.xyz/licenses/h-lpl/1.0.0

 This license governs use of the accompanying software. If you
 use the software, you accept this license. If you do not accept
 the license, you are not permitted to use the software.

 1. Definitions

 The terms "reproduce," "reproduction," "derivative works," and
 "distribution" have the same meaning here as under U.S.
 copyright law. A "contribution" is the original software, or
 any additions or changes to the software. A "contributor" is
 any person that distributes its contribution under this
 license. "Licensed patents" are a contributor’s patent claims
 that read directly on its contribution.

 2. Grant of Rights

 A) Copyright Grant- Subject to the terms of this license,
 including the license conditions and limitations in sections 3
 and 4, each contributor grants you a non-exclusive, worldwide,
 royalty-free copyright license to reproduce its contribution,
 prepare derivative works of its contribution, and distribute
 its contribution or any derivative works that you create.
 B) Patent Grant- Subject to the terms of this license,
 including the license conditions and limitations in section 3,
 each contributor grants you a non-exclusive, worldwide,
 royalty-free license under its licensed patents to make, have
 made, use, sell, offer for sale, import, and/or otherwise
 dispose of its contribution in the software or derivative works
 of the contribution in the software.

 3. Conditions and Limitations

 A) No Trademark License- This license does not grant you rights
 to use any contributors’ name, logo, or trademarks.
 B) If you bring a patent claim against any contributor over
 patents that you claim are infringed by the software, your
 patent license from such contributor is terminated with
 immediate effect.
 C) If you distribute any portion of the software, you must
 retain all copyright, patent, trademark, and attribution
 notices that are present in the software.
 D) If you distribute any portion of the software in source code
 form, you may do so only under this license by including a
 complete copy of this license with your distribution. If you
 distribute any portion of the software in compiled or object
 code form, you may only do so under a license that complies
 with this license.
 E) The software is licensed “as-is.” You bear all risks of
 using it. The contributors give no express warranties,
 guarantees, or conditions. You may have additional consumer
 rights under your local laws which this license cannot change.
 To the extent permitted under your local laws, the contributors
 exclude all implied warranties, including those of
 merchantability, fitness for a particular purpose and
 non-infringement.

 4. (F) Platform Limitation- The licenses granted in sections
 2.A & 2.B extend only to the software or derivative works that
 you create that run on a Holograph system product.

 ***************************************************************

*/

pragma solidity 0.8.13;

interface CollectionURI {
  function contractURI() external view returns (string memory);
}

File 17 of 26 : ERC165.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.13;

interface ERC165 {
  /// @notice Query if a contract implements an interface
  /// @param interfaceID The interface identifier, as specified in ERC-165
  /// @dev Interface identification is specified in ERC-165. This function
  ///  uses less than 30,000 gas.
  /// @return `true` if the contract implements `interfaceID` and
  ///  `interfaceID` is not 0xffffffff, `false` otherwise
  function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

File 18 of 26 : ERC721.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.13;

/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  Note: the ERC-165 identifier for this interface is 0x80ac58cd.
/* is ERC165 */
interface ERC721 {
  /// @dev This emits when ownership of any NFT changes by any mechanism.
  ///  This event emits when NFTs are created (`from` == 0) and destroyed
  ///  (`to` == 0). Exception: during contract creation, any number of NFTs
  ///  may be created and assigned without emitting Transfer. At the time of
  ///  any transfer, the approved address for that NFT (if any) is reset to none.
  event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);

  /// @dev This emits when the approved address for an NFT is changed or
  ///  reaffirmed. The zero address indicates there is no approved address.
  ///  When a Transfer event emits, this also indicates that the approved
  ///  address for that NFT (if any) is reset to none.
  event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);

  /// @dev This emits when an operator is enabled or disabled for an owner.
  ///  The operator can manage all NFTs of the owner.
  event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

  /// @notice Count all NFTs assigned to an owner
  /// @dev NFTs assigned to the zero address are considered invalid, and this
  ///  function throws for queries about the zero address.
  /// @param _owner An address for whom to query the balance
  /// @return The number of NFTs owned by `_owner`, possibly zero
  function balanceOf(address _owner) external view returns (uint256);

  /// @notice Find the owner of an NFT
  /// @dev NFTs assigned to zero address are considered invalid, and queries
  ///  about them do throw.
  /// @param _tokenId The identifier for an NFT
  /// @return The address of the owner of the NFT
  function ownerOf(uint256 _tokenId) external view returns (address);

  /// @notice Transfers the ownership of an NFT from one address to another address
  /// @dev Throws unless `msg.sender` is the current owner, an authorized
  ///  operator, or the approved address for this NFT. Throws if `_from` is
  ///  not the current owner. Throws if `_to` is the zero address. Throws if
  ///  `_tokenId` is not a valid NFT. When transfer is complete, this function
  ///  checks if `_to` is a smart contract (code size > 0). If so, it calls
  ///  `onERC721Received` on `_to` and throws if the return value is not
  ///  `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
  /// @param _from The current owner of the NFT
  /// @param _to The new owner
  /// @param _tokenId The NFT to transfer
  /// @param data Additional data with no specified format, sent in call to `_to`
  function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable;

  /// @notice Transfers the ownership of an NFT from one address to another address
  /// @dev This works identically to the other function with an extra data parameter,
  ///  except this function just sets data to "".
  /// @param _from The current owner of the NFT
  /// @param _to The new owner
  /// @param _tokenId The NFT to transfer
  function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;

  /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
  ///  TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
  ///  THEY MAY BE PERMANENTLY LOST
  /// @dev Throws unless `msg.sender` is the current owner, an authorized
  ///  operator, or the approved address for this NFT. Throws if `_from` is
  ///  not the current owner. Throws if `_to` is the zero address. Throws if
  ///  `_tokenId` is not a valid NFT.
  /// @param _from The current owner of the NFT
  /// @param _to The new owner
  /// @param _tokenId The NFT to transfer
  function transferFrom(address _from, address _to, uint256 _tokenId) external payable;

  /// @notice Change or reaffirm the approved address for an NFT
  /// @dev The zero address indicates there is no approved address.
  ///  Throws unless `msg.sender` is the current NFT owner, or an authorized
  ///  operator of the current owner.
  /// @param _approved The new approved NFT controller
  /// @param _tokenId The NFT to approve
  function approve(address _approved, uint256 _tokenId) external payable;

  /// @notice Enable or disable approval for a third party ("operator") to manage
  ///  all of `msg.sender`'s assets
  /// @dev Emits the ApprovalForAll event. The contract MUST allow
  ///  multiple operators per owner.
  /// @param _operator Address to add to the set of authorized operators
  /// @param _approved True if the operator is approved, false to revoke approval
  function setApprovalForAll(address _operator, bool _approved) external;

  /// @notice Get the approved address for a single NFT
  /// @dev Throws if `_tokenId` is not a valid NFT.
  /// @param _tokenId The NFT to find the approved address for
  /// @return The approved address for this NFT, or the zero address if there is none
  function getApproved(uint256 _tokenId) external view returns (address);

  /// @notice Query if an address is an authorized operator for another address
  /// @param _owner The address that owns the NFTs
  /// @param _operator The address that acts on behalf of the owner
  /// @return True if `_operator` is an approved operator for `_owner`, false otherwise
  function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}

File 19 of 26 : ERC721Enumerable.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.13;

/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  Note: the ERC-165 identifier for this interface is 0x780e9d63.
/* is ERC721 */
interface ERC721Enumerable {
  /// @notice Count NFTs tracked by this contract
  /// @return A count of valid NFTs tracked by this contract, where each one of
  ///  them has an assigned and queryable owner not equal to the zero address
  function totalSupply() external view returns (uint256);

  /// @notice Enumerate valid NFTs
  /// @dev Throws if `_index` >= `totalSupply()`.
  /// @param _index A counter less than `totalSupply()`
  /// @return The token identifier for the `_index`th NFT,
  ///  (sort order not specified)
  function tokenByIndex(uint256 _index) external view returns (uint256);

  /// @notice Enumerate NFTs assigned to an owner
  /// @dev Throws if `_index` >= `balanceOf(_owner)` or if
  ///  `_owner` is the zero address, representing invalid NFTs.
  /// @param _owner An address where we are interested in NFTs owned by them
  /// @param _index A counter less than `balanceOf(_owner)`
  /// @return The token identifier for the `_index`th NFT assigned to `_owner`,
  ///   (sort order not specified)
  function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
}

File 20 of 26 : ERC721Metadata.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.13;

/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  Note: the ERC-165 identifier for this interface is 0x5b5e139f.
/* is ERC721 */
interface ERC721Metadata {
  /// @notice A descriptive name for a collection of NFTs in this contract
  function name() external view returns (string memory _name);

  /// @notice An abbreviated name for NFTs in this contract
  function symbol() external view returns (string memory _symbol);

  /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
  /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
  ///  3986. The URI may point to a JSON file that conforms to the "ERC721
  ///  Metadata JSON Schema".
  function tokenURI(uint256 _tokenId) external view returns (string memory);
}

File 21 of 26 : ERC721TokenReceiver.sol
// SPDX-License-Identifier: UNLICENSED
/*

                         ┌───────────┐
                         │ HOLOGRAPH │
                         └───────────┘
╔═════════════════════════════════════════════════════════════╗
║                                                             ║
║                            / ^ \                            ║
║                            ~~*~~            ¸               ║
║                         [ '<>:<>' ]         │░░░            ║
║               ╔╗           _/"\_           ╔╣               ║
║             ┌─╬╬─┐          """          ┌─╬╬─┐             ║
║          ┌─┬┘ ╠╣ └┬─┐       \_/       ┌─┬┘ ╠╣ └┬─┐          ║
║       ┌─┬┘ │  ╠╣  │ └┬─┐           ┌─┬┘ │  ╠╣  │ └┬─┐       ║
║    ┌─┬┘ │  │  ╠╣  │  │ └┬─┐     ┌─┬┘ │  │  ╠╣  │  │ └┬─┐    ║
║ ┌─┬┘ │  │  │  ╠╣  │  │  │ └┬┐ ┌┬┘ │  │  │  ╠╣  │  │  │ └┬─┐ ║
╠┬┘ │  │  │  │  ╠╣  │  │  │  │└¤┘│  │  │  │  ╠╣  │  │  │  │ └┬╣
║│  │  │  │  │  ╠╣  │  │  │  │   │  │  │  │  ╠╣  │  │  │  │  │║
╠╩══╩══╩══╩══╩══╬╬══╩══╩══╩══╩═══╩══╩══╩══╩══╬╬══╩══╩══╩══╩══╩╣
╠┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╣
║               ╠╣                           ╠╣               ║
║               ╠╣                           ╠╣               ║
║    ,          ╠╣     ,        ,'      *    ╠╣               ║
║~~~~~^~~~~~~~~┌╬╬┐~~~^~~~~~~~~^^~~~~~~~~^~~┌╬╬┐~~~~~~~^~~~~~~║
╚══════════════╩╩╩╩═════════════════════════╩╩╩╩══════════════╝
     - one protocol, one bridge = infinite possibilities -


 ***************************************************************

 DISCLAIMER: U.S Patent Pending

 LICENSE: Holograph Limited Public License (H-LPL)

 https://holograph.xyz/licenses/h-lpl/1.0.0

 This license governs use of the accompanying software. If you
 use the software, you accept this license. If you do not accept
 the license, you are not permitted to use the software.

 1. Definitions

 The terms "reproduce," "reproduction," "derivative works," and
 "distribution" have the same meaning here as under U.S.
 copyright law. A "contribution" is the original software, or
 any additions or changes to the software. A "contributor" is
 any person that distributes its contribution under this
 license. "Licensed patents" are a contributor’s patent claims
 that read directly on its contribution.

 2. Grant of Rights

 A) Copyright Grant- Subject to the terms of this license,
 including the license conditions and limitations in sections 3
 and 4, each contributor grants you a non-exclusive, worldwide,
 royalty-free copyright license to reproduce its contribution,
 prepare derivative works of its contribution, and distribute
 its contribution or any derivative works that you create.
 B) Patent Grant- Subject to the terms of this license,
 including the license conditions and limitations in section 3,
 each contributor grants you a non-exclusive, worldwide,
 royalty-free license under its licensed patents to make, have
 made, use, sell, offer for sale, import, and/or otherwise
 dispose of its contribution in the software or derivative works
 of the contribution in the software.

 3. Conditions and Limitations

 A) No Trademark License- This license does not grant you rights
 to use any contributors’ name, logo, or trademarks.
 B) If you bring a patent claim against any contributor over
 patents that you claim are infringed by the software, your
 patent license from such contributor is terminated with
 immediate effect.
 C) If you distribute any portion of the software, you must
 retain all copyright, patent, trademark, and attribution
 notices that are present in the software.
 D) If you distribute any portion of the software in source code
 form, you may do so only under this license by including a
 complete copy of this license with your distribution. If you
 distribute any portion of the software in compiled or object
 code form, you may only do so under a license that complies
 with this license.
 E) The software is licensed “as-is.” You bear all risks of
 using it. The contributors give no express warranties,
 guarantees, or conditions. You may have additional consumer
 rights under your local laws which this license cannot change.
 To the extent permitted under your local laws, the contributors
 exclude all implied warranties, including those of
 merchantability, fitness for a particular purpose and
 non-infringement.

 4. (F) Platform Limitation- The licenses granted in sections
 2.A & 2.B extend only to the software or derivative works that
 you create that run on a Holograph system product.

 ***************************************************************

*/

pragma solidity 0.8.13;

/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
interface ERC721TokenReceiver {
  /// @notice Handle the receipt of an NFT
  /// @dev The ERC721 smart contract calls this function on the recipient
  ///  after a `transfer`. This function MAY throw to revert and reject the
  ///  transfer. Return of other than the magic value MUST result in the
  ///  transaction being reverted.
  ///  Note: the contract address is always the message sender.
  /// @param _operator The address which called `safeTransferFrom` function
  /// @param _from The address which previously owned the token
  /// @param _tokenId The NFT identifier which is being transferred
  /// @param _data Additional data with no specified format
  /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
  ///  unless throwing
  function onERC721Received(
    address _operator,
    address _from,
    uint256 _tokenId,
    bytes calldata _data
  ) external returns (bytes4);
}

File 22 of 26 : Holographable.sol
// SPDX-License-Identifier: UNLICENSED
/*

                         ┌───────────┐
                         │ HOLOGRAPH │
                         └───────────┘
╔═════════════════════════════════════════════════════════════╗
║                                                             ║
║                            / ^ \                            ║
║                            ~~*~~            ¸               ║
║                         [ '<>:<>' ]         │░░░            ║
║               ╔╗           _/"\_           ╔╣               ║
║             ┌─╬╬─┐          """          ┌─╬╬─┐             ║
║          ┌─┬┘ ╠╣ └┬─┐       \_/       ┌─┬┘ ╠╣ └┬─┐          ║
║       ┌─┬┘ │  ╠╣  │ └┬─┐           ┌─┬┘ │  ╠╣  │ └┬─┐       ║
║    ┌─┬┘ │  │  ╠╣  │  │ └┬─┐     ┌─┬┘ │  │  ╠╣  │  │ └┬─┐    ║
║ ┌─┬┘ │  │  │  ╠╣  │  │  │ └┬┐ ┌┬┘ │  │  │  ╠╣  │  │  │ └┬─┐ ║
╠┬┘ │  │  │  │  ╠╣  │  │  │  │└¤┘│  │  │  │  ╠╣  │  │  │  │ └┬╣
║│  │  │  │  │  ╠╣  │  │  │  │   │  │  │  │  ╠╣  │  │  │  │  │║
╠╩══╩══╩══╩══╩══╬╬══╩══╩══╩══╩═══╩══╩══╩══╩══╬╬══╩══╩══╩══╩══╩╣
╠┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╣
║               ╠╣                           ╠╣               ║
║               ╠╣                           ╠╣               ║
║    ,          ╠╣     ,        ,'      *    ╠╣               ║
║~~~~~^~~~~~~~~┌╬╬┐~~~^~~~~~~~~^^~~~~~~~~^~~┌╬╬┐~~~~~~~^~~~~~~║
╚══════════════╩╩╩╩═════════════════════════╩╩╩╩══════════════╝
     - one protocol, one bridge = infinite possibilities -


 ***************************************************************

 DISCLAIMER: U.S Patent Pending

 LICENSE: Holograph Limited Public License (H-LPL)

 https://holograph.xyz/licenses/h-lpl/1.0.0

 This license governs use of the accompanying software. If you
 use the software, you accept this license. If you do not accept
 the license, you are not permitted to use the software.

 1. Definitions

 The terms "reproduce," "reproduction," "derivative works," and
 "distribution" have the same meaning here as under U.S.
 copyright law. A "contribution" is the original software, or
 any additions or changes to the software. A "contributor" is
 any person that distributes its contribution under this
 license. "Licensed patents" are a contributor’s patent claims
 that read directly on its contribution.

 2. Grant of Rights

 A) Copyright Grant- Subject to the terms of this license,
 including the license conditions and limitations in sections 3
 and 4, each contributor grants you a non-exclusive, worldwide,
 royalty-free copyright license to reproduce its contribution,
 prepare derivative works of its contribution, and distribute
 its contribution or any derivative works that you create.
 B) Patent Grant- Subject to the terms of this license,
 including the license conditions and limitations in section 3,
 each contributor grants you a non-exclusive, worldwide,
 royalty-free license under its licensed patents to make, have
 made, use, sell, offer for sale, import, and/or otherwise
 dispose of its contribution in the software or derivative works
 of the contribution in the software.

 3. Conditions and Limitations

 A) No Trademark License- This license does not grant you rights
 to use any contributors’ name, logo, or trademarks.
 B) If you bring a patent claim against any contributor over
 patents that you claim are infringed by the software, your
 patent license from such contributor is terminated with
 immediate effect.
 C) If you distribute any portion of the software, you must
 retain all copyright, patent, trademark, and attribution
 notices that are present in the software.
 D) If you distribute any portion of the software in source code
 form, you may do so only under this license by including a
 complete copy of this license with your distribution. If you
 distribute any portion of the software in compiled or object
 code form, you may only do so under a license that complies
 with this license.
 E) The software is licensed “as-is.” You bear all risks of
 using it. The contributors give no express warranties,
 guarantees, or conditions. You may have additional consumer
 rights under your local laws which this license cannot change.
 To the extent permitted under your local laws, the contributors
 exclude all implied warranties, including those of
 merchantability, fitness for a particular purpose and
 non-infringement.

 4. (F) Platform Limitation- The licenses granted in sections
 2.A & 2.B extend only to the software or derivative works that
 you create that run on a Holograph system product.

 ***************************************************************

*/

pragma solidity 0.8.13;

interface Holographable {
  function bridgeIn(uint32 fromChain, bytes calldata payload) external returns (bytes4);

  function bridgeOut(
    uint32 toChain,
    address sender,
    bytes calldata payload
  ) external returns (bytes4 selector, bytes memory data);
}

File 23 of 26 : HolographERC721Interface.sol
// SPDX-License-Identifier: UNLICENSED
/*

                         ┌───────────┐
                         │ HOLOGRAPH │
                         └───────────┘
╔═════════════════════════════════════════════════════════════╗
║                                                             ║
║                            / ^ \                            ║
║                            ~~*~~            ¸               ║
║                         [ '<>:<>' ]         │░░░            ║
║               ╔╗           _/"\_           ╔╣               ║
║             ┌─╬╬─┐          """          ┌─╬╬─┐             ║
║          ┌─┬┘ ╠╣ └┬─┐       \_/       ┌─┬┘ ╠╣ └┬─┐          ║
║       ┌─┬┘ │  ╠╣  │ └┬─┐           ┌─┬┘ │  ╠╣  │ └┬─┐       ║
║    ┌─┬┘ │  │  ╠╣  │  │ └┬─┐     ┌─┬┘ │  │  ╠╣  │  │ └┬─┐    ║
║ ┌─┬┘ │  │  │  ╠╣  │  │  │ └┬┐ ┌┬┘ │  │  │  ╠╣  │  │  │ └┬─┐ ║
╠┬┘ │  │  │  │  ╠╣  │  │  │  │└¤┘│  │  │  │  ╠╣  │  │  │  │ └┬╣
║│  │  │  │  │  ╠╣  │  │  │  │   │  │  │  │  ╠╣  │  │  │  │  │║
╠╩══╩══╩══╩══╩══╬╬══╩══╩══╩══╩═══╩══╩══╩══╩══╬╬══╩══╩══╩══╩══╩╣
╠┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╣
║               ╠╣                           ╠╣               ║
║               ╠╣                           ╠╣               ║
║    ,          ╠╣     ,        ,'      *    ╠╣               ║
║~~~~~^~~~~~~~~┌╬╬┐~~~^~~~~~~~~^^~~~~~~~~^~~┌╬╬┐~~~~~~~^~~~~~~║
╚══════════════╩╩╩╩═════════════════════════╩╩╩╩══════════════╝
     - one protocol, one bridge = infinite possibilities -


 ***************************************************************

 DISCLAIMER: U.S Patent Pending

 LICENSE: Holograph Limited Public License (H-LPL)

 https://holograph.xyz/licenses/h-lpl/1.0.0

 This license governs use of the accompanying software. If you
 use the software, you accept this license. If you do not accept
 the license, you are not permitted to use the software.

 1. Definitions

 The terms "reproduce," "reproduction," "derivative works," and
 "distribution" have the same meaning here as under U.S.
 copyright law. A "contribution" is the original software, or
 any additions or changes to the software. A "contributor" is
 any person that distributes its contribution under this
 license. "Licensed patents" are a contributor’s patent claims
 that read directly on its contribution.

 2. Grant of Rights

 A) Copyright Grant- Subject to the terms of this license,
 including the license conditions and limitations in sections 3
 and 4, each contributor grants you a non-exclusive, worldwide,
 royalty-free copyright license to reproduce its contribution,
 prepare derivative works of its contribution, and distribute
 its contribution or any derivative works that you create.
 B) Patent Grant- Subject to the terms of this license,
 including the license conditions and limitations in section 3,
 each contributor grants you a non-exclusive, worldwide,
 royalty-free license under its licensed patents to make, have
 made, use, sell, offer for sale, import, and/or otherwise
 dispose of its contribution in the software or derivative works
 of the contribution in the software.

 3. Conditions and Limitations

 A) No Trademark License- This license does not grant you rights
 to use any contributors’ name, logo, or trademarks.
 B) If you bring a patent claim against any contributor over
 patents that you claim are infringed by the software, your
 patent license from such contributor is terminated with
 immediate effect.
 C) If you distribute any portion of the software, you must
 retain all copyright, patent, trademark, and attribution
 notices that are present in the software.
 D) If you distribute any portion of the software in source code
 form, you may do so only under this license by including a
 complete copy of this license with your distribution. If you
 distribute any portion of the software in compiled or object
 code form, you may only do so under a license that complies
 with this license.
 E) The software is licensed “as-is.” You bear all risks of
 using it. The contributors give no express warranties,
 guarantees, or conditions. You may have additional consumer
 rights under your local laws which this license cannot change.
 To the extent permitted under your local laws, the contributors
 exclude all implied warranties, including those of
 merchantability, fitness for a particular purpose and
 non-infringement.

 4. (F) Platform Limitation- The licenses granted in sections
 2.A & 2.B extend only to the software or derivative works that
 you create that run on a Holograph system product.

 ***************************************************************

*/

pragma solidity 0.8.13;

import "./CollectionURI.sol";
import "./ERC165.sol";
import "./ERC721.sol";
import "./ERC721Enumerable.sol";
import "./ERC721Metadata.sol";
import "./ERC721TokenReceiver.sol";
import "./Holographable.sol";

interface HolographERC721Interface is
  ERC165,
  ERC721,
  ERC721Enumerable,
  ERC721Metadata,
  ERC721TokenReceiver,
  CollectionURI,
  Holographable
{
  function approve(address to, uint256 tokenId) external payable;

  function burn(uint256 tokenId) external;

  function safeTransferFrom(address from, address to, uint256 tokenId) external payable;

  function setApprovalForAll(address to, bool approved) external;

  function sourceBurn(uint256 tokenId) external;

  function sourceMint(address to, uint224 tokenId) external;

  function sourceGetChainPrepend() external view returns (uint256);

  function sourceTransfer(address to, uint256 tokenId) external;

  function transfer(address to, uint256 tokenId) external payable;

  function contractURI() external view returns (string memory);

  function getApproved(uint256 tokenId) external view returns (address);

  function isApprovedForAll(address wallet, address operator) external view returns (bool);

  function name() external view returns (string memory);

  function burned(uint256 tokenId) external view returns (bool);

  function decimals() external pure returns (uint256);

  function exists(uint256 tokenId) external view returns (bool);

  function ownerOf(uint256 tokenId) external view returns (address);

  function supportsInterface(bytes4 interfaceId) external view returns (bool);

  function symbol() external view returns (string memory);

  function tokenByIndex(uint256 index) external view returns (uint256);

  function tokenOfOwnerByIndex(address wallet, uint256 index) external view returns (uint256);

  function tokensOfOwner(address wallet) external view returns (uint256[] memory);

  function tokenURI(uint256 tokenId) external view returns (string memory);

  function totalSupply() external view returns (uint256);
}

File 24 of 26 : HolographerInterface.sol
// SPDX-License-Identifier: UNLICENSED
/*

                         ┌───────────┐
                         │ HOLOGRAPH │
                         └───────────┘
╔═════════════════════════════════════════════════════════════╗
║                                                             ║
║                            / ^ \                            ║
║                            ~~*~~            ¸               ║
║                         [ '<>:<>' ]         │░░░            ║
║               ╔╗           _/"\_           ╔╣               ║
║             ┌─╬╬─┐          """          ┌─╬╬─┐             ║
║          ┌─┬┘ ╠╣ └┬─┐       \_/       ┌─┬┘ ╠╣ └┬─┐          ║
║       ┌─┬┘ │  ╠╣  │ └┬─┐           ┌─┬┘ │  ╠╣  │ └┬─┐       ║
║    ┌─┬┘ │  │  ╠╣  │  │ └┬─┐     ┌─┬┘ │  │  ╠╣  │  │ └┬─┐    ║
║ ┌─┬┘ │  │  │  ╠╣  │  │  │ └┬┐ ┌┬┘ │  │  │  ╠╣  │  │  │ └┬─┐ ║
╠┬┘ │  │  │  │  ╠╣  │  │  │  │└¤┘│  │  │  │  ╠╣  │  │  │  │ └┬╣
║│  │  │  │  │  ╠╣  │  │  │  │   │  │  │  │  ╠╣  │  │  │  │  │║
╠╩══╩══╩══╩══╩══╬╬══╩══╩══╩══╩═══╩══╩══╩══╩══╬╬══╩══╩══╩══╩══╩╣
╠┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╣
║               ╠╣                           ╠╣               ║
║               ╠╣                           ╠╣               ║
║    ,          ╠╣     ,        ,'      *    ╠╣               ║
║~~~~~^~~~~~~~~┌╬╬┐~~~^~~~~~~~~^^~~~~~~~~^~~┌╬╬┐~~~~~~~^~~~~~~║
╚══════════════╩╩╩╩═════════════════════════╩╩╩╩══════════════╝
     - one protocol, one bridge = infinite possibilities -


 ***************************************************************

 DISCLAIMER: U.S Patent Pending

 LICENSE: Holograph Limited Public License (H-LPL)

 https://holograph.xyz/licenses/h-lpl/1.0.0

 This license governs use of the accompanying software. If you
 use the software, you accept this license. If you do not accept
 the license, you are not permitted to use the software.

 1. Definitions

 The terms "reproduce," "reproduction," "derivative works," and
 "distribution" have the same meaning here as under U.S.
 copyright law. A "contribution" is the original software, or
 any additions or changes to the software. A "contributor" is
 any person that distributes its contribution under this
 license. "Licensed patents" are a contributor’s patent claims
 that read directly on its contribution.

 2. Grant of Rights

 A) Copyright Grant- Subject to the terms of this license,
 including the license conditions and limitations in sections 3
 and 4, each contributor grants you a non-exclusive, worldwide,
 royalty-free copyright license to reproduce its contribution,
 prepare derivative works of its contribution, and distribute
 its contribution or any derivative works that you create.
 B) Patent Grant- Subject to the terms of this license,
 including the license conditions and limitations in section 3,
 each contributor grants you a non-exclusive, worldwide,
 royalty-free license under its licensed patents to make, have
 made, use, sell, offer for sale, import, and/or otherwise
 dispose of its contribution in the software or derivative works
 of the contribution in the software.

 3. Conditions and Limitations

 A) No Trademark License- This license does not grant you rights
 to use any contributors’ name, logo, or trademarks.
 B) If you bring a patent claim against any contributor over
 patents that you claim are infringed by the software, your
 patent license from such contributor is terminated with
 immediate effect.
 C) If you distribute any portion of the software, you must
 retain all copyright, patent, trademark, and attribution
 notices that are present in the software.
 D) If you distribute any portion of the software in source code
 form, you may do so only under this license by including a
 complete copy of this license with your distribution. If you
 distribute any portion of the software in compiled or object
 code form, you may only do so under a license that complies
 with this license.
 E) The software is licensed “as-is.” You bear all risks of
 using it. The contributors give no express warranties,
 guarantees, or conditions. You may have additional consumer
 rights under your local laws which this license cannot change.
 To the extent permitted under your local laws, the contributors
 exclude all implied warranties, including those of
 merchantability, fitness for a particular purpose and
 non-infringement.

 4. (F) Platform Limitation- The licenses granted in sections
 2.A & 2.B extend only to the software or derivative works that
 you create that run on a Holograph system product.

 ***************************************************************

*/

pragma solidity 0.8.13;

interface HolographerInterface {
  function getContractType() external view returns (bytes32 contractType);

  function getDeploymentBlock() external view returns (uint256 deploymentBlock);

  function getHolograph() external view returns (address holograph);

  function getHolographEnforcer() external view returns (address);

  function getOriginChain() external view returns (uint32 originChain);

  function getSourceContract() external view returns (address sourceContract);
}

File 25 of 26 : HolographInterface.sol
// SPDX-License-Identifier: UNLICENSED
/*

                         ┌───────────┐
                         │ HOLOGRAPH │
                         └───────────┘
╔═════════════════════════════════════════════════════════════╗
║                                                             ║
║                            / ^ \                            ║
║                            ~~*~~            ¸               ║
║                         [ '<>:<>' ]         │░░░            ║
║               ╔╗           _/"\_           ╔╣               ║
║             ┌─╬╬─┐          """          ┌─╬╬─┐             ║
║          ┌─┬┘ ╠╣ └┬─┐       \_/       ┌─┬┘ ╠╣ └┬─┐          ║
║       ┌─┬┘ │  ╠╣  │ └┬─┐           ┌─┬┘ │  ╠╣  │ └┬─┐       ║
║    ┌─┬┘ │  │  ╠╣  │  │ └┬─┐     ┌─┬┘ │  │  ╠╣  │  │ └┬─┐    ║
║ ┌─┬┘ │  │  │  ╠╣  │  │  │ └┬┐ ┌┬┘ │  │  │  ╠╣  │  │  │ └┬─┐ ║
╠┬┘ │  │  │  │  ╠╣  │  │  │  │└¤┘│  │  │  │  ╠╣  │  │  │  │ └┬╣
║│  │  │  │  │  ╠╣  │  │  │  │   │  │  │  │  ╠╣  │  │  │  │  │║
╠╩══╩══╩══╩══╩══╬╬══╩══╩══╩══╩═══╩══╩══╩══╩══╬╬══╩══╩══╩══╩══╩╣
╠┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╣
║               ╠╣                           ╠╣               ║
║               ╠╣                           ╠╣               ║
║    ,          ╠╣     ,        ,'      *    ╠╣               ║
║~~~~~^~~~~~~~~┌╬╬┐~~~^~~~~~~~~^^~~~~~~~~^~~┌╬╬┐~~~~~~~^~~~~~~║
╚══════════════╩╩╩╩═════════════════════════╩╩╩╩══════════════╝
     - one protocol, one bridge = infinite possibilities -


 ***************************************************************

 DISCLAIMER: U.S Patent Pending

 LICENSE: Holograph Limited Public License (H-LPL)

 https://holograph.xyz/licenses/h-lpl/1.0.0

 This license governs use of the accompanying software. If you
 use the software, you accept this license. If you do not accept
 the license, you are not permitted to use the software.

 1. Definitions

 The terms "reproduce," "reproduction," "derivative works," and
 "distribution" have the same meaning here as under U.S.
 copyright law. A "contribution" is the original software, or
 any additions or changes to the software. A "contributor" is
 any person that distributes its contribution under this
 license. "Licensed patents" are a contributor’s patent claims
 that read directly on its contribution.

 2. Grant of Rights

 A) Copyright Grant- Subject to the terms of this license,
 including the license conditions and limitations in sections 3
 and 4, each contributor grants you a non-exclusive, worldwide,
 royalty-free copyright license to reproduce its contribution,
 prepare derivative works of its contribution, and distribute
 its contribution or any derivative works that you create.
 B) Patent Grant- Subject to the terms of this license,
 including the license conditions and limitations in section 3,
 each contributor grants you a non-exclusive, worldwide,
 royalty-free license under its licensed patents to make, have
 made, use, sell, offer for sale, import, and/or otherwise
 dispose of its contribution in the software or derivative works
 of the contribution in the software.

 3. Conditions and Limitations

 A) No Trademark License- This license does not grant you rights
 to use any contributors’ name, logo, or trademarks.
 B) If you bring a patent claim against any contributor over
 patents that you claim are infringed by the software, your
 patent license from such contributor is terminated with
 immediate effect.
 C) If you distribute any portion of the software, you must
 retain all copyright, patent, trademark, and attribution
 notices that are present in the software.
 D) If you distribute any portion of the software in source code
 form, you may do so only under this license by including a
 complete copy of this license with your distribution. If you
 distribute any portion of the software in compiled or object
 code form, you may only do so under a license that complies
 with this license.
 E) The software is licensed “as-is.” You bear all risks of
 using it. The contributors give no express warranties,
 guarantees, or conditions. You may have additional consumer
 rights under your local laws which this license cannot change.
 To the extent permitted under your local laws, the contributors
 exclude all implied warranties, including those of
 merchantability, fitness for a particular purpose and
 non-infringement.

 4. (F) Platform Limitation- The licenses granted in sections
 2.A & 2.B extend only to the software or derivative works that
 you create that run on a Holograph system product.

 ***************************************************************

*/

pragma solidity 0.8.13;

/**
 * @title Holograph Protocol
 * @author https://github.com/holographxyz
 * @notice This is the primary Holograph Protocol smart contract
 * @dev This contract stores a reference to all the primary modules and variables of the protocol
 */
interface HolographInterface {
  /**
   * @notice Get the address of the Holograph Bridge module
   * @dev Used for beaming holographable assets cross-chain
   */
  function getBridge() external view returns (address bridge);

  /**
   * @notice Update the Holograph Bridge module address
   * @param bridge address of the Holograph Bridge smart contract to use
   */
  function setBridge(address bridge) external;

  /**
   * @notice Get the chain ID that the Protocol was deployed on
   * @dev Useful for checking if/when a hard fork occurs
   */
  function getChainId() external view returns (uint256 chainId);

  /**
   * @notice Update the chain ID
   * @dev Useful for updating once a hard fork has been mitigated
   * @param chainId EVM chain ID to use
   */
  function setChainId(uint256 chainId) external;

  /**
   * @notice Get the address of the Holograph Factory module
   * @dev Used for deploying holographable smart contracts
   */
  function getFactory() external view returns (address factory);

  /**
   * @notice Update the Holograph Factory module address
   * @param factory address of the Holograph Factory smart contract to use
   */
  function setFactory(address factory) external;

  /**
   * @notice Get the Holograph chain Id
   * @dev Holograph uses an internal chain id mapping
   */
  function getHolographChainId() external view returns (uint32 holographChainId);

  /**
   * @notice Update the Holograph chain ID
   * @dev Useful for updating once a hard fork was mitigated
   * @param holographChainId Holograph chain ID to use
   */
  function setHolographChainId(uint32 holographChainId) external;

  /**
   * @notice Get the address of the Holograph Interfaces module
   * @dev Holograph uses this contract to store data that needs to be accessed by a large portion of the modules
   */
  function getInterfaces() external view returns (address interfaces);

  /**
   * @notice Update the Holograph Interfaces module address
   * @param interfaces address of the Holograph Interfaces smart contract to use
   */
  function setInterfaces(address interfaces) external;

  /**
   * @notice Get the address of the Holograph Operator module
   * @dev All cross-chain Holograph Bridge beams are handled by the Holograph Operator module
   */
  function getOperator() external view returns (address operator);

  /**
   * @notice Update the Holograph Operator module address
   * @param operator address of the Holograph Operator smart contract to use
   */
  function setOperator(address operator) external;

  /**
   * @notice Get the Holograph Registry module
   * @dev This module stores a reference for all deployed holographable smart contracts
   */
  function getRegistry() external view returns (address registry);

  /**
   * @notice Update the Holograph Registry module address
   * @param registry address of the Holograph Registry smart contract to use
   */
  function setRegistry(address registry) external;

  /**
   * @notice Get the Holograph Treasury module
   * @dev All of the Holograph Protocol assets are stored and managed by this module
   */
  function getTreasury() external view returns (address treasury);

  /**
   * @notice Update the Holograph Treasury module address
   * @param treasury address of the Holograph Treasury smart contract to use
   */
  function setTreasury(address treasury) external;

  /**
   * @notice Get the Holograph Utility Token address
   * @dev This is the official utility token of the Holograph Protocol
   */
  function getUtilityToken() external view returns (address utilityToken);

  /**
   * @notice Update the Holograph Utility Token address
   * @param utilityToken address of the Holograph Utility Token smart contract to use
   */
  function setUtilityToken(address utilityToken) external;
}

File 26 of 26 : InitializableInterface.sol
// SPDX-License-Identifier: UNLICENSED
/*

                         ┌───────────┐
                         │ HOLOGRAPH │
                         └───────────┘
╔═════════════════════════════════════════════════════════════╗
║                                                             ║
║                            / ^ \                            ║
║                            ~~*~~            ¸               ║
║                         [ '<>:<>' ]         │░░░            ║
║               ╔╗           _/"\_           ╔╣               ║
║             ┌─╬╬─┐          """          ┌─╬╬─┐             ║
║          ┌─┬┘ ╠╣ └┬─┐       \_/       ┌─┬┘ ╠╣ └┬─┐          ║
║       ┌─┬┘ │  ╠╣  │ └┬─┐           ┌─┬┘ │  ╠╣  │ └┬─┐       ║
║    ┌─┬┘ │  │  ╠╣  │  │ └┬─┐     ┌─┬┘ │  │  ╠╣  │  │ └┬─┐    ║
║ ┌─┬┘ │  │  │  ╠╣  │  │  │ └┬┐ ┌┬┘ │  │  │  ╠╣  │  │  │ └┬─┐ ║
╠┬┘ │  │  │  │  ╠╣  │  │  │  │└¤┘│  │  │  │  ╠╣  │  │  │  │ └┬╣
║│  │  │  │  │  ╠╣  │  │  │  │   │  │  │  │  ╠╣  │  │  │  │  │║
╠╩══╩══╩══╩══╩══╬╬══╩══╩══╩══╩═══╩══╩══╩══╩══╬╬══╩══╩══╩══╩══╩╣
╠┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╬╬┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╣
║               ╠╣                           ╠╣               ║
║               ╠╣                           ╠╣               ║
║    ,          ╠╣     ,        ,'      *    ╠╣               ║
║~~~~~^~~~~~~~~┌╬╬┐~~~^~~~~~~~~^^~~~~~~~~^~~┌╬╬┐~~~~~~~^~~~~~~║
╚══════════════╩╩╩╩═════════════════════════╩╩╩╩══════════════╝
     - one protocol, one bridge = infinite possibilities -


 ***************************************************************

 DISCLAIMER: U.S Patent Pending

 LICENSE: Holograph Limited Public License (H-LPL)

 https://holograph.xyz/licenses/h-lpl/1.0.0

 This license governs use of the accompanying software. If you
 use the software, you accept this license. If you do not accept
 the license, you are not permitted to use the software.

 1. Definitions

 The terms "reproduce," "reproduction," "derivative works," and
 "distribution" have the same meaning here as under U.S.
 copyright law. A "contribution" is the original software, or
 any additions or changes to the software. A "contributor" is
 any person that distributes its contribution under this
 license. "Licensed patents" are a contributor’s patent claims
 that read directly on its contribution.

 2. Grant of Rights

 A) Copyright Grant- Subject to the terms of this license,
 including the license conditions and limitations in sections 3
 and 4, each contributor grants you a non-exclusive, worldwide,
 royalty-free copyright license to reproduce its contribution,
 prepare derivative works of its contribution, and distribute
 its contribution or any derivative works that you create.
 B) Patent Grant- Subject to the terms of this license,
 including the license conditions and limitations in section 3,
 each contributor grants you a non-exclusive, worldwide,
 royalty-free license under its licensed patents to make, have
 made, use, sell, offer for sale, import, and/or otherwise
 dispose of its contribution in the software or derivative works
 of the contribution in the software.

 3. Conditions and Limitations

 A) No Trademark License- This license does not grant you rights
 to use any contributors’ name, logo, or trademarks.
 B) If you bring a patent claim against any contributor over
 patents that you claim are infringed by the software, your
 patent license from such contributor is terminated with
 immediate effect.
 C) If you distribute any portion of the software, you must
 retain all copyright, patent, trademark, and attribution
 notices that are present in the software.
 D) If you distribute any portion of the software in source code
 form, you may do so only under this license by including a
 complete copy of this license with your distribution. If you
 distribute any portion of the software in compiled or object
 code form, you may only do so under a license that complies
 with this license.
 E) The software is licensed “as-is.” You bear all risks of
 using it. The contributors give no express warranties,
 guarantees, or conditions. You may have additional consumer
 rights under your local laws which this license cannot change.
 To the extent permitted under your local laws, the contributors
 exclude all implied warranties, including those of
 merchantability, fitness for a particular purpose and
 non-infringement.

 4. (F) Platform Limitation- The licenses granted in sections
 2.A & 2.B extend only to the software or derivative works that
 you create that run on a Holograph system product.

 ***************************************************************

*/

pragma solidity 0.8.13;

/**
 * @title Initializable
 * @author https://github.com/holographxyz
 * @notice Use init instead of constructor
 * @dev This allows for use of init function to make one time initializations without the need of a constructor
 */
interface InitializableInterface {
  /**
   * @notice Used internally to initialize the contract instead of through a constructor
   * @dev This function is called by the deployer/factory when creating a contract
   * @param initPayload abi encoded payload to use for contract initilaization
   */
  function init(bytes memory initPayload) external returns (bytes4);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 999999
  },
  "metadata": {
    "bytecodeHash": "none",
    "useLiteralContent": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc721a-upgradeable/=erc721a-upgradeable/",
    "forge-std/=lib/forge-std/src/"
  ],
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"Access_MissingRoleOrAdmin","type":"error"},{"inputs":[],"name":"Access_OnlyAdmin","type":"error"},{"inputs":[],"name":"Access_WithdrawNotAllowed","type":"error"},{"inputs":[{"internalType":"address","name":"proposedAddress","type":"address"}],"name":"Admin_InvalidUpgradeAddress","type":"error"},{"inputs":[],"name":"Admin_UnableToFinalizeNotOpenEdition","type":"error"},{"inputs":[],"name":"ExternalMetadataRenderer_CallFailed","type":"error"},{"inputs":[],"name":"MarketFilterAddressNotSupportedForChain","type":"error"},{"inputs":[],"name":"MarketFilterDAOAddressNotSupportedForChain","type":"error"},{"inputs":[],"name":"MintFee_FundsSendFailure","type":"error"},{"inputs":[],"name":"Mint_SoldOut","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[],"name":"Presale_Inactive","type":"error"},{"inputs":[],"name":"Presale_MerkleNotApproved","type":"error"},{"inputs":[],"name":"Presale_TooManyForAddress","type":"error"},{"inputs":[],"name":"Purchase_TooManyForAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"correctPrice","type":"uint256"}],"name":"Purchase_WrongPrice","type":"error"},{"inputs":[],"name":"RemoteOperatorFilterRegistryCallFailed","type":"error"},{"inputs":[],"name":"Sale_Inactive","type":"error"},{"inputs":[{"internalType":"uint16","name":"maxRoyaltyBPS","type":"uint16"}],"name":"Setup_RoyaltyPercentageTooHigh","type":"error"},{"inputs":[],"name":"Withdraw_FundsSendFailure","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"source","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FundsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newAddress","type":"address"},{"indexed":true,"internalType":"address","name":"changedBy","type":"address"}],"name":"FundsRecipientChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"withdrawnBy","type":"address"},{"indexed":true,"internalType":"address","name":"withdrawnTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"feeRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"mintFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"mintFeeRecipient","type":"address"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"MintFeePayout","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"numberOfMints","type":"uint256"}],"name":"OpenMintFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"pricePerToken","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"firstPurchasedTokenId","type":"uint256"}],"name":"Sale","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"changedBy","type":"address"}],"name":"SalesConfigChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"contract IMetadataRenderer","name":"renderer","type":"address"}],"name":"UpdatedMetadataRenderer","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"adminMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"}],"name":"adminMintAirdrop","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"beforeSafeTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"beforeTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"config","outputs":[{"internalType":"contract IMetadataRenderer","name":"metadataRenderer","type":"address"},{"internalType":"uint64","name":"editionSize","type":"uint64"},{"internalType":"uint16","name":"royaltyBPS","type":"uint16"},{"internalType":"address payable","name":"fundsRecipient","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dropsPriceOracle","outputs":[{"internalType":"contract IDropsPriceOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc721TransferHelper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finalizeOpenEdition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"initPayload","type":"bytes"}],"name":"init","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"enable","type":"bool"}],"name":"manageMarketFilterSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"marketFilterAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataRenderer","outputs":[{"internalType":"contract IMetadataRenderer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"mintedPerAddress","outputs":[{"components":[{"internalType":"uint256","name":"totalMints","type":"uint256"},{"internalType":"uint256","name":"presaleMints","type":"uint256"},{"internalType":"uint256","name":"publicMints","type":"uint256"}],"internalType":"struct AddressMintDetails","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newMarketFilterAddress","type":"address"}],"name":"modifyMarketFilterAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"onIsApprovedForAll","outputs":[{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openseaOperatorFilterRegistry","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"presaleMintsByAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"purchase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"pricePerToken","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"purchasePresale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"saleDetails","outputs":[{"components":[{"internalType":"bool","name":"publicSaleActive","type":"bool"},{"internalType":"bool","name":"presaleActive","type":"bool"},{"internalType":"uint256","name":"publicSalePrice","type":"uint256"},{"internalType":"uint64","name":"publicSaleStart","type":"uint64"},{"internalType":"uint64","name":"publicSaleEnd","type":"uint64"},{"internalType":"uint64","name":"presaleStart","type":"uint64"},{"internalType":"uint64","name":"presaleEnd","type":"uint64"},{"internalType":"bytes32","name":"presaleMerkleRoot","type":"bytes32"},{"internalType":"uint256","name":"maxSalePurchasePerAddress","type":"uint256"},{"internalType":"uint256","name":"totalMinted","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"}],"internalType":"struct SaleDetails","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"salesConfig","outputs":[{"internalType":"uint104","name":"publicSalePrice","type":"uint104"},{"internalType":"uint32","name":"maxSalePurchasePerAddress","type":"uint32"},{"internalType":"uint64","name":"publicSaleStart","type":"uint64"},{"internalType":"uint64","name":"publicSaleEnd","type":"uint64"},{"internalType":"uint64","name":"presaleStart","type":"uint64"},{"internalType":"uint64","name":"presaleEnd","type":"uint64"},{"internalType":"bytes32","name":"presaleMerkleRoot","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"newRecipientAddress","type":"address"}],"name":"setFundsRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IMetadataRenderer","name":"newRenderer","type":"address"},{"internalType":"bytes","name":"setupRenderer","type":"bytes"}],"name":"setMetadataRenderer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint104","name":"publicSalePrice","type":"uint104"},{"internalType":"uint32","name":"maxSalePurchasePerAddress","type":"uint32"},{"internalType":"uint64","name":"publicSaleStart","type":"uint64"},{"internalType":"uint64","name":"publicSaleEnd","type":"uint64"},{"internalType":"uint64","name":"presaleStart","type":"uint64"},{"internalType":"uint64","name":"presaleEnd","type":"uint64"},{"internalType":"bytes32","name":"presaleMerkleRoot","type":"bytes32"}],"name":"setSaleConfiguration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalMintsByAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"args","type":"bytes"}],"name":"updateMarketFilterSettings","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234801561001057600080fd5b50615efd80620000216000396000f3fe6080604052600436106102895760003560e01c806361fea76811610153578063ac9650d8116100cb578063e58306f91161007f578063efef39a111610064578063efef39a1146109e6578063f7cd1d9b146109f9578063ffdb716314610a2657610303565b8063e58306f9146109b1578063e8a3d485146109d157610303565b8063bb20d857116100b0578063bb20d8571461092f578063c87b56dd1461094f578063d445b9781461096f57610303565b8063ac9650d8146108e2578063b8ae5a2c1461090f57610303565b80638a1968de116101225780638da5cb5b116101075780638da5cb5b1461088b5780638f32d59b146108a05780639123f01e146108b557610303565b80638a1968de146108435780638cb163f41461086357610303565b806361fea76814610702578063703199701461072f57806379502c551461075a57806384816f2a1461082357610303565b80632ca16676116102015780633bcdcc87116101b557806341e96eb11161019a57806341e96eb1146106565780634ddf47d41461066b57806354fd4d50146106bc57610303565b80633bcdcc87146106215780633ccfd60b1461064157610303565b80632f54bf6e116101e65780632f54bf6e146105df578063343b278f146105925780633474a4a6146105ff57610303565b80632ca16676146105925780632f0ae5fa146105b257610303565b806317430c9e116102585780632078d35f1161023d5780632078d35f1461051857806324d7806c1461055f57806325024a2b1461057f57610303565b806317430c9e146104095780631d2c0b381461042c57610303565b8063015eaa7a1461032e57806301ffc9a71461036357806306fdde03146103c557806310a7eb5d146103e757610303565b3661030357367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff167f8e47b87b0ef542cdfa1659c551d88bad38aa7f452d2bbb349ab7530dfec8be8f346040516102f991815260200190565b60405180910390a2005b6040517f46756e6374696f6e206e6f7420666f756e6400000000000000000000000000008152601481fd5b34801561033a57600080fd5b5061034e61034936600461522b565b610a46565b60405190151581526020015b60405180910390f35b34801561036f57600080fd5b5061034e61037e366004615264565b7fffffffff00000000000000000000000000000000000000000000000000000000167f1a95c452000000000000000000000000000000000000000000000000000000001490565b3480156103d157600080fd5b506103da610a91565b60405161035a9190615320565b3480156103f357600080fd5b50610407610402366004615333565b610b50565b005b34801561041557600080fd5b5061041e610e8a565b60405190815260200161035a565b34801561043857600080fd5b506005546006546007546104bf926cffffffffffffffffffffffffff8116926d0100000000000000000000000000820463ffffffff16927101000000000000000000000000000000000090920467ffffffffffffffff9081169281831692680100000000000000008104831692700100000000000000000000000000000000909104169087565b604080516cffffffffffffffffffffffffff909816885263ffffffff909616602088015267ffffffffffffffff948516958701959095529183166060860152821660808501521660a083015260c082015260e00161035a565b34801561052457600080fd5b5061053a6daaeb6d7670e522a718067333cd4e81565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161035a565b34801561056b57600080fd5b5061034e61057a366004615333565b610ea8565b61041e61058d36600461539c565b610f06565b34801561059e57600080fd5b5061034e6105ad36600461543f565b611550565b3480156105be57600080fd5b5060025461053a9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156105eb57600080fd5b5061034e6105fa366004615333565b61175e565b34801561060b57600080fd5b506106146117bd565b60405161035a91906154a1565b34801561062d57600080fd5b5061040761063c3660046156b0565b611928565b34801561064d57600080fd5b50610407611c3e565b34801561066257600080fd5b5061040761216c565b34801561067757600080fd5b5061068b610686366004615700565b61248e565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161035a565b3480156106c857600080fd5b5060408051808201909152600581527f312e302e3000000000000000000000000000000000000000000000000000000060208201526103da565b34801561070e57600080fd5b5061041e61071d366004615333565b60086020526000908152604090205481565b34801561073b57600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff1661053a565b34801561076657600080fd5b506003546004546107d69173ffffffffffffffffffffffffffffffffffffffff8082169274010000000000000000000000000000000000000000830467ffffffffffffffff16927c0100000000000000000000000000000000000000000000000000000000900461ffff16911684565b6040805173ffffffffffffffffffffffffffffffffffffffff958616815267ffffffffffffffff909416602085015261ffff9092169183019190915291909116606082015260800161035a565b34801561082f57600080fd5b5061040761083e366004615333565b612aa3565b34801561084f57600080fd5b5061040761085e366004615743565b612cbc565b34801561086f57600080fd5b5061053a73a3db09eec42baff7a50fb8f9af90a0e035ef330281565b34801561089757600080fd5b5061053a613271565b3480156108ac57600080fd5b5061034e61329b565b3480156108c157600080fd5b5061041e6108d0366004615333565b60096020526000908152604090205481565b3480156108ee57600080fd5b506109026108fd366004615760565b613397565b60405161035a9190615823565b34801561091b57600080fd5b5061041e61092a3660046158a3565b613498565b34801561093b57600080fd5b506103da61094a3660046158e5565b61379b565b34801561095b57600080fd5b506103da61096a36600461591b565b613ae1565b34801561097b57600080fd5b5061098f61098a366004615333565b613cba565b604080518251815260208084015190820152918101519082015260600161035a565b3480156109bd57600080fd5b5061041e6109cc366004615934565b613d3f565b3480156109dd57600080fd5b506103da614007565b61041e6109f436600461591b565b614077565b348015610a0557600080fd5b5060015461053a9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610a3257600080fd5b50610407610a413660046159a3565b6145d0565b60015460009073ffffffffffffffffffffffffffffffffffffffff1615801590610a8a575060015473ffffffffffffffffffffffffffffffffffffffff8381169116145b9392505050565b6060610abb7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b73ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015610b05573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b4b9190810190615a60565b905090565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5473ffffffffffffffffffffffffffffffffffffffff163303610c71577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614610c6c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e000000000060448201526064015b60405180910390fd5b610d27565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b73ffffffffffffffffffffffffffffffffffffffff8116610dca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f46756e647320526563697069656e742063616e6e6f742062652030206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610c63565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8316179055367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f70a7ea5c664ab9c21baf3da59bb2f1e1ca33557b08a0031fab4f17076744995160405160405180910390a350565b600554600090610b4b906cffffffffffffffffffffffffff1661492f565b60008173ffffffffffffffffffffffffffffffffffffffff16610ee97fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775490565b73ffffffffffffffffffffffffffffffffffffffff161492915050565b6000610f307f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a31372795490565b600203610f99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f484f4c4f47524150483a207265656e7472616e742063616c6c000000000000006044820152606401610c63565b610fc260027f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b600354869074010000000000000000000000000000000000000000900467ffffffffffffffff161580159061104657506003546000547401000000000000000000000000000000000000000090910467ffffffffffffffff1690611044907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683615ad8565b115b1561107d576040517f717c513000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110856149d4565b6110bb576040517f95ed3c1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61116484848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050600754915050367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001356040805173ffffffffffffffffffffffffffffffffffffffff909216602083015281018a90526060810189905260800160405160208183030381529060405280519060200120614a23565b61119a576040517f85b70e5200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006111a58661492f565b90506111b18882615af0565b3410156111f7576111c28887615af0565b6040517f6a1c179e000000000000000000000000000000000000000000000000000000008152600401610c6391815260200190565b60006112038983615af0565b61120d9034615b2d565b73ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe036013516600090815260086020526040812080549293508b9290919061126a908490615ad8565b909155505073ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0360135166000908152600860205260409020548810156112f1576040517fa7b32bb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61131e367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001358a614a39565b60006113487fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b905060008173ffffffffffffffffffffffffffffffffffffffff166377dbd8636040518163ffffffff1660e01b8152600401602060405180830381865afa158015611397573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bb9190615b44565b60008054919250906113ec908d907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16615b2d565b6113f69083615ad8565b611401906001615ad8565b9050848c367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff167f4e26b0356a15833a75d497ecc40ebbb716b99466ed0dba9454f1fff451e25a908460405161147091815260200190565b60405180910390a4831561151757367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1684620334505a116114c9575a6114ce565b620334505b6040519091906000818181858888f193505050503d806000811461150e576040519150601f19603f3d011682016040523d82523d6000602084013e611513565b606091505b5050505b9550505050505061154760017f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b95945050505050565b600073ffffffffffffffffffffffffffffffffffffffff8616158015906115c65750367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614155b15611752577f5c835f3b6bd322d9a084ffdeac746df2b96cce308e7f0612f4ff4f9c490734cc548015611750576daaeb6d7670e522a718067333cd4e63c617113430367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001356040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa9250505080156116d6575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526116d391810190615b68565b60015b611747576040517fede71dcc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0360135166004820152602401610c63565b91506115479050565b505b50600195945050505050565b60006117887fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775490565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915260405180610160016040528061182a614e10565b151581526020016118396149d4565b151581526005546cffffffffffffffffffffffffff8116602083015271010000000000000000000000000000000000810467ffffffffffffffff90811660408401526006548082166060850152680100000000000000008104821660808501527001000000000000000000000000000000009004811660a084015260075460c08401526d010000000000000000000000000090910463ffffffff1660e08301526000547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166101008301526003547401000000000000000000000000000000000000000090041661012090910152919050565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5473ffffffffffffffffffffffffffffffffffffffff163303611a44577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614611a3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b611afa565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611afa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055805115611bc6576040517f856a7ffa00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063856a7ffa90611b93908490600401615320565b600060405180830381600087803b158015611bad57600080fd5b505af1158015611bc1573d6000803e3d6000fd5b505050505b7f046c5d913c35948c3e0e44c3599eb14bf33b73f141fa8bb282b300414998b868367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001356040805173ffffffffffffffffffffffffffffffffffffffff928316815291851660208301520160405180910390a15050565b7f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727954600203611cc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f484f4c4f47524150483a207265656e7472616e742063616c6c000000000000006044820152606401610c63565b611cf260027f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b60045473ffffffffffffffffffffffffffffffffffffffff16611d71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f46756e647320526563697069656e742061646472657373206e6f7420736574006044820152606401610c63565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe036013590479060009073ffffffffffffffffffffffffffffffffffffffff16634827ae0c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2b9190615b90565b73ffffffffffffffffffffffffffffffffffffffff16633b19e84a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e999190615b90565b60045490915060009073ffffffffffffffffffffffffffffffffffffffff858116911614801590611f1757507fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b8015611f4f57508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b15611f86576040517f1dab829b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b801561203a5760008273ffffffffffffffffffffffffffffffffffffffff16826203345090604051600060405180830381858888f193505050503d8060008114611fec576040519150601f19603f3d011682016040523d82523d6000602084013e611ff1565b606091505b505090508061202c576040517f39debd5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120368285615b2d565b9350505b60045460405160009173ffffffffffffffffffffffffffffffffffffffff16906203345090869084818181858888f193505050503d806000811461209a576040519150601f19603f3d011682016040523d82523d6000602084013e61209f565b606091505b50509050806120da576040517f39debd5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004546040805186815273ffffffffffffffffffffffffffffffffffffffff868116602083015291810185905291811691908716907f8a95554e4c9dcaaf33f247387f2ee77390780487d3365e3a804788791a1df5009060600160405180910390a3505050505061216a60017f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5473ffffffffffffffffffffffffffffffffffffffff163303612288577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614612283576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b61233e565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461233e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b60035474010000000000000000000000000000000000000000900467ffffffffffffffff9081161461239c576040517fe742c08400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000546003805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff90921691909117905561241a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe036013590565b6003546040517401000000000000000000000000000000000000000090910467ffffffffffffffff16815273ffffffffffffffffffffffffffffffffffffffff91909116907fb6cc1e876b8d7479c8afe025a58658b0f3c3ec5bd0f28cb4261326b162069bf89060200160405180910390a2565b60006124b87f4e5f991bca30eca2d4643aaefa807e88f96a4a97398933d572a3c0d973004a015490565b1561251f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f484f4c4f47524150483a20616c726561647920696e697469616c697a656400006044820152606401610c63565b6000828060200190518101906125359190615ca0565b8051600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff928316179055602082015191925016156125d0576020810151600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790555b6125fc81604001517fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf77277755565b60408051608080820183526101008401805173ffffffffffffffffffffffffffffffffffffffff9081168085528684015167ffffffffffffffff908116602080880182905260a0808b015161ffff16898b018190526060808d015188169a81018b9052600380547c01000000000000000000000000000000000000000000000000000000009093027fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff740100000000000000000000000000000000000000009097027fffffffff00000000000000000000000000000000000000000000000000000000909416909817929092179490941695909517909455600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001690981790975560e0890151805160058054998301519a830151851671010000000000000000000000000000000000027fffffffffffffff0000000000000000ffffffffffffffffffffffffffffffffff63ffffffff909c166d0100000000000000000000000000027fffffffffffffffffffffffffffffff0000000000000000000000000000000000909b166cffffffffffffffffffffffffff90931692909217999099179990991698909817909655948601516006805495880151928801518716700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff93881668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909716929097169190911794909417169390931790915560c090920151600755905116156128f7576101008101516101208201516040517f856a7ffa00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9092169163856a7ffa916128c491600401615320565b600060405180830381600087803b1580156128de57600080fd5b505af11580156128f2573d6000803e3d6000fd5b505050505b8060c00151801561291657506daaeb6d7670e522a718067333cd4e3b15155b15612a715760025473ffffffffffffffffffffffffffffffffffffffff166129b4576040517f4420e4860000000000000000000000000000000000000000000000000000000081523060048201526daaeb6d7670e522a718067333cd4e90634420e48690602401600060405180830381600087803b15801561299757600080fd5b505af11580156129ab573d6000803e3d6000fd5b50505050612a4c565b6002546040517f7d3e3dbe00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff90911660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe90604401600060405180830381600087803b158015612a3357600080fd5b505af1158015612a47573d6000803e3d6000fd5b505050505b60017f5c835f3b6bd322d9a084ffdeac746df2b96cce308e7f0612f4ff4f9c490734cc555b612a9a60017f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b610a8a83614e55565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5473ffffffffffffffffffffffffffffffffffffffff163303612bbf577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614612bba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b612c75565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612c75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5473ffffffffffffffffffffffffffffffffffffffff163303612dd8577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614612dd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b612e8e565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612e8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b600254309073ffffffffffffffffffffffffffffffffffffffff16612edf576040517f707ff7e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fc3c5a54700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526daaeb6d7670e522a718067333cd4e9063c3c5a547906024016020604051808303816000875af1158015612f59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f7d9190615b68565b158015612f875750815b1561302b576002546040517f7d3e3dbe00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015290911660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe906044015b600060405180830381600087803b15801561300e57600080fd5b505af1158015613022573d6000803e3d6000fd5b505050506131bf565b811561309d576002546040517fb314d41400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015290911660248201526daaeb6d7670e522a718067333cd4e9063b314d41490604401612ff4565b6040517f34a0dc1000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152600060248201526daaeb6d7670e522a718067333cd4e906334a0dc1090604401600060405180830381600087803b15801561311957600080fd5b505af115801561312d573d6000803e3d6000fd5b50506040517f2ec2c24600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526daaeb6d7670e522a718067333cd4e9250632ec2c2469150602401600060405180830381600087803b1580156131a657600080fd5b505af11580156131ba573d6000803e3d6000fd5b505050505b6040517fc3c5a5470000000000000000000000000000000000000000000000000000000081523060048201526000906daaeb6d7670e522a718067333cd4e9063c3c5a547906024016020604051808303816000875af1158015613226573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061324a9190615b68565b7f5c835f3b6bd322d9a084ffdeac746df2b96cce308e7f0612f4ff4f9c490734cc55505050565b6000610b4b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775490565b60006132c57fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b73ffffffffffffffffffffffffffffffffffffffff163303613359577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614905090565b507fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16331490565b6060815167ffffffffffffffff8111156133b3576133b361556c565b6040519080825280602002602001820160405280156133e657816020015b60608152602001906001900390816133d15790505b50905060005b8251811015613492576134623084838151811061340b5761340b615dac565b602002602001015161343d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe036013590565b60405160200161344e929190615ddb565b604051602081830303815290604052614ffc565b82828151811061347457613474615dac565b6020026020010181905250808061348a90615e25565b9150506133ec565b50919050565b60006134c27fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b73ffffffffffffffffffffffffffffffffffffffff1633036135bc577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff16146135b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b613672565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b600354829074010000000000000000000000000000000000000000900467ffffffffffffffff16158015906136f657506003546000547401000000000000000000000000000000000000000090910467ffffffffffffffff16906136f4907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683615ad8565b115b1561372d576040517f717c513000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b838110156137715761376985858381811061374d5761374d615dac565b90506020020160208101906137629190615333565b6001614a39565b600101613730565b50506000547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169392505050565b60606137c57fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b73ffffffffffffffffffffffffffffffffffffffff1633036138bf577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff16146138ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b613975565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613975576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b6000806daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1685856040516139ad929190615e5d565b6000604051808303816000865af19150503d80600081146139ea576040519150601f19603f3d011682016040523d82523d6000602084013e6139ef565b606091505b509150915081613a2b576040517f25f3885400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fc3c5a5470000000000000000000000000000000000000000000000000000000081523060048201526000906daaeb6d7670e522a718067333cd4e9063c3c5a547906024016020604051808303816000875af1158015613a92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ab69190615b68565b7f5c835f3b6bd322d9a084ffdeac746df2b96cce308e7f0612f4ff4f9c490734cc5550949350505050565b60606000613b0d7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b6040517f4f558e790000000000000000000000000000000000000000000000000000000081526004810185905290915073ffffffffffffffffffffffffffffffffffffffff821690634f558e7990602401602060405180830381865afa158015613b7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b9f9190615b68565b613c05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4552433732313a20746f6b656e20646f6573206e6f74206578697374000000006044820152606401610c63565b6003546040517fc87b56dd0000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff9091169063c87b56dd90602401600060405180830381865afa158015613c74573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a8a9190810190615a60565b613cde60405180606001604052806000815260200160008152602001600081525090565b6040805160608101825273ffffffffffffffffffffffffffffffffffffffff841660008181526009602081815285832054808652848452600882528684205482870181905294909352529192830191613d379190615b2d565b905292915050565b6000613d697fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b73ffffffffffffffffffffffffffffffffffffffff163303613e63577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614613e5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b613f19565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613f19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b600354829074010000000000000000000000000000000000000000900467ffffffffffffffff1615801590613f9d57506003546000547401000000000000000000000000000000000000000090910467ffffffffffffffff1690613f9b907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683615ad8565b115b15613fd4576040517f717c513000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613fde8484614a39565b50506000547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692915050565b600354604080517fe8a3d485000000000000000000000000000000000000000000000000000000008152905160609273ffffffffffffffffffffffffffffffffffffffff169163e8a3d4859160048083019260009291908290030181865afa158015610b05573d6000803e3d6000fd5b60006140a17f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a31372795490565b60020361410a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f484f4c4f47524150483a207265656e7472616e742063616c6c000000000000006044820152606401610c63565b61413360027f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b600354829074010000000000000000000000000000000000000000900467ffffffffffffffff16158015906141b757506003546000547401000000000000000000000000000000000000000090910467ffffffffffffffff16906141b5907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683615ad8565b115b156141ee576040517f717c513000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6141f6614e10565b61422c576040517ff12dcc7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055460009061424a906cffffffffffffffffffffffffff1661492f565b90506142568482615af0565b34101561427a576005546111c29085906cffffffffffffffffffffffffff16615af0565b60006142868583615af0565b6142909034615b2d565b6005549091506d0100000000000000000000000000900463ffffffff161580159061433e5750600554367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff166000908152600860209081526040808320546009909252909120546d010000000000000000000000000090920463ffffffff1691614332908890615ad8565b61433c9190615b2d565b115b15614375576040517f220ae94c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143a2367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013586614a39565b60006143cc7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b905060008173ffffffffffffffffffffffffffffffffffffffff166377dbd8636040518163ffffffff1660e01b8152600401602060405180830381865afa15801561441b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061443f9190615b44565b60008054919250906144709089907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16615b2d565b61447a9083615ad8565b614485906001615ad8565b90508488367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff167f4e26b0356a15833a75d497ecc40ebbb716b99466ed0dba9454f1fff451e25a90846040516144f491815260200190565b60405180910390a4831561459b57367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1684620334505a1161454d575a614552565b620334505b6040519091906000818181858888f193505050503d8060008114614592576040519150601f19603f3d011682016040523d82523d6000602084013e614597565b606091505b5050505b955050505050506145cb60017f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b919050565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5473ffffffffffffffffffffffffffffffffffffffff1633036146ec577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff16146146e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b6147a2565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146147a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b600580546cffffffffffffffffffffffffff89167fffffffffffffffffffffffffffffff0000000000000000000000000000000000909116176d010000000000000000000000000063ffffffff891602177fffffffffffffff0000000000000000ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000067ffffffffffffffff8881169190910291909117909155600680548683167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116176801000000000000000086841602177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16700100000000000000000000000000000000928516929092029190911790556007819055367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff167fc1ff5e4744ac8dd2b8027a10e3723b165975297501c71c4e7dcb8796d96375db60405160405180910390a250505050505050565b60008160000361494157506000919050565b6040517ff5d781610000000000000000000000000000000000000000000000000000000081526004810183905273a3db09eec42baff7a50fb8f9af90a0e035ef33029063f5d7816190602401602060405180830381865afa1580156149aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149ce9190615b44565b92915050565b600654600090426801000000000000000090910467ffffffffffffffff1611801590610b4b5750506006544270010000000000000000000000000000000090910467ffffffffffffffff161190565b600082614a308584615021565b14949350505050565b6000614a637fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b905060008173ffffffffffffffffffffffffffffffffffffffff166377dbd8636040518163ffffffff1660e01b8152600401602060405180830381865afa158015614ab2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ad69190615b44565b90506000805b84811015614e085760008054600191908190614b179084907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16615e6d565b92506101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1602179055505b60005473ffffffffffffffffffffffffffffffffffffffff851690634f558e7990614baf907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1686615ad8565b6040518263ffffffff1660e01b8152600401614bcd91815260200190565b602060405180830381865afa158015614bea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c0e9190615b68565b80614cbc575060005473ffffffffffffffffffffffffffffffffffffffff8516906323250cae90614c5d907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1686615ad8565b6040518263ffffffff1660e01b8152600401614c7b91815260200190565b602060405180830381865afa158015614c98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cbc9190615b68565b15614d475760008054600191908190614cf49084907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16615e6d565b92506101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550614b66565b6000546040517f3b4f1b2600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff88811660048301527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921660248201819052935090851690633b4f1b2690604401600060405180830381600087803b158015614ddd57600080fd5b505af1158015614df1573d6000803e3d6000fd5b505050508080614e0090615e25565b915050614adc565b505050505050565b600554600090427101000000000000000000000000000000000090910467ffffffffffffffff1611801590610b4b5750506006544267ffffffffffffffff9091161190565b6000614e7f7f4e5f991bca30eca2d4643aaefa807e88f96a4a97398933d572a3c0d973004a015490565b15614ee6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a20616c726561647920696e697469616c697a656400000000006044820152606401610c63565b337fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd8190557fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff8116614faa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f484f4c4f47524150483a206f776e6572206e6f742073657400000000000000006044820152606401610c63565b614fd360017f4e5f991bca30eca2d4643aaefa807e88f96a4a97398933d572a3c0d973004a0155565b507f4ddf47d4000000000000000000000000000000000000000000000000000000009392505050565b6060610a8a8383604051806060016040528060278152602001615eca60279139615095565b600081815b845181101561508d57600085828151811061504357615043615dac565b60200260200101519050808311615069576000838152602082905260409020925061507a565b600081815260208490526040902092505b508061508581615e25565b915050615026565b509392505050565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516150bf9190615ead565b600060405180830381855af49150503d80600081146150fa576040519150601f19603f3d011682016040523d82523d6000602084013e6150ff565b606091505b50915091506151108683838761511a565b9695505050505050565b606083156151b05782516000036151a95773ffffffffffffffffffffffffffffffffffffffff85163b6151a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c63565b50816151ba565b6151ba83836151c2565b949350505050565b8151156151d25781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c639190615320565b73ffffffffffffffffffffffffffffffffffffffff8116811461522857600080fd5b50565b6000806040838503121561523e57600080fd5b823561524981615206565b9150602083013561525981615206565b809150509250929050565b60006020828403121561527657600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610a8a57600080fd5b60005b838110156152c15781810151838201526020016152a9565b838111156152d0576000848401525b50505050565b600081518084526152ee8160208601602086016152a6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610a8a60208301846152d6565b60006020828403121561534557600080fd5b8135610a8a81615206565b60008083601f84011261536257600080fd5b50813567ffffffffffffffff81111561537a57600080fd5b6020830191508360208260051b850101111561539557600080fd5b9250929050565b6000806000806000608086880312156153b457600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff8111156153e057600080fd5b6153ec88828901615350565b969995985093965092949392505050565b60008083601f84011261540f57600080fd5b50813567ffffffffffffffff81111561542757600080fd5b60208301915083602082850101111561539557600080fd5b60008060008060006080868803121561545757600080fd5b853561546281615206565b9450602086013561547281615206565b935060408601359250606086013567ffffffffffffffff81111561549557600080fd5b6153ec888289016153fd565b815115158152610160810160208301516154bf602084018215159052565b506040830151604083015260608301516154e5606084018267ffffffffffffffff169052565b506080830151615501608084018267ffffffffffffffff169052565b5060a083015161551d60a084018267ffffffffffffffff169052565b5060c083015161553960c084018267ffffffffffffffff169052565b5060e083810151908301526101008084015190830152610120808401519083015261014092830151929091019190915290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610140810167ffffffffffffffff811182821017156155bf576155bf61556c565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561560c5761560c61556c565b604052919050565b600067ffffffffffffffff82111561562e5761562e61556c565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261566b57600080fd5b813561567e61567982615614565b6155c5565b81815284602083860101111561569357600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156156c357600080fd5b82356156ce81615206565b9150602083013567ffffffffffffffff8111156156ea57600080fd5b6156f68582860161565a565b9150509250929050565b60006020828403121561571257600080fd5b813567ffffffffffffffff81111561572957600080fd5b6151ba8482850161565a565b801515811461522857600080fd5b60006020828403121561575557600080fd5b8135610a8a81615735565b6000602080838503121561577357600080fd5b823567ffffffffffffffff8082111561578b57600080fd5b818501915085601f83011261579f57600080fd5b8135818111156157b1576157b161556c565b8060051b6157c08582016155c5565b91825283810185019185810190898411156157da57600080fd5b86860192505b83831015615816578235858111156157f85760008081fd5b6158068b89838a010161565a565b83525091860191908601906157e0565b9998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015615896577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526158848583516152d6565b9450928501929085019060010161584a565b5092979650505050505050565b600080602083850312156158b657600080fd5b823567ffffffffffffffff8111156158cd57600080fd5b6158d985828601615350565b90969095509350505050565b600080602083850312156158f857600080fd5b823567ffffffffffffffff81111561590f57600080fd5b6158d9858286016153fd565b60006020828403121561592d57600080fd5b5035919050565b6000806040838503121561594757600080fd5b823561595281615206565b946020939093013593505050565b6cffffffffffffffffffffffffff8116811461522857600080fd5b63ffffffff8116811461522857600080fd5b67ffffffffffffffff8116811461522857600080fd5b600080600080600080600060e0888a0312156159be57600080fd5b87356159c981615960565b965060208801356159d98161597b565b955060408801356159e98161598d565b945060608801356159f98161598d565b93506080880135615a098161598d565b925060a0880135615a198161598d565b8092505060c0880135905092959891949750929550565b6000615a3e61567984615614565b9050828152838383011115615a5257600080fd5b610a8a8360208301846152a6565b600060208284031215615a7257600080fd5b815167ffffffffffffffff811115615a8957600080fd5b8201601f81018413615a9a57600080fd5b6151ba84825160208401615a30565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615aeb57615aeb615aa9565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615b2857615b28615aa9565b500290565b600082821015615b3f57615b3f615aa9565b500390565b600060208284031215615b5657600080fd5b5051919050565b80516145cb81615735565b600060208284031215615b7a57600080fd5b8151610a8a81615735565b80516145cb81615206565b600060208284031215615ba257600080fd5b8151610a8a81615206565b80516145cb8161598d565b805161ffff811681146145cb57600080fd5b600060e08284031215615bdc57600080fd5b60405160e0810181811067ffffffffffffffff82111715615bff57615bff61556c565b80604052508091508251615c1281615960565b81526020830151615c228161597b565b60208201526040830151615c358161598d565b60408201526060830151615c488161598d565b6060820152615c5960808401615bad565b6080820152615c6a60a08401615bad565b60a082015260c083015160c08201525092915050565b600082601f830112615c9157600080fd5b610a8a83835160208501615a30565b600060208284031215615cb257600080fd5b815167ffffffffffffffff80821115615cca57600080fd5b908301906102008286031215615cdf57600080fd5b615ce761559b565b615cf083615b85565b8152615cfe60208401615b85565b6020820152615d0f60408401615b85565b6040820152615d2060608401615b85565b6060820152615d3160808401615bad565b6080820152615d4260a08401615bb8565b60a0820152615d5360c08401615b5d565b60c0820152615d658660e08501615bca565b60e0820152615d776101c08401615b85565b6101008201526101e083015182811115615d9057600080fd5b615d9c87828601615c80565b6101208301525095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008351615ded8184602088016152a6565b60609390931b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190920190815260140192915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615e5657615e56615aa9565b5060010190565b8183823760009101908152919050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff808316818516808303821115615ea457615ea4615aa9565b01949350505050565b60008251615ebf8184602087016152a6565b919091019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080d000a

Deployed Bytecode

0x6080604052600436106102895760003560e01c806361fea76811610153578063ac9650d8116100cb578063e58306f91161007f578063efef39a111610064578063efef39a1146109e6578063f7cd1d9b146109f9578063ffdb716314610a2657610303565b8063e58306f9146109b1578063e8a3d485146109d157610303565b8063bb20d857116100b0578063bb20d8571461092f578063c87b56dd1461094f578063d445b9781461096f57610303565b8063ac9650d8146108e2578063b8ae5a2c1461090f57610303565b80638a1968de116101225780638da5cb5b116101075780638da5cb5b1461088b5780638f32d59b146108a05780639123f01e146108b557610303565b80638a1968de146108435780638cb163f41461086357610303565b806361fea76814610702578063703199701461072f57806379502c551461075a57806384816f2a1461082357610303565b80632ca16676116102015780633bcdcc87116101b557806341e96eb11161019a57806341e96eb1146106565780634ddf47d41461066b57806354fd4d50146106bc57610303565b80633bcdcc87146106215780633ccfd60b1461064157610303565b80632f54bf6e116101e65780632f54bf6e146105df578063343b278f146105925780633474a4a6146105ff57610303565b80632ca16676146105925780632f0ae5fa146105b257610303565b806317430c9e116102585780632078d35f1161023d5780632078d35f1461051857806324d7806c1461055f57806325024a2b1461057f57610303565b806317430c9e146104095780631d2c0b381461042c57610303565b8063015eaa7a1461032e57806301ffc9a71461036357806306fdde03146103c557806310a7eb5d146103e757610303565b3661030357367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff167f8e47b87b0ef542cdfa1659c551d88bad38aa7f452d2bbb349ab7530dfec8be8f346040516102f991815260200190565b60405180910390a2005b6040517f46756e6374696f6e206e6f7420666f756e6400000000000000000000000000008152601481fd5b34801561033a57600080fd5b5061034e61034936600461522b565b610a46565b60405190151581526020015b60405180910390f35b34801561036f57600080fd5b5061034e61037e366004615264565b7fffffffff00000000000000000000000000000000000000000000000000000000167f1a95c452000000000000000000000000000000000000000000000000000000001490565b3480156103d157600080fd5b506103da610a91565b60405161035a9190615320565b3480156103f357600080fd5b50610407610402366004615333565b610b50565b005b34801561041557600080fd5b5061041e610e8a565b60405190815260200161035a565b34801561043857600080fd5b506005546006546007546104bf926cffffffffffffffffffffffffff8116926d0100000000000000000000000000820463ffffffff16927101000000000000000000000000000000000090920467ffffffffffffffff9081169281831692680100000000000000008104831692700100000000000000000000000000000000909104169087565b604080516cffffffffffffffffffffffffff909816885263ffffffff909616602088015267ffffffffffffffff948516958701959095529183166060860152821660808501521660a083015260c082015260e00161035a565b34801561052457600080fd5b5061053a6daaeb6d7670e522a718067333cd4e81565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161035a565b34801561056b57600080fd5b5061034e61057a366004615333565b610ea8565b61041e61058d36600461539c565b610f06565b34801561059e57600080fd5b5061034e6105ad36600461543f565b611550565b3480156105be57600080fd5b5060025461053a9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156105eb57600080fd5b5061034e6105fa366004615333565b61175e565b34801561060b57600080fd5b506106146117bd565b60405161035a91906154a1565b34801561062d57600080fd5b5061040761063c3660046156b0565b611928565b34801561064d57600080fd5b50610407611c3e565b34801561066257600080fd5b5061040761216c565b34801561067757600080fd5b5061068b610686366004615700565b61248e565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161035a565b3480156106c857600080fd5b5060408051808201909152600581527f312e302e3000000000000000000000000000000000000000000000000000000060208201526103da565b34801561070e57600080fd5b5061041e61071d366004615333565b60086020526000908152604090205481565b34801561073b57600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff1661053a565b34801561076657600080fd5b506003546004546107d69173ffffffffffffffffffffffffffffffffffffffff8082169274010000000000000000000000000000000000000000830467ffffffffffffffff16927c0100000000000000000000000000000000000000000000000000000000900461ffff16911684565b6040805173ffffffffffffffffffffffffffffffffffffffff958616815267ffffffffffffffff909416602085015261ffff9092169183019190915291909116606082015260800161035a565b34801561082f57600080fd5b5061040761083e366004615333565b612aa3565b34801561084f57600080fd5b5061040761085e366004615743565b612cbc565b34801561086f57600080fd5b5061053a73a3db09eec42baff7a50fb8f9af90a0e035ef330281565b34801561089757600080fd5b5061053a613271565b3480156108ac57600080fd5b5061034e61329b565b3480156108c157600080fd5b5061041e6108d0366004615333565b60096020526000908152604090205481565b3480156108ee57600080fd5b506109026108fd366004615760565b613397565b60405161035a9190615823565b34801561091b57600080fd5b5061041e61092a3660046158a3565b613498565b34801561093b57600080fd5b506103da61094a3660046158e5565b61379b565b34801561095b57600080fd5b506103da61096a36600461591b565b613ae1565b34801561097b57600080fd5b5061098f61098a366004615333565b613cba565b604080518251815260208084015190820152918101519082015260600161035a565b3480156109bd57600080fd5b5061041e6109cc366004615934565b613d3f565b3480156109dd57600080fd5b506103da614007565b61041e6109f436600461591b565b614077565b348015610a0557600080fd5b5060015461053a9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610a3257600080fd5b50610407610a413660046159a3565b6145d0565b60015460009073ffffffffffffffffffffffffffffffffffffffff1615801590610a8a575060015473ffffffffffffffffffffffffffffffffffffffff8381169116145b9392505050565b6060610abb7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b73ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015610b05573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b4b9190810190615a60565b905090565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5473ffffffffffffffffffffffffffffffffffffffff163303610c71577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614610c6c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e000000000060448201526064015b60405180910390fd5b610d27565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b73ffffffffffffffffffffffffffffffffffffffff8116610dca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f46756e647320526563697069656e742063616e6e6f742062652030206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610c63565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8316179055367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f70a7ea5c664ab9c21baf3da59bb2f1e1ca33557b08a0031fab4f17076744995160405160405180910390a350565b600554600090610b4b906cffffffffffffffffffffffffff1661492f565b60008173ffffffffffffffffffffffffffffffffffffffff16610ee97fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775490565b73ffffffffffffffffffffffffffffffffffffffff161492915050565b6000610f307f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a31372795490565b600203610f99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f484f4c4f47524150483a207265656e7472616e742063616c6c000000000000006044820152606401610c63565b610fc260027f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b600354869074010000000000000000000000000000000000000000900467ffffffffffffffff161580159061104657506003546000547401000000000000000000000000000000000000000090910467ffffffffffffffff1690611044907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683615ad8565b115b1561107d576040517f717c513000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110856149d4565b6110bb576040517f95ed3c1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61116484848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050600754915050367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001356040805173ffffffffffffffffffffffffffffffffffffffff909216602083015281018a90526060810189905260800160405160208183030381529060405280519060200120614a23565b61119a576040517f85b70e5200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006111a58661492f565b90506111b18882615af0565b3410156111f7576111c28887615af0565b6040517f6a1c179e000000000000000000000000000000000000000000000000000000008152600401610c6391815260200190565b60006112038983615af0565b61120d9034615b2d565b73ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe036013516600090815260086020526040812080549293508b9290919061126a908490615ad8565b909155505073ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0360135166000908152600860205260409020548810156112f1576040517fa7b32bb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61131e367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001358a614a39565b60006113487fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b905060008173ffffffffffffffffffffffffffffffffffffffff166377dbd8636040518163ffffffff1660e01b8152600401602060405180830381865afa158015611397573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bb9190615b44565b60008054919250906113ec908d907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16615b2d565b6113f69083615ad8565b611401906001615ad8565b9050848c367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff167f4e26b0356a15833a75d497ecc40ebbb716b99466ed0dba9454f1fff451e25a908460405161147091815260200190565b60405180910390a4831561151757367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1684620334505a116114c9575a6114ce565b620334505b6040519091906000818181858888f193505050503d806000811461150e576040519150601f19603f3d011682016040523d82523d6000602084013e611513565b606091505b5050505b9550505050505061154760017f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b95945050505050565b600073ffffffffffffffffffffffffffffffffffffffff8616158015906115c65750367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614155b15611752577f5c835f3b6bd322d9a084ffdeac746df2b96cce308e7f0612f4ff4f9c490734cc548015611750576daaeb6d7670e522a718067333cd4e63c617113430367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001356040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa9250505080156116d6575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526116d391810190615b68565b60015b611747576040517fede71dcc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0360135166004820152602401610c63565b91506115479050565b505b50600195945050505050565b60006117887fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775490565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915260405180610160016040528061182a614e10565b151581526020016118396149d4565b151581526005546cffffffffffffffffffffffffff8116602083015271010000000000000000000000000000000000810467ffffffffffffffff90811660408401526006548082166060850152680100000000000000008104821660808501527001000000000000000000000000000000009004811660a084015260075460c08401526d010000000000000000000000000090910463ffffffff1660e08301526000547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166101008301526003547401000000000000000000000000000000000000000090041661012090910152919050565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5473ffffffffffffffffffffffffffffffffffffffff163303611a44577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614611a3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b611afa565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611afa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055805115611bc6576040517f856a7ffa00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063856a7ffa90611b93908490600401615320565b600060405180830381600087803b158015611bad57600080fd5b505af1158015611bc1573d6000803e3d6000fd5b505050505b7f046c5d913c35948c3e0e44c3599eb14bf33b73f141fa8bb282b300414998b868367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001356040805173ffffffffffffffffffffffffffffffffffffffff928316815291851660208301520160405180910390a15050565b7f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727954600203611cc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f484f4c4f47524150483a207265656e7472616e742063616c6c000000000000006044820152606401610c63565b611cf260027f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b60045473ffffffffffffffffffffffffffffffffffffffff16611d71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f46756e647320526563697069656e742061646472657373206e6f7420736574006044820152606401610c63565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe036013590479060009073ffffffffffffffffffffffffffffffffffffffff16634827ae0c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2b9190615b90565b73ffffffffffffffffffffffffffffffffffffffff16633b19e84a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e999190615b90565b60045490915060009073ffffffffffffffffffffffffffffffffffffffff858116911614801590611f1757507fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b8015611f4f57508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b15611f86576040517f1dab829b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b801561203a5760008273ffffffffffffffffffffffffffffffffffffffff16826203345090604051600060405180830381858888f193505050503d8060008114611fec576040519150601f19603f3d011682016040523d82523d6000602084013e611ff1565b606091505b505090508061202c576040517f39debd5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120368285615b2d565b9350505b60045460405160009173ffffffffffffffffffffffffffffffffffffffff16906203345090869084818181858888f193505050503d806000811461209a576040519150601f19603f3d011682016040523d82523d6000602084013e61209f565b606091505b50509050806120da576040517f39debd5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004546040805186815273ffffffffffffffffffffffffffffffffffffffff868116602083015291810185905291811691908716907f8a95554e4c9dcaaf33f247387f2ee77390780487d3365e3a804788791a1df5009060600160405180910390a3505050505061216a60017f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5473ffffffffffffffffffffffffffffffffffffffff163303612288577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614612283576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b61233e565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461233e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b60035474010000000000000000000000000000000000000000900467ffffffffffffffff9081161461239c576040517fe742c08400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000546003805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff90921691909117905561241a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe036013590565b6003546040517401000000000000000000000000000000000000000090910467ffffffffffffffff16815273ffffffffffffffffffffffffffffffffffffffff91909116907fb6cc1e876b8d7479c8afe025a58658b0f3c3ec5bd0f28cb4261326b162069bf89060200160405180910390a2565b60006124b87f4e5f991bca30eca2d4643aaefa807e88f96a4a97398933d572a3c0d973004a015490565b1561251f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f484f4c4f47524150483a20616c726561647920696e697469616c697a656400006044820152606401610c63565b6000828060200190518101906125359190615ca0565b8051600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff928316179055602082015191925016156125d0576020810151600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790555b6125fc81604001517fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf77277755565b60408051608080820183526101008401805173ffffffffffffffffffffffffffffffffffffffff9081168085528684015167ffffffffffffffff908116602080880182905260a0808b015161ffff16898b018190526060808d015188169a81018b9052600380547c01000000000000000000000000000000000000000000000000000000009093027fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff740100000000000000000000000000000000000000009097027fffffffff00000000000000000000000000000000000000000000000000000000909416909817929092179490941695909517909455600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001690981790975560e0890151805160058054998301519a830151851671010000000000000000000000000000000000027fffffffffffffff0000000000000000ffffffffffffffffffffffffffffffffff63ffffffff909c166d0100000000000000000000000000027fffffffffffffffffffffffffffffff0000000000000000000000000000000000909b166cffffffffffffffffffffffffff90931692909217999099179990991698909817909655948601516006805495880151928801518716700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff93881668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909716929097169190911794909417169390931790915560c090920151600755905116156128f7576101008101516101208201516040517f856a7ffa00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9092169163856a7ffa916128c491600401615320565b600060405180830381600087803b1580156128de57600080fd5b505af11580156128f2573d6000803e3d6000fd5b505050505b8060c00151801561291657506daaeb6d7670e522a718067333cd4e3b15155b15612a715760025473ffffffffffffffffffffffffffffffffffffffff166129b4576040517f4420e4860000000000000000000000000000000000000000000000000000000081523060048201526daaeb6d7670e522a718067333cd4e90634420e48690602401600060405180830381600087803b15801561299757600080fd5b505af11580156129ab573d6000803e3d6000fd5b50505050612a4c565b6002546040517f7d3e3dbe00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff90911660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe90604401600060405180830381600087803b158015612a3357600080fd5b505af1158015612a47573d6000803e3d6000fd5b505050505b60017f5c835f3b6bd322d9a084ffdeac746df2b96cce308e7f0612f4ff4f9c490734cc555b612a9a60017f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b610a8a83614e55565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5473ffffffffffffffffffffffffffffffffffffffff163303612bbf577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614612bba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b612c75565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612c75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5473ffffffffffffffffffffffffffffffffffffffff163303612dd8577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614612dd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b612e8e565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612e8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b600254309073ffffffffffffffffffffffffffffffffffffffff16612edf576040517f707ff7e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fc3c5a54700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526daaeb6d7670e522a718067333cd4e9063c3c5a547906024016020604051808303816000875af1158015612f59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f7d9190615b68565b158015612f875750815b1561302b576002546040517f7d3e3dbe00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015290911660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe906044015b600060405180830381600087803b15801561300e57600080fd5b505af1158015613022573d6000803e3d6000fd5b505050506131bf565b811561309d576002546040517fb314d41400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015290911660248201526daaeb6d7670e522a718067333cd4e9063b314d41490604401612ff4565b6040517f34a0dc1000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152600060248201526daaeb6d7670e522a718067333cd4e906334a0dc1090604401600060405180830381600087803b15801561311957600080fd5b505af115801561312d573d6000803e3d6000fd5b50506040517f2ec2c24600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526daaeb6d7670e522a718067333cd4e9250632ec2c2469150602401600060405180830381600087803b1580156131a657600080fd5b505af11580156131ba573d6000803e3d6000fd5b505050505b6040517fc3c5a5470000000000000000000000000000000000000000000000000000000081523060048201526000906daaeb6d7670e522a718067333cd4e9063c3c5a547906024016020604051808303816000875af1158015613226573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061324a9190615b68565b7f5c835f3b6bd322d9a084ffdeac746df2b96cce308e7f0612f4ff4f9c490734cc55505050565b6000610b4b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775490565b60006132c57fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b73ffffffffffffffffffffffffffffffffffffffff163303613359577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614905090565b507fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16331490565b6060815167ffffffffffffffff8111156133b3576133b361556c565b6040519080825280602002602001820160405280156133e657816020015b60608152602001906001900390816133d15790505b50905060005b8251811015613492576134623084838151811061340b5761340b615dac565b602002602001015161343d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe036013590565b60405160200161344e929190615ddb565b604051602081830303815290604052614ffc565b82828151811061347457613474615dac565b6020026020010181905250808061348a90615e25565b9150506133ec565b50919050565b60006134c27fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b73ffffffffffffffffffffffffffffffffffffffff1633036135bc577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff16146135b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b613672565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b600354829074010000000000000000000000000000000000000000900467ffffffffffffffff16158015906136f657506003546000547401000000000000000000000000000000000000000090910467ffffffffffffffff16906136f4907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683615ad8565b115b1561372d576040517f717c513000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b838110156137715761376985858381811061374d5761374d615dac565b90506020020160208101906137629190615333565b6001614a39565b600101613730565b50506000547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169392505050565b60606137c57fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b73ffffffffffffffffffffffffffffffffffffffff1633036138bf577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff16146138ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b613975565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613975576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b6000806daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1685856040516139ad929190615e5d565b6000604051808303816000865af19150503d80600081146139ea576040519150601f19603f3d011682016040523d82523d6000602084013e6139ef565b606091505b509150915081613a2b576040517f25f3885400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fc3c5a5470000000000000000000000000000000000000000000000000000000081523060048201526000906daaeb6d7670e522a718067333cd4e9063c3c5a547906024016020604051808303816000875af1158015613a92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ab69190615b68565b7f5c835f3b6bd322d9a084ffdeac746df2b96cce308e7f0612f4ff4f9c490734cc5550949350505050565b60606000613b0d7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b6040517f4f558e790000000000000000000000000000000000000000000000000000000081526004810185905290915073ffffffffffffffffffffffffffffffffffffffff821690634f558e7990602401602060405180830381865afa158015613b7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b9f9190615b68565b613c05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4552433732313a20746f6b656e20646f6573206e6f74206578697374000000006044820152606401610c63565b6003546040517fc87b56dd0000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff9091169063c87b56dd90602401600060405180830381865afa158015613c74573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a8a9190810190615a60565b613cde60405180606001604052806000815260200160008152602001600081525090565b6040805160608101825273ffffffffffffffffffffffffffffffffffffffff841660008181526009602081815285832054808652848452600882528684205482870181905294909352529192830191613d379190615b2d565b905292915050565b6000613d697fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b73ffffffffffffffffffffffffffffffffffffffff163303613e63577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1614613e5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b613f19565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613f19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b600354829074010000000000000000000000000000000000000000900467ffffffffffffffff1615801590613f9d57506003546000547401000000000000000000000000000000000000000090910467ffffffffffffffff1690613f9b907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683615ad8565b115b15613fd4576040517f717c513000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613fde8484614a39565b50506000547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692915050565b600354604080517fe8a3d485000000000000000000000000000000000000000000000000000000008152905160609273ffffffffffffffffffffffffffffffffffffffff169163e8a3d4859160048083019260009291908290030181865afa158015610b05573d6000803e3d6000fd5b60006140a17f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a31372795490565b60020361410a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f484f4c4f47524150483a207265656e7472616e742063616c6c000000000000006044820152606401610c63565b61413360027f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b600354829074010000000000000000000000000000000000000000900467ffffffffffffffff16158015906141b757506003546000547401000000000000000000000000000000000000000090910467ffffffffffffffff16906141b5907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683615ad8565b115b156141ee576040517f717c513000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6141f6614e10565b61422c576040517ff12dcc7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055460009061424a906cffffffffffffffffffffffffff1661492f565b90506142568482615af0565b34101561427a576005546111c29085906cffffffffffffffffffffffffff16615af0565b60006142868583615af0565b6142909034615b2d565b6005549091506d0100000000000000000000000000900463ffffffff161580159061433e5750600554367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff166000908152600860209081526040808320546009909252909120546d010000000000000000000000000090920463ffffffff1691614332908890615ad8565b61433c9190615b2d565b115b15614375576040517f220ae94c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143a2367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013586614a39565b60006143cc7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b905060008173ffffffffffffffffffffffffffffffffffffffff166377dbd8636040518163ffffffff1660e01b8152600401602060405180830381865afa15801561441b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061443f9190615b44565b60008054919250906144709089907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16615b2d565b61447a9083615ad8565b614485906001615ad8565b90508488367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff167f4e26b0356a15833a75d497ecc40ebbb716b99466ed0dba9454f1fff451e25a90846040516144f491815260200190565b60405180910390a4831561459b57367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff1684620334505a1161454d575a614552565b620334505b6040519091906000818181858888f193505050503d8060008114614592576040519150601f19603f3d011682016040523d82523d6000602084013e614597565b606091505b5050505b955050505050506145cb60017f04b524dd539523930d3901481aa9455d7752b49add99e1647adb8b09a313727955565b919050565b7fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5473ffffffffffffffffffffffffffffffffffffffff1633036146ec577fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff16367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff16146146e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b6147a2565b7fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146147a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a206f776e6572206f6e6c792066756e6374696f6e00000000006044820152606401610c63565b600580546cffffffffffffffffffffffffff89167fffffffffffffffffffffffffffffff0000000000000000000000000000000000909116176d010000000000000000000000000063ffffffff891602177fffffffffffffff0000000000000000ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000067ffffffffffffffff8881169190910291909117909155600680548683167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116176801000000000000000086841602177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16700100000000000000000000000000000000928516929092029190911790556007819055367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013573ffffffffffffffffffffffffffffffffffffffff167fc1ff5e4744ac8dd2b8027a10e3723b165975297501c71c4e7dcb8796d96375db60405160405180910390a250505050505050565b60008160000361494157506000919050565b6040517ff5d781610000000000000000000000000000000000000000000000000000000081526004810183905273a3db09eec42baff7a50fb8f9af90a0e035ef33029063f5d7816190602401602060405180830381865afa1580156149aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149ce9190615b44565b92915050565b600654600090426801000000000000000090910467ffffffffffffffff1611801590610b4b5750506006544270010000000000000000000000000000000090910467ffffffffffffffff161190565b600082614a308584615021565b14949350505050565b6000614a637fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd5490565b905060008173ffffffffffffffffffffffffffffffffffffffff166377dbd8636040518163ffffffff1660e01b8152600401602060405180830381865afa158015614ab2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ad69190615b44565b90506000805b84811015614e085760008054600191908190614b179084907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16615e6d565b92506101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1602179055505b60005473ffffffffffffffffffffffffffffffffffffffff851690634f558e7990614baf907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1686615ad8565b6040518263ffffffff1660e01b8152600401614bcd91815260200190565b602060405180830381865afa158015614bea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c0e9190615b68565b80614cbc575060005473ffffffffffffffffffffffffffffffffffffffff8516906323250cae90614c5d907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1686615ad8565b6040518263ffffffff1660e01b8152600401614c7b91815260200190565b602060405180830381865afa158015614c98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cbc9190615b68565b15614d475760008054600191908190614cf49084907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16615e6d565b92506101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550614b66565b6000546040517f3b4f1b2600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff88811660048301527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921660248201819052935090851690633b4f1b2690604401600060405180830381600087803b158015614ddd57600080fd5b505af1158015614df1573d6000803e3d6000fd5b505050508080614e0090615e25565b915050614adc565b505050505050565b600554600090427101000000000000000000000000000000000090910467ffffffffffffffff1611801590610b4b5750506006544267ffffffffffffffff9091161190565b6000614e7f7f4e5f991bca30eca2d4643aaefa807e88f96a4a97398933d572a3c0d973004a015490565b15614ee6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732313a20616c726561647920696e697469616c697a656400000000006044820152606401610c63565b337fe9fcff60011c1a99f7b7244d1f2d9da93d79ea8ef3654ce590d775575255b2bd8190557fb56711ba6bd3ded7639fc335ee7524fe668a79d7558c85992e3f8494cf7727775473ffffffffffffffffffffffffffffffffffffffff8116614faa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f484f4c4f47524150483a206f776e6572206e6f742073657400000000000000006044820152606401610c63565b614fd360017f4e5f991bca30eca2d4643aaefa807e88f96a4a97398933d572a3c0d973004a0155565b507f4ddf47d4000000000000000000000000000000000000000000000000000000009392505050565b6060610a8a8383604051806060016040528060278152602001615eca60279139615095565b600081815b845181101561508d57600085828151811061504357615043615dac565b60200260200101519050808311615069576000838152602082905260409020925061507a565b600081815260208490526040902092505b508061508581615e25565b915050615026565b509392505050565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516150bf9190615ead565b600060405180830381855af49150503d80600081146150fa576040519150601f19603f3d011682016040523d82523d6000602084013e6150ff565b606091505b50915091506151108683838761511a565b9695505050505050565b606083156151b05782516000036151a95773ffffffffffffffffffffffffffffffffffffffff85163b6151a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c63565b50816151ba565b6151ba83836151c2565b949350505050565b8151156151d25781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c639190615320565b73ffffffffffffffffffffffffffffffffffffffff8116811461522857600080fd5b50565b6000806040838503121561523e57600080fd5b823561524981615206565b9150602083013561525981615206565b809150509250929050565b60006020828403121561527657600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610a8a57600080fd5b60005b838110156152c15781810151838201526020016152a9565b838111156152d0576000848401525b50505050565b600081518084526152ee8160208601602086016152a6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610a8a60208301846152d6565b60006020828403121561534557600080fd5b8135610a8a81615206565b60008083601f84011261536257600080fd5b50813567ffffffffffffffff81111561537a57600080fd5b6020830191508360208260051b850101111561539557600080fd5b9250929050565b6000806000806000608086880312156153b457600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff8111156153e057600080fd5b6153ec88828901615350565b969995985093965092949392505050565b60008083601f84011261540f57600080fd5b50813567ffffffffffffffff81111561542757600080fd5b60208301915083602082850101111561539557600080fd5b60008060008060006080868803121561545757600080fd5b853561546281615206565b9450602086013561547281615206565b935060408601359250606086013567ffffffffffffffff81111561549557600080fd5b6153ec888289016153fd565b815115158152610160810160208301516154bf602084018215159052565b506040830151604083015260608301516154e5606084018267ffffffffffffffff169052565b506080830151615501608084018267ffffffffffffffff169052565b5060a083015161551d60a084018267ffffffffffffffff169052565b5060c083015161553960c084018267ffffffffffffffff169052565b5060e083810151908301526101008084015190830152610120808401519083015261014092830151929091019190915290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610140810167ffffffffffffffff811182821017156155bf576155bf61556c565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561560c5761560c61556c565b604052919050565b600067ffffffffffffffff82111561562e5761562e61556c565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261566b57600080fd5b813561567e61567982615614565b6155c5565b81815284602083860101111561569357600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156156c357600080fd5b82356156ce81615206565b9150602083013567ffffffffffffffff8111156156ea57600080fd5b6156f68582860161565a565b9150509250929050565b60006020828403121561571257600080fd5b813567ffffffffffffffff81111561572957600080fd5b6151ba8482850161565a565b801515811461522857600080fd5b60006020828403121561575557600080fd5b8135610a8a81615735565b6000602080838503121561577357600080fd5b823567ffffffffffffffff8082111561578b57600080fd5b818501915085601f83011261579f57600080fd5b8135818111156157b1576157b161556c565b8060051b6157c08582016155c5565b91825283810185019185810190898411156157da57600080fd5b86860192505b83831015615816578235858111156157f85760008081fd5b6158068b89838a010161565a565b83525091860191908601906157e0565b9998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015615896577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526158848583516152d6565b9450928501929085019060010161584a565b5092979650505050505050565b600080602083850312156158b657600080fd5b823567ffffffffffffffff8111156158cd57600080fd5b6158d985828601615350565b90969095509350505050565b600080602083850312156158f857600080fd5b823567ffffffffffffffff81111561590f57600080fd5b6158d9858286016153fd565b60006020828403121561592d57600080fd5b5035919050565b6000806040838503121561594757600080fd5b823561595281615206565b946020939093013593505050565b6cffffffffffffffffffffffffff8116811461522857600080fd5b63ffffffff8116811461522857600080fd5b67ffffffffffffffff8116811461522857600080fd5b600080600080600080600060e0888a0312156159be57600080fd5b87356159c981615960565b965060208801356159d98161597b565b955060408801356159e98161598d565b945060608801356159f98161598d565b93506080880135615a098161598d565b925060a0880135615a198161598d565b8092505060c0880135905092959891949750929550565b6000615a3e61567984615614565b9050828152838383011115615a5257600080fd5b610a8a8360208301846152a6565b600060208284031215615a7257600080fd5b815167ffffffffffffffff811115615a8957600080fd5b8201601f81018413615a9a57600080fd5b6151ba84825160208401615a30565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615aeb57615aeb615aa9565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615b2857615b28615aa9565b500290565b600082821015615b3f57615b3f615aa9565b500390565b600060208284031215615b5657600080fd5b5051919050565b80516145cb81615735565b600060208284031215615b7a57600080fd5b8151610a8a81615735565b80516145cb81615206565b600060208284031215615ba257600080fd5b8151610a8a81615206565b80516145cb8161598d565b805161ffff811681146145cb57600080fd5b600060e08284031215615bdc57600080fd5b60405160e0810181811067ffffffffffffffff82111715615bff57615bff61556c565b80604052508091508251615c1281615960565b81526020830151615c228161597b565b60208201526040830151615c358161598d565b60408201526060830151615c488161598d565b6060820152615c5960808401615bad565b6080820152615c6a60a08401615bad565b60a082015260c083015160c08201525092915050565b600082601f830112615c9157600080fd5b610a8a83835160208501615a30565b600060208284031215615cb257600080fd5b815167ffffffffffffffff80821115615cca57600080fd5b908301906102008286031215615cdf57600080fd5b615ce761559b565b615cf083615b85565b8152615cfe60208401615b85565b6020820152615d0f60408401615b85565b6040820152615d2060608401615b85565b6060820152615d3160808401615bad565b6080820152615d4260a08401615bb8565b60a0820152615d5360c08401615b5d565b60c0820152615d658660e08501615bca565b60e0820152615d776101c08401615b85565b6101008201526101e083015182811115615d9057600080fd5b615d9c87828601615c80565b6101208301525095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008351615ded8184602088016152a6565b60609390931b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190920190815260140192915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615e5657615e56615aa9565b5060010190565b8183823760009101908152919050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff808316818516808303821115615ea457615ea4615aa9565b01949350505050565b60008251615ebf8184602087016152a6565b919091019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080d000a

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
[ 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.