ETH Price: $3,622.68 (-2.32%)

Token

ERC-20: TinyDaemons (TINYDMN)
 

Overview

Max Total Supply

2,007 TINYDMN

Holders

896

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
1 TINYDMN
0x131ea4dc4cda09d7d075bc3e3537959dc759c193
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
TinyDaemons

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 100 runs

Other Settings:
default evmVersion
File 1 of 40 : TinyDaemons.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: TinyDaemons.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: TinyDaemons an LZ ERC 721
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "./access/MaxAccess.sol";
import "./modules/TimeCop.sol";
import "./modules/NonblockingReceiver.sol";
import "./modules/ContractURI.sol";
import "./modules/PaymentSplitterV2.sol";
import "./modules/lzLlamas.sol";
import "./eip/2981/ERC2981Collection.sol";

contract TinyDaemons is MaxAccess
                      , TimeCop
                      , ContractURI
                      , PaymentSplitterV2
                      , ERC2981Collection
                      , lzLlamas
                      , ERC721
                      , ERC721Burnable
                      , NonblockingReceiver {

  using Strings for uint256;

  uint private gasForDestinationLzReceive = 350000;
  string base;

  event UpdatedBaseURI(string _old, string _new);
  event ThankYou(address user, uint amount);

  constructor() ERC721("TinyDaemons", "TINYDMN") {}

  modifier presaleChecks() {
    if (balanceOf(msg.sender) >= 4) {
      revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "Token: Ok ",
                    Strings.toHexString(uint160(msg.sender), 20),
                    " you have ",
                    Strings.toString(balanceOf(msg.sender)),
                    " maximum at this time is 4."
                  )
                )
      });
    }
    _;
  }

  modifier saleChecks() {
    if (balanceOf(msg.sender) >= 10) {
      revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "Token: Ok ",
                    Strings.toHexString(uint160(msg.sender), 20),
                    " you have ",
                    Strings.toString(balanceOf(msg.sender)),
                    " maximum at this time is 10."
                  )
                )
      });
    }
    _;
  }

  function presaleMint(
    uint quant
  ) external
    onlyPresale()
    presaleChecks() {
    if (quant > 2) {
      revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "Token: Ok ",
                    Strings.toHexString(uint160(msg.sender), 20),
                    " you wanted to mint ",
                    Strings.toString(quant),
                    " 2 or less please."
                  )
                )
      });
    }
    for (uint x = 0; x < quant;) {
      // this is a little sneaky to ensure you can't mint 1-2-2
      if (balanceOf(msg.sender) >= 4) {
        revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "Token: Ok ",
                    Strings.toHexString(uint160(msg.sender), 20),
                    " you wanted to mint ",
                    Strings.toString(quant),
                    " that puts you at ",
                    Strings.toString(quant + balanceOf(msg.sender)),
                    " maximum at this time is 4."
                  )
                )
        });
      }
      // mint it
      _safeMint(msg.sender, _nextUp());
      _oneRegularMint();
      unchecked { ++x; }
    }
  }

  function publicMint()
    external 
    onlySale()
    saleChecks() {
    _safeMint(msg.sender, _nextUp());
    _oneRegularMint();
  }

  function teamMint()
    external
    onlyDev() {
    uint quant = this.minterTeamMintsRemaining();
    for (uint x = 0; x < quant;) {
      // mint it
      _safeMint(this.owner(), _nextUp());
      _oneTeamMint();
      unchecked { ++x; }
    }
  }
    
  function donate()
    external
    payable {
    // thank you
    emit ThankYou(msg.sender, msg.value);
  }

  // @notice: Function to receive ether, msg.data must be empty
  receive() 
    external
    payable {
    // From PaymentSplitter.sol
    emit PaymentReceived(msg.sender, msg.value);
  }

  // @notice: Function to receive ether, msg.data is not empty
  fallback()
    external
    payable {
    // From PaymentSplitter.sol
    emit PaymentReceived(msg.sender, msg.value);
  }

  // @notice this is a public getter for ETH blance on contract
  function getBalance()
    external
    view
    returns (uint) {
    return address(this).balance;
  }

  // @notice: This sets the data for LZ minting
  // @param startNumber: What tokenID number to start with
  // @param authMint: How many to mint on this chain
  // @param teamMints: How many for team mint on this chain
  // @param string memory img: Provenance Hash of images in sequence
  // @param string memory json: Provenance Hash of metadata in sequence
  // @param newAddress: The address for the LZ Endpoint (see LZ docs)
  function setMinter (
    uint startNumber
  , uint authMint
  , uint teamMints
  , string memory img
  , string memory json
  , address newAddress
  ) external
    onlyDev {
    _setLZLlamasEngine( startNumber
                      , authMint
                      , teamMints);
    _setProvenance( img
                  , json);
    endpoint = ILayerZeroEndpoint(newAddress);
  }

  /*
   *     #@+                                             .                                     
   *    -@@#                                             =#*+=---+**-                          
   *    %@@.                                               .==*@@@@+-                          
   *   =@@*                                                  -@@@*                             
   *  .@@@                                                 .#@@#:                              
   *  *@@+        :                          ::   -:    +**@%@*=*-            .:   --    .:    
   *  @@%      =%@@@#@@. -@@*   +*:  .*##+.  @@- *@@=   =%@@**++*+    .+##*.  @@= *@@= .%@@%   
   * +@@=     #@@#--@@@. #@@*  =@@+ =@@@%@+ +@@:#--*#- -#%%.         -@@@#@* =@@:#-:*%*%@#-%= .
   * @@@    :#@@+.=@@@: .@@@ :*@@% =@@@%%= .@@#@-     .#@*          :@@@#%+ .%@#%=    %@##*@#*@
   * @@#  .*@@@%#%-@@* +@@@#*@#@@#%@@+: .-#*@@@*      *%%     ....  +@*: .-#*@@@*    =@% :%%-: 
   * =@@.=@@=-%#-  +@%@#:-*#+.@@@*:.%++%%=.%@@+       @@%#%**#@%@@@@*@*+%%+.%@@*     .%##@#    
   *   -==:         .-:     =%@@.    ::.   =%:        =%##+-.      .::::.   -#-        :-.     
   *                      +@@@@=                                                               
   *                    .%@-*@#                                                                
   *                    %@.=@@.                                                                
   *                    =@%@%:                                                                 
   *
   * @dev: This is the LayerZero functions for NonblockingReceiver.sol and more
   */

  // @notice: This function transfers the nft from your address on the 
  //          source chain to the same address on the destination chain
  // @param _chainId: the uint16 of desination chain (see LZ docs)
  // @param tokenId: tokenID to be sent
  function traverseChains(
    uint16 _chainId
  , uint tokenId
  ) public
    payable {
    if (msg.sender != ownerOf(tokenId)) {
      revert Unauthorized();
    }
    if (trustedRemoteLookup[_chainId].length == 0) {
      revert MaxSplaining({
        reason: "Token: Ok the Dev didn't set this paramater, contact MaxFlowO2.eth."
      });
    }

    // burn NFT, eliminating it from circulation on src chain
    _burn(tokenId);
    // fixes totalSupply()
    _subOne();

    // abi.encode() the payload with the values to send
    bytes memory payload = abi.encode(
                             msg.sender
                           , tokenId);

    // encode adapterParams to specify more gas for the destination
    uint16 version = 1;
    bytes memory adapterParams = abi.encodePacked(
                                   version
                                 , gasForDestinationLzReceive);

    // get the fees we need to pay to LayerZero + Relayer to cover message delivery
    // you will be refunded for extra gas paid
    (uint messageFee, ) = endpoint.estimateFees(
                            _chainId
                          , address(this)
                          , payload
                          , false
                          , adapterParams);

    // revert this transaction if the fees are not met
    if (messageFee > msg.value) {
      revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "Token: ",
                    Strings.toHexString(uint160(msg.sender), 20),
                    " sent ",
                    Strings.toString(msg.value),
                    " instead of ",
                    Strings.toString(messageFee)
                  )
                )
      });
    }

    // send the transaction to the endpoint
    endpoint.send{value: msg.value}(
      _chainId,                           // destination chainId
      trustedRemoteLookup[_chainId],      // destination address of nft contract
      payload,                            // abi.encoded()'ed bytes
      payable(msg.sender),                // refund address
      address(0x0),                       // 'zroPaymentAddress' unused for this
      adapterParams                       // txParameters 
    );
  }

  // @notice: just in case this fixed variable limits us from future integrations
  // @param newVal: new value for gas amount
  function setGasForDestinationLzReceive(
    uint newVal
  ) external onlyOwner {
    gasForDestinationLzReceive = newVal;
  }

  // @notice internal function to mint NFT from migration
  // @param _srcChainId - the source endpoint identifier
  // @param _srcAddress - the source sending contract address from the source chain
  // @param _nonce - the ordered message nonce
  // @param _payload - the signed payload is the UA bytes has encoded to be sent
  function _LzReceive(
    uint16 _srcChainId
  , bytes memory _srcAddress
  , uint64 _nonce
  , bytes memory _payload
  ) override
    internal {
    // decode
    (address toAddr, uint tokenId) = abi.decode(_payload, (address, uint));

    // mint the tokens back into existence on destination chain
    _safeMint(toAddr, tokenId);
    // fixes totalSupply()
    _addOne();
  }

  // @notice: will return gas value for LZ
  // @return: uint for gas value
  function currentLZGas()
    external
    view
    returns (uint256) {
    return gasForDestinationLzReceive;
  }  

  /*
   *       .=*#%@@@@%+                                     .:.                                 
   * .-+*%@@@@@@@-:::-*+                         =-=+**#%%@@@@%:     -*%@@@@%*-            #@@%
   * :*@%*=:-@@@*                                +%@@%##*+@@@@#    =@@@@#=.   =@:        +@@@@@
   *       .@@@#                                        =@@@%-   -#@@@#:       @@:     +@@@@@@=
   *      .@@@#                                        *@@@*   .#@@@%:        =@@-   =@@@@@@@% 
   *     :@@@*                                   -*##%@@@@@#:  :*##+         :@@#      --@%@@= 
   *    .@@@@===-     .    ..                     *@@@@@+++.                -@@%        #%%@#  
   * -#%@@@@@%##*=   @@@  =@@@   -+*+-             =@@@-                   =@@*.       :@#@@.  
   *  +%@@@:        =@@# #++@@:-*@@@@@=           -@@@:                  .=%*          =#@@#   
   *   %@@=      =+ #@@:#=: .++*@@*.%@: .:       :@@%.                  -*#-           %#@@-   
   *  .@@@     -#%=.@@%%#.    :@@*    :---       @@@.                  :#+            .%@@@    
   *  =@@+  .+%@%- *@@%%-     *@@   =%%++       :@@*                .-*+....:-*.      -#@@#:   
   *   #@*.+@@@=  :@@@@-      +@%=#@@%-         .%@-               #%@@@@@@@@@@*.   .++@@@@@*  
   *    -*#*+:    -@@+.        =###*:             =-               -**++++=-::::    :+**+=-.   
   *
   * @dev: These are the ERC721 functions/overrides plus ERC165 at the end
   */

  // @notice will update _baseURI() by onlyDeveloper() role
  // @param _base: Base for NFT's
  function setBaseURI(
    string memory _base
    )
    public
    onlyDev() {
    string memory old = base;
    base = _base;
    emit UpdatedBaseURI(old, base);
  }

  // @notice: This override sets _base as the string for tokenURI(tokenId)
  function _baseURI()
    internal
    view
    override
    returns (string memory) {
    return base;
  }

  // @notice: This override is for making string/number now string/number.json
  // @param tokenId: tokenId to pull URI for
  function tokenURI(
    uint256 tokenId
  ) public
    view
    virtual
    override (ERC721)
    returns (string memory) {
    if (!_exists(tokenId)) {
      revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "ERC721Metadata: URI query for ",
                    Strings.toString(tokenId),
                    " returns nonexistent token"
                  )
                )
      });
    }
    string memory baseURI = _baseURI();
    string memory json = ".json";
    return bytes(baseURI).length > 0 ? string(
                                         abi.encodePacked(
                                           baseURI
                                         , tokenId.toString()
                                         , json)
                                       ) : "";
  }

  // @notice: This override is to correct totalSupply()
  // @param tokenId: tokenId to burn
  function burn(
    uint256 tokenId
  ) public
    virtual
    override(ERC721Burnable) {
    //solhint-disable-next-line max-line-length
    if (!_isApprovedOrOwner(_msgSender(), tokenId)) {
      revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "ERC721Burnable: ",
                    Strings.toHexString(uint160(msg.sender), 20),
                    " is not owner nor approved"
                  )
                )
      });
    }
    _burn(tokenId);
    // fixes totalSupply()
    _subOne();
  }

  // @notice: Standard override for ERC165
  // @param interfaceId: interfaceId to check for compliance
  // @return: bool if interfaceId is supported
  function supportsInterface(
    bytes4 interfaceId
  ) public
    view
    virtual
    override (
      ERC721
    , IERC165
    ) returns (bool) {
    return (
      interfaceId == type(IRole).interfaceId  ||
      interfaceId == type(IDeveloper).interfaceId  ||
      interfaceId == type(IDeveloperV2).interfaceId  ||
      interfaceId == type(IOwner).interfaceId  ||
      interfaceId == type(IOwnerV2).interfaceId  ||
      interfaceId == type(IERC2981).interfaceId  ||
      interfaceId == type(IMAX2981).interfaceId  ||
      interfaceId == type(IMAXPaymentSplitter).interfaceId  ||
      interfaceId == type(IPaymentSplitter).interfaceId  ||
      interfaceId == type(IMAX721).interfaceId  ||
      interfaceId == type(ILlamas).interfaceId  ||
      interfaceId == type(lzILlamas).interfaceId  ||
      interfaceId == type(ITimeCop).interfaceId  ||
      interfaceId == type(IContractURI).interfaceId  ||
      interfaceId == type(IMAXContractURI).interfaceId  ||
      interfaceId == type(ILayerZeroReceiver).interfaceId  ||
      super.supportsInterface(interfaceId)
    );
  }
}

File 2 of 40 : lzLlamas.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: lzLlamas.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Solidity for Llama/BAYC Mint engine, does Provenance for Metadata/Images, for lzModules
 * Source: https://etherscan.io/address/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d#code
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "./lzILlamas.sol";
import "../lib/PsuedoRand.sol";
import "../lib/CountersV2.sol";

abstract contract lzLlamas is lzILlamas {

  using PsuedoRand for PsuedoRand.Engine;
  using CountersV2 for CountersV2.Counter;

  PsuedoRand.Engine private llamas;
  CountersV2.Counter private tokensOnChain;
  uint private tokenStartNumber;

  event SetStartNumbers(uint numberToMint, uint startingID, uint endingID);

  // @dev this is for any team mint that happens, must be included in mint...
  function _oneTeamMint()
    internal {
    llamas.battersUp();
    llamas.battersUpTeam();
    tokensOnChain.increment();
  }

  // @dev this is for any mint outside of a team mint, must be included in mint...
  function _oneRegularMint()
    internal {
    llamas.battersUp();
    tokensOnChain.increment();
  }

  // @dev this is to add one to on chain minted
  function _addOne()
    internal {
    tokensOnChain.increment();
  }

  // @dev this is to substract one to on chain minted
  function _subOne()
    internal {
    tokensOnChain.decrement();
  }

  // @dev this will set the boolean for minter status
  // @param toggle: bool for enabled or not
  function _setStatus(
    bool toggle
  ) internal {
    llamas.setStatus(toggle);
  }

  // @dev this will set the minter fees
  // @param number: uint for fees in wei.
  function _setMintFees(
    uint number
  ) internal {
    llamas.setFees(number);
  }

  // @dev this will set the mint engine
  // @param _startID: uint for startingID number (say 2000)
  // @param _mintingCap: uint for publicMint() capacity of this chain
  // @param _teamMints: uint for maximum teamMints() capacity on this chain
  function _setLZLlamasEngine(
    uint _startID
  , uint _mintingCap
  , uint _teamMints
  ) internal {
    tokenStartNumber = _startID;
    llamas.setMaxCap(_mintingCap);
    llamas.setMaxTeam(_teamMints);

    emit SetStartNumbers( _mintingCap
                        , _startID
                        , _mintingCap + _startID);
  }

  // @dev this will set the Provenance Hashes
  // @param string memory img - Provenance Hash of images in sequence
  // @param string memory json - Provenance Hash of metadata in sequence
  // @notice: This will set the start number as well, make sure to set MaxCap
  //  also can be a hyperlink... sha3... ipfs.. whatever.
  function _setProvenance(
    string memory img
  , string memory json
  ) internal {
    llamas.setProvJSON(json);
    llamas.setProvIMG(img);
    llamas.setStartNumber();
  }

  function _nextUp()
    internal
    view
    returns (uint) {
    return tokenStartNumber + llamas.mintID();
  }

  // @dev will return status of Minter
  // @return - bool of active or not
  function minterStatus()
    external
    view
    virtual
    override
    returns (bool) {
    return llamas.status;
  }

  // @dev will return minting fees
  // @return - uint of mint costs in wei
  function minterFees()
    external
    view
    virtual
    override
    returns (uint) {
    return llamas.mintFee;
  }

  // @dev will return maximum mint capacity
  // @return - uint of maximum mints allowed
  function minterMaximumCapacity()
    external
    view
    virtual
    override
    returns (uint) {
    return llamas.maxCapacity;
  }

  // @dev will return maximum mint capacity
  // @return - uint of maximum mints allowed
  function minterMintsRemaining()
    external
    view
    virtual
    returns (uint) {
    return llamas.maxCapacity - llamas.showMinted();
  }

  // @dev will return maximum mint capacity
  // @return - uint of maximum mints allowed
  function minterCurrentMints()
    external
    view
    virtual
    returns (uint) {
    return llamas.showMinted();
  }

  // @dev will return maximum "team minting" capacity
  // @return - uint of maximum airdrops or team mints allowed
  function minterMaximumTeamMints()
    external
    view
    virtual
    override
    returns (uint) {
    return llamas.maxTeamMints;
  }

  // @dev will return "team mints" left
  // @return - uint of remaing airdrops or team mints
  function minterTeamMintsRemaining()
    external
    view
    virtual
    override
    returns (uint) {
    return llamas.maxTeamMints - llamas.showTeam();
  }

  // @dev will return "team mints" count
  // @return - uint of airdrops or team mints done
  function minterTeamMintsCount()
    external
    view
    virtual
    override
    returns (uint) {
    return llamas.showTeam();
  }

  // @dev: will return total supply for mint
  // @return: uint for this mint
  function totalSupply()
    external
    view
    virtual
    override
    returns (uint256) {
    return tokensOnChain.current();
  }

  // @dev: will return Provenance hash of images
  // @return: string memory of the Images Hash (sha256)
  function RevealProvenanceImages() 
    external 
    view 
    virtual
    override 
    returns (string memory) {
    return llamas.ProvenanceIMG;
  }

  // @dev: will return Provenance hash of metadata
  // @return: string memory of the Metadata Hash (sha256)
  function RevealProvenanceJSON()
    external
    view
    virtual
    override
    returns (string memory) {
    return llamas.ProvenanceJSON;
  }

  // @dev: will return starting number for mint
  // @return: uint of the start number
  function RevealStartNumber()
    external
    view
    virtual
    override
    returns (uint256) {
    return llamas.startNumber;
  }

  // @dev: this is will show the start number for this chain's start number
  // @return: uint of start number
  function lzStartNumber()
    external
    view
    virtual
    override
    returns (uint256) {
    return tokenStartNumber;
  }
}

File 3 of 40 : lzILlamas.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: lzILlamas.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for Llama/BAYC Mint engine, does Provenance for Metadata/Images
 * Source: https://etherscan.io/address/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d#code
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "./ILlamas.sol";

///
/// @dev Interface for the ILlamas Standard v2.0 for LayerZero
///  this includes metadata with images
///

interface lzILlamas is ILlamas {

  // @dev: this is will show the start number for this chain's start number
  // @return: uint of start number
  function lzStartNumber()
    external
    view
    returns (uint256);

}

File 4 of 40 : TimeCop.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: TimeCop.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Time based mechanism for Solidity
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "./ITimeCop.sol";
import "../access/MaxAccess.sol";

abstract contract TimeCop is MaxAccess
                           , ITimeCop {

   uint private startPresale;
   uint private presaleDuration;

   event PresaleSet(uint start, uint length);

  function setPresale(
    uint time
  , uint duration
  ) external
    onlyDev() {
    startPresale = time;
    presaleDuration = duration;
    emit PresaleSet(time, duration);
  }

  function showPresaleStart()
    external
    view
    virtual
    override (ITimeCop)
    returns (uint) {
    return startPresale;
  }

  function showStart()
    external
    view
    virtual
    override (ITimeCop)
    returns (uint) {
    return startPresale + presaleDuration;
  }

  function showPresaleTimes()
    external
    view
    virtual
    override (ITimeCop)
    returns (uint, uint) {
    return (
      startPresale
    , startPresale + presaleDuration
    );
  }

    modifier onlyPresale() {
    if (block.timestamp < startPresale) {
      revert TooSoonJunior({
        yourTime: block.timestamp
      , hitTime: startPresale
      });
    }
    if (block.timestamp >= startPresale + presaleDuration) {
      revert TooLateBoomer({
        yourTime: block.timestamp
      , hitTime: startPresale + presaleDuration
      });
    }
    _;
  }

    modifier onlySale() {
    if (block.timestamp < startPresale + presaleDuration) {
      revert TooSoonJunior({
        yourTime: block.timestamp
      , hitTime: startPresale + presaleDuration
      });
    }
    if (startPresale == 0) {
      revert MaxSplaining({
        reason: "TimeCop: You've been Time Copped. NGL onlyDev() hasn't set the time"
      });
    }
    _;
  }
}

File 5 of 40 : PaymentSplitterV2.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: PaymentSplitterV2.sol
 * @author: OG was OZ, rewritten by Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Updated to add/subtract payees
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "./IMAXPaymentSplitter.sol";
import "../access/MaxAccess.sol";
import "@openzeppelin/contracts/utils/Address.sol";

// Removal of SafeMath due to ^0.8.0 standards, not needed

/**
 * @title PaymentSplitter
 * @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware
 * that the Ether will be split in this way, since it is handled transparently by the contract.
 *
 * The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each
 * account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim
 * an amount proportional to the percentage of total shares they were assigned.
 *
 * `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
 * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
 * function.
 */

abstract contract PaymentSplitterV2 is MaxAccess
                                     , IMAXPaymentSplitter {

  event PayeeAdded(address account, uint256 shares);
  event PaymentReleased(address to, uint256 amount);
  event PaymentReceived(address from, uint256 amount);
  event PayeeRemoved(address account, uint256 shares);
  event PayeesReset();

  uint256 private _totalShares;
  uint256 private _totalReleased;
  mapping(address => uint256) private _shares;
  mapping(address => uint256) private _released;
  address[] private _payees;

  /**
   * @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully
   * reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the
   * reliability of the events, and not the actual splitting of Ether.
   *
   * To learn more about this see the Solidity documentation for
   * https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
   * functions].
   *
   *  receive() external payable virtual {
   *    emit PaymentReceived(msg.sender, msg.value);
   *  }
   *
   *  // Fallback function is called when msg.data is not empty
   *  // Added to PaymentSplitter.sol
   *  fallback() external payable {
   *    emit PaymentReceived(msg.sender, msg.value);
   *  }
   *
   * receive() and fallback() to be handled at final contract
   */

  /**
   * @dev Getter for the total shares held by payees.
   */
  function totalShares() 
    external
    view
    virtual
    override
    returns (uint256) {
    return _totalShares;
  }

  /**
   * @dev Getter for the total amount of Ether already released.
   */
  function totalReleased()
    external
    view
    virtual
    override
    returns (uint256) {
    return _totalReleased;
  }

  /**
   * @dev Getter for the amount of shares held by an account.
   */
  function shares(
    address account
  ) external
    view
    virtual
    override
    returns (uint256) {
    return _shares[account];
  }

  /**
   * @dev Getter for the amount of Ether already released to a payee.
   */
  function released(
    address account
  ) external
    view
    virtual
    override
    returns (uint256) {
    return _released[account];
  }

  /**
   * @dev Getter for the address of the payee number `index`.
   */
  function payee(
    uint256 index
  ) external
    view
    virtual
    override
    returns (address) {
    return _payees[index];
  }

  /**
   * @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
   * total shares and their previous withdrawals.
   */
  // This function was updated from "account" to msg.sender
  function claim()
    external
    virtual
    override {
    address check = msg.sender;

    if (_shares[check] == 0) {
      revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "PaymentSplitter: ",
                    Strings.toHexString(uint160(msg.sender), 20),
                    " has no shares."
                  )
                )
      });
    }

    uint256 totalReceived = address(this).balance + _totalReleased;
    uint256 payment = (totalReceived * _shares[check]) / _totalShares - _released[check];

    if (payment == 0) {
      revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "PaymentSplitter: ",
                    Strings.toHexString(uint160(msg.sender), 20),
                    " is not due payment."
                  )
                )
      });
    }

    _released[check] = _released[check] + payment;
    _totalReleased = _totalReleased + payment;

    Address.sendValue(payable(check), payment);
    emit PaymentReleased(check, payment);
  }

  // now the internal logic of this contract

  /**
   * @dev Add a new payee to the contract.
   * @param account The address of the payee to add.
   * @param shares_ The number of shares owned by the payee.
   */
  // This function was updated to internal
  function _addPayee(
    address account
  , uint256 shares_
  ) internal {
    if (account == address(0)) {
      revert MaxSplaining({
        reason: "PaymentSplitter: account is the zero address"
      });
    } else if (shares_ == 0) {
      revert MaxSplaining({
        reason: "PaymentSplitter: shares are 0"
      });
    } else if (_shares[account] > 0) {
      revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "PaymentSplitter: ",
                    Strings.toHexString(uint160(account), 20),
                    " already has ",
                    Strings.toString(_shares[account]),
                    " shares."
                  )
                )
      });
    }

    _payees.push(account);
    _shares[account] = shares_;
    _totalShares = _totalShares + shares_;

    emit PayeeAdded(account, shares_);
  }

  /**
   * @dev finds index in array
   * @param account The address of the payee
   */
  function _findIndex(
    address account
  ) internal
    view
    returns (uint index) {
    uint max = _payees.length;
    for (uint i = 0; i < max;) {
      if (_payees[i] == account) {
        index = i;
      }
      unchecked { ++i; }
    }
  }

  /**
   * @dev Remove a payee to the contract.
   * @param account The address of the payee to remove.
   * leaves all payment data in the contract incase something was claimed
   */
  function _removePayee(
    address account
  ) internal {
    if (account == address(0)) {
      revert MaxSplaining({
        reason: "PaymentSplitter: account is the zero address"
      });
    } 

    // This finds the payee in the array _payees and removes it
    uint remove = _findIndex(account);
    address last = _payees[_payees.length - 1];
    _payees[remove] = last;
    _payees.pop();

    uint removeTwo = _shares[account];
    _shares[account] = 0;
    _totalShares = _totalShares - removeTwo;

    emit PayeeRemoved(account, removeTwo);
  }

  /**
   * @dev clears all data in PaymentSplitterV2
   * leaves all payment data in the contract incase something was claimed
   */
  function _clearAll()
    internal {
    uint max = _payees.length;
    for (uint i = 0; i < max;) {
      address account = _payees[i];
      _shares[account] = 0;
      unchecked { ++i; }
    }
    delete _totalShares;
    delete _payees;
    emit PayeesReset();
  }

  // @notice: This adds a payment split to PaymentSplitterV2.sol
  // @param newSplit: Address of payee
  // @param newShares: Shares to send user
  function addSplit (
    address newSplit
  , uint256 newShares
  ) external
    virtual
    override
    onlyDev() {
    _addPayee(newSplit, newShares);
  }

  // @notice: This removes a payment split on PaymentSplitterV2.sol
  // @param remSplit: Address of payee to remove
  function removeSplit (
    address remSplit
  ) external
    virtual
    override
    onlyDev() {
    _removePayee(remSplit);
  }

  // @notice: This removes all payment splits on PaymentSplitterV2.sol
  function clearSplits()
    external
    virtual
    override
    onlyDev() {
    _clearAll();
  }
}

File 6 of 40 : NonblockingReceiver.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: NonblockingReceiver.sol
 * @author: OG?? Rewrite: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: LZ non blocking reciever
 * OG Source: https://etherscan.io/address/0xa74ae2c6fca0cedbaef30a8ceef834b247186bcf#code
 * Remember to set all the trustedRemoteLookups with trustedRemoteLookup[chainID] = contract address
 */

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

import "./ILayerZeroReceiver.sol";
import "./ILayerZeroEndpoint.sol";
import "../access/MaxAccess.sol";

abstract contract NonblockingReceiver is MaxAccess, ILayerZeroReceiver {

  ILayerZeroEndpoint internal endpoint;

  struct FailedMessages {
    uint payloadLength;
    bytes32 payloadHash;
  }

  mapping(uint16 => mapping(bytes => mapping(uint => FailedMessages))) public failedMessages;
  mapping(uint16 => bytes) public trustedRemoteLookup;

  event TrustedRemoteSet(
    uint16 _chainId
  , bytes _trustedRemote);

  event MessageFailed(
    uint16 _srcChainId
  , bytes _srcAddress
  , uint64 _nonce
  , bytes _payload);

  // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
  // @param _srcChainId - the source endpoint identifier
  // @param _srcAddress - the source sending contract address from the source chain
  // @param _nonce - the ordered message nonce
  // @param _payload - the signed payload is the UA bytes has encoded to be sent
  function lzReceive(
    uint16 _srcChainId
  , bytes memory _srcAddress
  , uint64 _nonce
  , bytes memory _payload
  ) external
    override {
    if (msg.sender != address(endpoint)) {
      revert MaxSplaining({
        reason: "NonblockingReceiver: This message did not come from the endpoint, you failed, I won!"
      });
    }

    if (
      _srcAddress.length != trustedRemoteLookup[_srcChainId].length ||
      keccak256(_srcAddress) != keccak256(trustedRemoteLookup[_srcChainId])
    ) {
      revert MaxSplaining({
        reason: "NonblockingReceiver: This message did not come from a trusted contract, you failed, I won!"
      });
    }

    // try-catch all errors/exceptions
    // having failed messages does not block messages passing
    try this.onLzReceive(_srcChainId, _srcAddress, _nonce, _payload) {
      // do nothing
    } catch {
      // error or exception
      failedMessages[_srcChainId][_srcAddress][_nonce] = FailedMessages(_payload.length, keccak256(_payload));
      emit MessageFailed(_srcChainId, _srcAddress, _nonce, _payload);
    }
  }

  // @notice this is the catch all above (should be an internal?)
  // @param _srcChainId - the source endpoint identifier
  // @param _srcAddress - the source sending contract address from the source chain
  // @param _nonce - the ordered message nonce
  // @param _payload - the signed payload is the UA bytes has encoded to be sent
  function onLzReceive(
    uint16 _srcChainId
  , bytes memory _srcAddress
  , uint64 _nonce
  , bytes memory _payload
  ) public {

    // only internal transaction
    if (msg.sender != address(this)) {
      revert MaxSplaining({
        reason: "NonblockingReceiver: This message did not come internally, you failed, I won!"
      });
    }

    // handle incoming message
    _LzReceive( _srcChainId, _srcAddress, _nonce, _payload);
  }

  // @notice internal function to do something in the main contract
  // @param _srcChainId - the source endpoint identifier
  // @param _srcAddress - the source sending contract address from the source chain
  // @param _nonce - the ordered message nonce
  // @param _payload - the signed payload is the UA bytes has encoded to be sent
  function _LzReceive(
    uint16 _srcChainId
  , bytes memory _srcAddress
  , uint64 _nonce
  , bytes memory _payload
  ) virtual
    internal;

  // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
  // @param _dstChainId - the destination chain identifier
  // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
  // @param _payload - a custom bytes payload to send to the destination contract
  // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
  // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
  // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
  function _lzSend(
    uint16 _dstChainId
  , bytes memory _payload
  , address payable _refundAddress
  , address _zroPaymentAddress
  , bytes memory _txParam
  ) internal {
    endpoint.send{value: msg.value}(
      _dstChainId
    , trustedRemoteLookup[_dstChainId]
    , _payload, _refundAddress
    , _zroPaymentAddress
    , _txParam);
  }

  // @notice this is to retry a failed message on LayerZero
  // @param _srcChainId - the source chain identifier
  // @param _srcAddress - the source chain contract address
  // @param _nonce - the ordered message nonce
  // @param _payload - the payload to be retried
  function retryMessage(
    uint16 _srcChainId
  , bytes memory _srcAddress
  , uint64 _nonce
  , bytes calldata _payload
  ) external
    payable {
    // assert there is message to retry
    FailedMessages storage failedMsg = failedMessages[_srcChainId][_srcAddress][_nonce];
    if (failedMsg.payloadHash == bytes32(0)) {
      revert MaxSplaining({
        reason: "NonblockingReceiver: This message was already executed, you failed, I won!"
      });
    }
    if (
      _payload.length != failedMsg.payloadLength ||
      keccak256(_payload) != failedMsg.payloadHash
    ) {
      revert MaxSplaining({
        reason: "NonblockingReceiver: This message was not stored, you failed, I won!"
      });
    }

    // clear the stored message
    failedMsg.payloadLength = 0;
    failedMsg.payloadHash = bytes32(0);

    // execute the message. revert if it fails again
    this.onLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
  }


  // @notice this is to set all valid incoming messages
  // @param _srcChainId - the source chain identifier
  // @param _trustedRemote - the source chain contract address
  function setTrustedRemote(
    uint16 _chainId
  , bytes calldata _trustedRemote
  ) external
    onlyDev() {
    trustedRemoteLookup[_chainId] = _trustedRemote;
    emit TrustedRemoteSet(_chainId, _trustedRemote);
  }
}

File 7 of 40 : ITimeCop.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: ITimeCop.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Time based interface for Solidity
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

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

interface ITimeCop is IERC165 {

  function setPresale(
    uint time
  , uint duration
  ) external;

  function showPresaleStart()
    external
    view
    returns (uint);

  function showStart()
    external
    view
    returns (uint);

  function showPresaleTimes()
    external
    view
    returns (uint, uint);

}

File 8 of 40 : IPaymentSplitter.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: IPaymentSplitter.sol
 * @author: OG was OZ, rewritten by Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for PaymentSplitter.sol
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

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

///
/// @dev Interface for PaymentSplitter
///

interface IPaymentSplitter is IERC165 {

  /**
   * @dev Getter for the total shares held by payees.
   */
  function totalShares()
    external
    returns (uint256);

  /**
   * @dev Getter for the total amount of Ether already released.
   */
  function totalReleased()
    external
    returns (uint256);

  /**
   * @dev Getter for the amount of shares held by an account.
   */
  function shares(
    address account
  ) external
    view
    returns (uint256);

  /**
   * @dev Getter for the amount of Ether already released to a payee.
   */
  function released(
    address account
  ) external
    view
    returns (uint256);

  /**
   * @dev Getter for the address of the payee number `index`.
   */
  function payee(
    uint256 index
  ) external
    view
    returns (address);

  /**
   * @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
   * total shares and their previous withdrawals.
   */
  // This function was updated from "account" to msg.sender
  function claim()
    external;
}

File 9 of 40 : IMAXPaymentSplitter.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: IMAXPaymentSplitter.sol
 * @author: OG was OZ, rewritten by Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface extension for PaymentSplitter.sol
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "./IPaymentSplitter.sol";

///
/// @dev Interface extension for PaymentSplitter
///

interface IMAXPaymentSplitter is IPaymentSplitter {

  // @notice: This adds a payment split to PaymentSplitterV2.sol
  // @param newSplit: Address of payee
  // @param newShares: Shares to send user
  function addSplit (
    address newSplit
  , uint256 newShares
  ) external;

  // @notice: This removes a payment split on PaymentSplitterV2.sol
  // @param remSplit: Address of payee to remove
  function removeSplit (
    address remSplit
  ) external;

  // @notice: This removes all payment splits on PaymentSplitterV2.sol
  function clearSplits()
    external;

}

File 10 of 40 : IMAXContractURI.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: IMAXContractURI.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Extension for IContractURI
 */
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "./IContractURI.sol";

interface IMAXContractURI is IContractURI {

  // @notice this sets the contractURI, set to internal
  // @param URI - string to URI of Contract Metadata
  // @notice: let the metadata be in this format
  // {
  //   "name": Project's name,
  //   "description": Project's Description,
  //   "image": pfp for project,
  //   "external_link": web url,
  //   "seller_fee_basis_points": 100 -> Indicates a 1% seller fee.
  //   "fee_recipient": checksum address
  // }
  function setContractURI(
    string memory URI
  ) external;
}

File 11 of 40 : IMAX721.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: IMAX721.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for UX/UI
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

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

///
/// @dev Interface for @MaxFlowO2's Contracts
///

interface IMAX721 is IERC165 {

  // @dev will return status of Minter
  // @return - bool of active or not
  function minterStatus() 
    external
    view
    returns (bool);

  // @dev will return minting fees
  // @return - uint of mint costs in wei
  function minterFees()
    external
    view
    returns (uint);

  // @dev will return maximum mint capacity
  // @return - uint of maximum mints allowed
  function minterMaximumCapacity()
    external
    view
    returns (uint);

  // @dev will return maximum "team minting" capacity
  // @return - uint of maximum airdrops or team mints allowed
  function minterMaximumTeamMints()
    external
    view
    returns (uint);

  // @dev will return "team mints" left
  // @return - uint of remaing airdrops or team mints
  function minterTeamMintsRemaining()
    external
    view
    returns (uint);

  // @dev will return "team mints" count
  // @return - uint of airdrops or team mints done
  function minterTeamMintsCount()
    external
    view
    returns (uint);

  // @dev: will return total supply for mint
  // @return: uint for this mint
  function totalSupply()
    external
    view
    returns (uint256);
}

File 12 of 40 : ILlamas.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: ILlamas.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for Llama/BAYC Mint engine, does Provenance for Metadata/Images
 * Source: https://etherscan.io/address/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d#code
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "./IMAX721.sol";

///
/// @dev Interface for the ILlamas Standard v2.0
///  this includes metadata with images
///

interface ILlamas is IMAX721{

  // @dev: will return Provenance hash of images
  // @return: string memory of the Images Hash (sha256)
  function RevealProvenanceImages()
    external
    view
    returns (string memory);

  // @dev: will return Provenance hash of metadata
  // @return: string memory of the Metadata Hash (sha256)
  function RevealProvenanceJSON()
    external
    view
    returns (string memory);

  // @dev: will return starting number for mint
  // @return: uint of the start number
  function RevealStartNumber()
    external
    view
    returns (uint256);

}

File 13 of 40 : ILayerZeroUserApplicationConfig.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: ILayerZeroUserApplicationConfig.sol
 * @author: OG?? Rewrite: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for LayerZeroUserApplicationConfig
 * OG Source: https://etherscan.io/address/0xa74ae2c6fca0cedbaef30a8ceef834b247186bcf#code
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;

interface ILayerZeroUserApplicationConfig {
  // @notice set the configuration of the LayerZero messaging library of the specified version
  // @param _version - messaging library version
  // @param _chainId - the chainId for the pending config change
  // @param _configType - type of configuration. every messaging library has its own convention.
  // @param _config - configuration in the bytes. can encode arbitrary content.
  function setConfig(
    uint16 _version
  , uint16 _chainId
  , uint _configType
  , bytes calldata _config
  ) external;

  // @notice set the send() LayerZero messaging library version to _version
  // @param _version - new messaging library version
  function setSendVersion(
    uint16 _version
  ) external;

  // @notice set the lzReceive() LayerZero messaging library version to _version
  // @param _version - new messaging library version
  function setReceiveVersion(
    uint16 _version
  ) external;

  // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload
  // @param _srcChainId - the chainId of the source chain
  // @param _srcAddress - the contract address of the source contract at the source chain
  function forceResumeReceive(
    uint16 _srcChainId
  , bytes calldata _srcAddress
  ) external;
}

File 14 of 40 : ILayerZeroReceiver.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: ILayerZeroReceiver.sol
 * @author: OG?? Rewrite: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for LayerZeroReceiver
 * OG Source: https://etherscan.io/address/0xa74ae2c6fca0cedbaef30a8ceef834b247186bcf#code
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;

interface ILayerZeroReceiver {

  // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
  // @param _srcChainId - the source endpoint identifier
  // @param _srcAddress - the source sending contract address from the source chain
  // @param _nonce - the ordered message nonce
  // @param _payload - the signed payload is the UA bytes has encoded to be sent
  function lzReceive(
    uint16 _srcChainId
  , bytes calldata _srcAddress
  , uint64 _nonce
  , bytes calldata _payload
  ) external;

}

File 15 of 40 : ILayerZeroEndpoint.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: ILayerZeroEndpoint.sol
 * @author: OG?? Rewrite: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for LayerZeroEndpoint
 * OG Source: https://etherscan.io/address/0xa74ae2c6fca0cedbaef30a8ceef834b247186bcf#code
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;

import "./ILayerZeroUserApplicationConfig.sol";

interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
  // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
  // @param _dstChainId - the destination chain identifier
  // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
  // @param _payload - a custom bytes payload to send to the destination contract
  // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
  // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
  // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
  function send(
    uint16 _dstChainId
  , bytes calldata _destination
  , bytes calldata _payload
  , address payable _refundAddress
  , address _zroPaymentAddress
  , bytes calldata _adapterParams
  ) external
    payable;

  // @notice used by the messaging library to publish verified payload
  // @param _srcChainId - the source chain identifier
  // @param _srcAddress - the source contract (as bytes) at the source chain
  // @param _dstAddress - the address on destination chain
  // @param _nonce - the unbound message ordering nonce
  // @param _gasLimit - the gas limit for external contract execution
  // @param _payload - verified payload to send to the destination contract
  function receivePayload(
    uint16 _srcChainId
  , bytes calldata _srcAddress
  , address _dstAddress
  , uint64 _nonce
  , uint _gasLimit
  , bytes calldata _payload
  ) external;

  // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain
  // @param _srcChainId - the source chain identifier
  // @param _srcAddress - the source chain contract address
  function getInboundNonce(
    uint16 _srcChainId
  , bytes calldata _srcAddress
  ) external
    view
    returns (uint64);

  // @notice get the outboundNonce from this source chain which, consequently, is always an EVM
  // @param _srcAddress - the source chain contract address
  function getOutboundNonce(
    uint16 _dstChainId
  , address _srcAddress
  ) external
    view
    returns (uint64);

  // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery
  // @param _dstChainId - the destination chain identifier
  // @param _userApplication - the user app address on this EVM chain
  // @param _payload - the custom message to send over LayerZero
  // @param _payInZRO - if false, user app pays the protocol fee in native token
  // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain
  function estimateFees(
    uint16 _dstChainId
  , address _userApplication
  , bytes calldata _payload
  , bool _payInZRO
  , bytes calldata _adapterParam
  ) external
    view
    returns (
    uint nativeFee
  , uint zroFee);

  // @notice get this Endpoint's immutable source identifier
  function getChainId()
    external
    view
    returns (uint16);

  // @notice the interface to retry failed message on this Endpoint destination
  // @param _srcChainId - the source chain identifier
  // @param _srcAddress - the source chain contract address
  // @param _payload - the payload to be retried
  function retryPayload(
    uint16 _srcChainId
  , bytes calldata _srcAddress
  , bytes calldata _payload
  ) external;

  // @notice query if any STORED payload (message blocking) at the endpoint.
  // @param _srcChainId - the source chain identifier
  // @param _srcAddress - the source chain contract address
  function hasStoredPayload(
    uint16 _srcChainId
  , bytes calldata _srcAddress
  ) external
    view
    returns (bool);

  // @notice query if the _libraryAddress is valid for sending msgs.
  // @param _userApplication - the user app address on this EVM chain
  function getSendLibraryAddress(
    address _userApplication
  ) external
    view
    returns (address);

  // @notice query if the _libraryAddress is valid for receiving msgs.
  // @param _userApplication - the user app address on this EVM chain
  function getReceiveLibraryAddress(
    address _userApplication
  ) external
    view
    returns (address);

  // @notice query if the non-reentrancy guard for send() is on
  // @return true if the guard is on. false otherwise
  function isSendingPayload()
    external
    view
    returns (bool);

  // @notice query if the non-reentrancy guard for receive() is on
  // @return true if the guard is on. false otherwise
  function isReceivingPayload()
    external
    view
    returns (bool);

  // @notice get the configuration of the LayerZero messaging library of the specified version
  // @param _version - messaging library version
  // @param _chainId - the chainId for the pending config change
  // @param _userApplication - the contract address of the user application
  // @param _configType - type of configuration. every messaging library has its own convention.
  function getConfig(
    uint16 _version
  , uint16 _chainId
  , address _userApplication
  , uint _configType
  ) external
    view
    returns (bytes memory);

  // @notice get the send() LayerZero messaging library version
  // @param _userApplication - the contract address of the user application
  function getSendVersion(
    address _userApplication
  ) external
    view
    returns (uint16);

  // @notice get the lzReceive() LayerZero messaging library version
  // @param _userApplication - the contract address of the user application
  function getReceiveVersion(
    address _userApplication
  ) external
    view
    returns (uint16);
}

File 16 of 40 : IContractURI.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: IContractURI.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Purely for OpenSea compliance
 */
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

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

///
/// @dev Interface for the OpenSea Standard
///

interface IContractURI is IERC165{

  // @notice contractURI() called for retreval of 
  //  OpenSea style collections pages
  // @return - the string URI of the contract, usually IPFS
  function contractURI()
    external
    view
    returns (string memory);
}

File 17 of 40 : ContractURI.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: ContractURI.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Purely for OpenSea compliance
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "./IMAXContractURI.sol";
import "../access/MaxAccess.sol";

///
/// @dev Implementation of IMAXContractURI.sol
///

abstract contract ContractURI is MaxAccess
                               , IMAXContractURI {

  event ContractURIChange(
          string _old
        , string _new);

  string private thisContractURI;

  // @notice this sets the contractURI, set to internal
  // @param newURI - string to URI of Contract Metadata
  // @notice: let the metadata be in this format
  //{
  //  "name": Project's name,
  //  "description": Project's Description,
  //  "image": pfp for project,
  //  "external_link": web url,
  //  "seller_fee_basis_points": 100 -> Indicates a 1% seller fee.
  //  "fee_recipient": checksum address
  //}
  function _setContractURI(
    string memory newURI
  ) internal {
    string memory old = thisContractURI;
    thisContractURI = newURI;
    emit ContractURIChange(old, thisContractURI);
  }

  // @notice this clears the contractURI, set to internal
  function _clearContractURI() internal {
    string memory old = thisContractURI;
    delete thisContractURI;
    emit ContractURIChange(old, thisContractURI);
  }

  // @notice this sets the contractURI, set to internal
  // @param URI - string to URI of Contract Metadata
  // @notice: let the metadata be in this format
  // {
  //   "name": Project's name,
  //   "description": Project's Description,
  //   "image": pfp for project,
  //   "external_link": web url,
  //   "seller_fee_basis_points": 100 -> Indicates a 1% seller fee.
  //   "fee_recipient": checksum address
  // }
  function setContractURI(
    string memory URI
  ) external
    virtual
    override
    onlyDev() {
    _setContractURI(URI);
  }

  // @notice contractURI() called for retreval of
  //  OpenSea style collections pages
  // @return - string thisContractURI
  function contractURI() 
    external
    view
    virtual
    override(IContractURI)
    returns (string memory) {
    return thisContractURI;
  }
}

File 18 of 40 : Roles.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: Roles.sol
 * @author: OpenZeppelin, rewrite by Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Library for MaxAcess.sol
 * @dev: Rewritten for gas optimization, and from abstract -> library, added
 * multiple types instead of a solo role.
 * Original source:
 * https://github.com/hiddentao/openzeppelin-solidity/blob/master/contracts/access/Roles.sol
 *
 * Include with 'using Roles for Roles.Role;'
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "@openzeppelin/contracts/utils/Strings.sol";

library Roles {

  // @dev: this is Unauthorized(), basically a catch all, zero description
  // @notice: 0x82b42900 bytes4 of this
  error Unauthorized();

  // @dev: this is MaxSplaining(), giving you a reason, aka require(param, "reason")
  // @param reason: Use the "Contract name: error"
  // @notice: 0x0661b792 bytes4 of this
  error MaxSplaining(
    string reason
  );

  event RoleChanged(bytes4 _type, address _user, bool _status); // 0x0baaa7ab

  struct Role {
    mapping(address => mapping(bytes4 => bool)) bearer;
  }

  /**
   * @dev give an account access to this role
   */
  function add(Role storage role, bytes4 _type, address account) internal {
    if (account == address(0)) {
      revert Unauthorized();
    } else if (has(role, _type, account)) {
      revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "Lib Roles: ",
                    Strings.toHexString(uint160(account), 20),
                    " already has role ",
                    Strings.toHexString(uint32(_type), 4)
                  )
                )
      });
    }
    role.bearer[account][_type] = true;
    emit RoleChanged(_type, account, true);
  }

  /**
   * @dev remove an account's access to this role
   */
  function remove(Role storage role, bytes4 _type, address account) internal {
    if (account == address(0)) {
      revert Unauthorized();
    } else if (!has(role, _type, account)) {
      revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "Lib Roles: ",
                    Strings.toHexString(uint160(account), 20),
                    " does not have role ",
                    Strings.toHexString(uint32(_type), 4)
                  )
                )
      });
    }
    role.bearer[account][_type] = false;
    emit RoleChanged(_type, account, false);
  }

  /**
   * @dev check if an account has this role
   * @return bool
   */
  function has(Role storage role, bytes4 _type, address account)
    internal
    view
    returns (bool)
  {
    if (account == address(0)) {
      revert Unauthorized();
    }
    return role.bearer[account][_type];
  }
}

File 19 of 40 : PsuedoRand.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: PsuedoRand.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Library for Llama/BAYC Mint engine...
 *  basically a random start point and a bookends mint to start
 *  i.e. 0-2999 start at 500 -> 2999, then 0 -> 499.
 *
 *  Covers IMAX721.sol and Illamas.sol
 *
 * Include with 'using PsuedoRand for PsuedoRand.Engine;'
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "./CountersV2.sol";

library PsuedoRand {
  using CountersV2 for CountersV2.Counter;

  event SetProvenanceIMG(string _new, string _old);
  event SetProvenanceJSON(string _new, string _old);
  event SetStartNumber(uint _new);
  event SetMaxCapacity(uint _new, uint _old);
  event SetMaxTeamMint(uint _new, uint _old);
  event SetMintFees(uint _new, uint _old);
  event SetStatus(bool _new);

  // @dev: this is MaxSplaining(), giving you a reason, aka require(param, "reason")
  // @param reason: Use the "Contract name: error"
  // @notice: 0x0661b792 bytes4 of this
  error MaxSplaining(
    string reason
  );

  struct Engine {
    uint256 mintFee;
    uint256 startNumber;
    uint256 maxCapacity;
    uint256 maxTeamMints;
    string ProvenanceIMG;
    string ProvenanceJSON;
    CountersV2.Counter currentMinted;
    CountersV2.Counter currentTeam;
    bool status;
  }

  function setProvJSON(
    Engine storage engine
  , string memory provJSON
  ) internal {
    string memory old = engine.ProvenanceJSON;
    engine.ProvenanceJSON = provJSON;
    emit SetProvenanceJSON(provJSON, old);
  }
 
  function setProvIMG(
    Engine storage engine
  , string memory provIMG
  ) internal {
    string memory old = engine.ProvenanceIMG;
    engine.ProvenanceIMG = provIMG;
    emit SetProvenanceIMG(provIMG, old);
  }

  function setStartNumber(
    Engine storage engine
  ) internal {
    if (engine.maxCapacity == 0) {
      revert MaxSplaining({
        reason : "PsuedoRandom Lib: Maximum Capacity not set!"
      });
    }
    engine.startNumber = uint(
                           keccak256(
                             abi.encodePacked(
                               block.timestamp
                             , msg.sender
                             , engine.ProvenanceIMG
                             , engine.ProvenanceJSON
                             , block.difficulty))) 
                         % engine.maxCapacity;
    emit SetStartNumber(engine.startNumber);
  }

  function setMaxCap(
    Engine storage engine
  , uint256 max
  ) internal {
    uint old = engine.maxCapacity;
    engine.maxCapacity = max;
    emit SetMaxCapacity(max, old);
  }

  function setMaxTeam(
    Engine storage engine
  , uint256 max
  ) internal {
    uint old = engine.maxTeamMints;
    engine.maxTeamMints = max;
    emit SetMaxTeamMint(max, old);
  }

  function setFees(
    Engine storage engine
  , uint256 max
  ) internal {
    uint old = engine.mintFee;
    engine.mintFee = max;
    emit SetMintFees(max, old);
  }

  function setStatus(
    Engine storage engine
  , bool change
  ) internal {
    engine.status = change;
    emit SetStatus(change);
  }

  function mintID(
    Engine storage engine
  ) internal
    view
    returns (uint256) {
    return (engine.startNumber + engine.currentMinted.current()) % engine.maxCapacity;
  }

  function showTeam(
    Engine storage engine
  ) internal 
    view
    returns (uint256) {
    return engine.currentTeam.current();
  }

  function showMinted(
    Engine storage engine
  ) internal
    view
    returns (uint256) {
    return engine.currentMinted.current();
  }

  function battersUpTeam(
    Engine storage engine
  ) internal {
    engine.currentTeam.increment();
  }

  function battersUp(
    Engine storage engine
  ) internal {
    engine.currentMinted.increment();
  }
}

File 20 of 40 : CountersV2.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: CountersV2.sol
 * @author Matt Condon (@shrugs), Edits by Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @dev Provides counters that can only be incremented, decremented, reset or set. 
 * This can be used e.g. to track the number of elements in a mapping, issuing ERC721 ids
 * or counting request ids.
 *
 * Edited by @MaxFlowO2 for more NFT functionality on 13 Jan 2022
 * added .set(uint) so if projects need to start at say 1 or some random number they can
 * and an event log for numbers being reset or set.
 *
 * Include with `using CountersV2 for CountersV2.Counter;`
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

library CountersV2 {

  // @dev: this is MaxSplaining(), giving you a reason, aka require(param, "reason")
  // @param reason: Use the "Contract name: error"
  // @notice: 0x0661b792 bytes4 of this
  error MaxSplaining(
    string reason
  );

  event CounterNumberChangedTo(uint _number);

  struct Counter {
    // This variable should never be directly accessed by users of the library: interactions must be restricted to
    // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
    // this feature: see https://github.com/ethereum/solidity/issues/4637
    uint256 _value; // default: 0
  }

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

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

  function decrement(
    Counter storage counter
  ) internal {
    uint256 value = counter._value;
    if (value == 0) {
      revert MaxSplaining({
        reason : "CountersV2: No negatives in uints"
      });
    }
    unchecked {
      --counter._value;
    }
  }

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

  function set(
    Counter storage counter
  , uint number
  ) internal {
    counter._value = number;
    emit CounterNumberChangedTo(counter._value);
  }  
}

File 21 of 40 : MaxErrors.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: MaxErrors.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Custom errors for all contracts, minus libraries
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

abstract contract MaxErrors {

  // @dev: this is Unauthorized(), basically a catch all, zero description
  // @notice: 0x82b42900 bytes4 of this
  error Unauthorized();

  // @dev: this is MaxSplaining(), giving you a reason, aka require(param, "reason")
  // @param reason: Use the "Contract name: error"
  // @notice: 0x0661b792 bytes4 of this
  error MaxSplaining(
    string reason
  );

  // @dev: this is TooSoonJunior(), using times
  // @param yourTime: should almost always be block.timestamp
  // @param hitTime: the time you should have started
  // @notice: 0xf3f82ac5 bytes4 of this
  error TooSoonJunior(
    uint yourTime
  , uint hitTime
  );

  // @dev: this is TooLateBoomer(), using times
  // @param yourTime: should almost always be block.timestamp
  // @param hitTime: the time you should have ended
  // @notice: 0x43c540ef bytes4 of this
  error TooLateBoomer(
    uint yourTime
  , uint hitTime
  );

}

File 22 of 40 : IMAX2981.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: IMAX2981.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: IERC2981 Extension
 */

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./IERC2981.sol";

interface IMAX2981 is IERC2981 {

  // @notice: This sets the contract as royalty reciever (useful with abstract PaymentSplitter)
  // @param permille: Percentage you want so 3.5% -> 35
  function setRoyaltiesThis (
    uint permille
  ) external;

  // @notice: This sets royalties per EIP-2981
  // @param newAddress: Sets the address for royalties
  // @param permille: Percentage you want so 3.5% -> 35
  function setRoyalties (
    address newAddress
  , uint256 permille
  ) external;

  // @notice: This clears all EIP-2981 royalties (address(0) and 0%)
  function clearRoyalties()
    external;

}

File 23 of 40 : IERC2981.sol
/***
 *    ███████╗██╗██████╗       ██████╗  █████╗  █████╗  ██╗
 *    ██╔════╝██║██╔══██╗      ╚════██╗██╔══██╗██╔══██╗███║
 *    █████╗  ██║██████╔╝█████╗ █████╔╝╚██████║╚█████╔╝╚██║
 *    ██╔══╝  ██║██╔═══╝ ╚════╝██╔═══╝  ╚═══██║██╔══██╗ ██║
 *    ███████╗██║██║           ███████╗ █████╔╝╚█████╔╝ ██║
 *    ╚══════╝╚═╝╚═╝           ╚══════╝ ╚════╝  ╚════╝  ╚═╝                                                        
 * Zach Burks, James Morgan, Blaine Malone, James Seibel,
 * "EIP-2981: NFT Royalty Standard,"
 * Ethereum Improvement Proposals, no. 2981, September 2020. [Online serial].
 * Available: https://eips.ethereum.org/EIPS/eip-2981.
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

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

///
/// @dev Interface for the NFT Royalty Standard
///

interface IERC2981 is IERC165 {

  // @notice Called with the sale price to determine how much royalty
  //  is owed and to whom.
  // @param _tokenId - the NFT asset queried for royalty information
  // @param _salePrice - the sale price of the NFT asset specified by _tokenId
  // @return receiver - address of who should be sent the royalty payment
  // @return royaltyAmount - the royalty payment amount for _salePrice
  function royaltyInfo(
    uint256 _tokenId
  , uint256 _salePrice
  ) external
    view
    returns (
    address receiver
  , uint256 royaltyAmount
  );
}

File 24 of 40 : ERC2981Collection.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: ERC2981Collection.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Use case for EIP 2981, steered more towards NFT Collections as a whole
 */

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./IMAX2981.sol";
import "../../access/MaxAccess.sol";

abstract contract ERC2981Collection is MaxAccess, IMAX2981 {

  address private royaltyAddress;
  uint256 private royaltyPermille;

  event royalatiesSet(
          uint value
        , address recipient
        );

  // the internals to do logic flows later

  // @dev to set roaylties on contract via EIP 2891
  // @param _receiver, address of recipient
  // @param _permille, permille xx.x -> xxx value
  function _setRoyalties(
    address _receiver
  , uint256 _permille
  ) internal {
  if (_permille >= 1000 || _permille == 0) {
    revert MaxSplaining({
      reason: string(
                abi.encodePacked(
                  "ERC2981Collection: ",
                  Strings.toHexString(uint160(msg.sender), 20),
                  " submitted ",
                  Strings.toString(_permille),
                  " and that is out of bounds!"
                )
              )
    });
  }
    royaltyAddress = _receiver;
    royaltyPermille = _permille;
    emit royalatiesSet(royaltyPermille, royaltyAddress);
  }

  // @dev to remove royalties from contract
  function _removeRoyalties()
    internal {
    delete royaltyAddress;
    delete royaltyPermille;
    emit royalatiesSet(royaltyPermille, royaltyAddress);
  }

  // Logic for this contract (abstract)

  // @notice: This sets the contract as royalty reciever (useful with abstract PaymentSplitter)
  // @param permille: Percentage you want so 3.5% -> 35
  function setRoyaltiesThis (
    uint permille
  ) external
    virtual
    override
    onlyOwner() {
    _setRoyalties(address(this), permille);
  }

  // @notice: This sets royalties per EIP-2981
  // @param newAddress: Sets the address for royalties
  // @param permille: Percentage you want so 3.5% -> 35
  function setRoyalties (
    address newAddress
  , uint256 permille
  ) external
    virtual
    override
    onlyOwner() {
    _setRoyalties(newAddress, permille);
  }

  // @notice: This clears all EIP-2981 royalties (address(0) and 0%)
  function clearRoyalties()
    external
    virtual
    override
    onlyOwner() {
    _removeRoyalties();
  }

  // @dev Override for royaltyInfo(uint256, uint256)
  // @param _tokenId, uint of token ID to be checked
  // @param _salePrice, uint of amount of sale
  // @return receiver, address of recipient
  // @return royaltyAmount, amount royalties recieved
  function royaltyInfo(
    uint256 _tokenId
  , uint256 _salePrice
  ) external
    view
    virtual
    override
    returns (
    address receiver
  , uint256 royaltyAmount
  ) {
    receiver = royaltyAddress;
    royaltyAmount = _salePrice * royaltyPermille / 1000;
  }
}

File 25 of 40 : MaxAccess.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: MaxAccess.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Access control based off EIP 173/roles from OZ
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "./IOwnerV2.sol";
import "./IDeveloperV2.sol";
import "./IRole.sol";
import "../lib/Roles.sol";
import "../errors/MaxErrors.sol";
import "@openzeppelin/contracts/utils/Strings.sol";

abstract contract MaxAccess is MaxErrors
                             , IRole
                             , IOwnerV2
                             , IDeveloperV2 {
  using Roles for Roles.Role;

  Roles.Role private contractRoles;

  // bytes4 caluclated as follows
  // bytes4(keccak256(bytes(signature)))
  // developer() => 0xca4b208b
  // owner() => 0x8da5cb5b
  // admin() => 0xf851a440
  // was using trailing () for caluclations

  bytes4 constant private DEVS = 0xca4b208b;
  bytes4 constant private PENDING_DEVS = 0xca4b208a; // DEVS - 1
  bytes4 constant private OWNERS = 0x8da5cb5b;
  bytes4 constant private PENDING_OWNERS = 0x8da5cb5a; // OWNERS - 1
  bytes4 constant private ADMIN = 0xf851a440;

  // @dev you can sub your own address here... this is MaxFlowO2.eth
  // these are for displays anyways, and init().
  address private TheDev = address(0x4CE69fd760AD0c07490178f9a47863Dc0358cCCD);
  address private TheOwner = address(0x44f750eB065596c150B3479B1DF6957da300a332);

  constructor() {
    // supercedes all the logic below
    contractRoles.add(ADMIN, address(this));
    _grantRole(ADMIN, TheDev);
    _grantRole(OWNERS, TheOwner);
    _grantRole(DEVS, TheDev);
  }

  // modifiers
  modifier onlyRole(bytes4 role) {
    if (_checkRole(role, msg.sender) || _checkRole(ADMIN, msg.sender)) {
      _;
    } else {
      revert MaxSplaining({
        reason: string(
                  abi.encodePacked(
                    "MaxAccess: You are a not an ",
                    Strings.toHexString(uint32(role), 4),
                    " or ",
                    Strings.toHexString(uint32(ADMIN), 4),
                    " ",
                    Strings.toHexString(uint160(msg.sender), 20)
                  )
                )
      });
    }
  }

  modifier onlyDev() {
    if (!_checkRole(DEVS, msg.sender)) {
      revert Unauthorized();
    }
    _;
  }

  modifier onlyOwner() {
    if (!_checkRole(OWNERS, msg.sender)) {
      revert Unauthorized();
    }
    _;
  }

  // internal logic first 
  // (sets the tone later, and for later contracts)

  // @dev: this is the bool for checking if the account has a role via lib roles.sol
  // @param role: bytes4 of the role to check for
  // @param account: address of account to check
  // @return: bool true/false
  function _checkRole(
    bytes4 role
  , address account
  ) internal
    view
    virtual
    returns (bool) {
    return contractRoles.has(role, account);
  }

  // @dev: this is the internal to grant roles
  // @param role: bytes4 of the role
  // @param account: address of account to add
  function _grantRole(
    bytes4 role
  , address account
  ) internal
    virtual {
    contractRoles.add(role, account);
  }

  // @dev: this is the internal to revoke roles
  // @param role: bytes4 of the role
  // @param account: address of account to remove
  function _revokeRole(
    bytes4 role
  , address account
  ) internal
    virtual {
    contractRoles.remove(role, account);
  }

  // @dev: Returns `true` if `account` has been granted `role`.
  // @param role: Bytes4 of a role
  // @param account: Address to check
  // @return: bool true/false if account has role
  function hasRole(
    bytes4 role
  , address account
  ) external
    view
    virtual
    override
    returns (bool) {
    return _checkRole(role, account);
  }

  // @dev: Returns the admin role that controls a role
  // @param role: Role to check
  // @return: admin role
  function getRoleAdmin(
    bytes4 role
  ) external
    view
    virtual
    override
    returns (bytes4) {
    return ADMIN;
  }

  // @dev: Grants `role` to `account`
  // @param role: Bytes4 of a role
  // @param account: account to give role to
  function grantRole(
    bytes4 role
  , address account
  ) external
    virtual
    override 
    onlyRole(role) {

    if (role == PENDING_DEVS) {
      // locks out pending devs from mass swapping roles
      if (_checkRole(PENDING_DEVS, msg.sender)) {
        revert MaxSplaining({
          reason: string(
                    abi.encodePacked(
                      "MaxAccess: You are a pending developer() ",
                      Strings.toHexString(uint160(msg.sender), 20),
                      " you can not grant role ",
                      Strings.toHexString(uint32(role), 4),
                      " to ",
                      Strings.toHexString(uint160(account), 20)
                    )
                  )
        });
      }
    }

    if (role == PENDING_OWNERS) {
      // locks out pending owners from mass swapping roles
      if (_checkRole(PENDING_OWNERS, msg.sender)) {
        revert MaxSplaining({
          reason: string(
                    abi.encodePacked(
                      "MaxAccess: You are a pending owner() ",
                      Strings.toHexString(uint160(msg.sender), 20),
                      " you can not grant role ",
                      Strings.toHexString(uint32(role), 4),
                      " to ",
                      Strings.toHexString(uint160(account), 20)
                    )
                  )
        });
      }
    }

    _grantRole(role, account);
  }

  // @dev: Revokes `role` from `account`
  // @param role: Bytes4 of a role
  // @param account: account to revoke role from
  function revokeRole(
    bytes4 role
  , address account
  ) external
    virtual
    override
    onlyRole(role) {

    if (role == PENDING_DEVS) {
      // locks out pending devs from mass swapping roles
      if (account != msg.sender) {
        revert MaxSplaining({
          reason: string(
                    abi.encodePacked(
                      "MaxAccess: You are a pending developer() ",
                      Strings.toHexString(uint160(msg.sender), 20),
                      " you can not revoke role ",
                      Strings.toHexString(uint32(role), 4),
                      " to ",
                      Strings.toHexString(uint160(account), 20)
                    )
                  )
        });
      }
    }

    if (role == PENDING_OWNERS) {
      // locks out pending owners from mass swapping roles
      if (account != msg.sender) {
        revert MaxSplaining({
          reason: string(
                    abi.encodePacked(
                      "MaxAccess: You are a pending owner() ",
                      Strings.toHexString(uint160(msg.sender), 20),
                      " you can not revoke role ",
                      Strings.toHexString(uint32(role), 4),
                      " to ",
                      Strings.toHexString(uint160(account), 20)
                    )
                  )
        });
      }
    }
    _revokeRole(role, account);
  }

  // @dev: Renounces `role` from `account`
  // @param role: Bytes4 of a role
  // @param account: account to renounce role from
  function renounceRole(
    bytes4 role
  ) external
    virtual
    override 
    onlyRole(role) {
    address user = msg.sender;
    _revokeRole(role, user);
  }

  // Now the classic onlyDev() + "V2" suggested by auditors

  // @dev: Classic "EIP-173" but for onlyDev()
  // @return: Developer of contract
  function developer()
    external
    view
    virtual
    override
    returns (address) {
    return TheDev;
  }

  // @dev: This renounces your role as onlyDev()
  function renounceDeveloper()
    external
    virtual
    override 
    onlyRole(DEVS) {
    address user = msg.sender;
    _revokeRole(DEVS, user);
  }

  // @dev: Classic "EIP-173" but for onlyDev()
  // @param newDeveloper: addres of new pending Developer role
  function transferDeveloper(
    address newDeveloper
  ) external
    virtual
    override 
    onlyRole(DEVS) {
    address user = msg.sender;
    _grantRole(DEVS, newDeveloper);
    _revokeRole(DEVS, user);
  }

  // @dev: This accepts the push-pull method of onlyDev()
  function acceptDeveloper()
    external
    virtual
    override 
    onlyRole(PENDING_DEVS) {
    address user = msg.sender;
    _revokeRole(PENDING_DEVS, user);
    _grantRole(DEVS, user);
  }

  // @dev: This declines the push-pull method of onlyDev()
  function declineDeveloper()
    external
    virtual
    override 
    onlyRole(PENDING_DEVS) {
    address user = msg.sender;
    _revokeRole(PENDING_DEVS, user);
  }

  // @dev: This starts the push-pull method of onlyDev()
  // @param newDeveloper: addres of new pending developer role
  function pushDeveloper(
    address newDeveloper
  ) external
    virtual
    override
    onlyRole(DEVS) {
    _grantRole(PENDING_DEVS, newDeveloper);
  }

  // @dev: This changes the display of developer()
  // @param newDisplay: new display addrss for developer()
  function setDeveloper(
    address newDisplay
  ) external
    onlyDev() {
    if (!_checkRole(DEVS, newDisplay)) {
        revert MaxSplaining({
          reason: string(
                    abi.encodePacked(
                      "MaxAccess: The address ",
                      Strings.toHexString(uint160(newDisplay), 20),
                      " is not a developer and does not have the role ",
                      Strings.toHexString(uint32(DEVS), 4),
                      " there ",
                      Strings.toHexString(uint160(msg.sender), 20)
                    )
                  )
        });
    }
    TheDev = newDisplay;
  }

  // Now the classic onlyOwner() + "V2" suggested by auditors

  // @dev: Classic "EIP-173" getter for owner()
  // @return: owner of contract
  function owner()
    external
    view
    virtual
    override
    returns (address) {
    return TheOwner;
  }

   // @dev: This renounces your role as onlyOwner()
  function renounceOwnership()
    external
    virtual
    override
    onlyRole(OWNERS) {
    address user = msg.sender;
    _revokeRole(OWNERS, user);
  }

  // @dev: Classic "EIP-173" but for onlyOwner()
  // @param newOwner: addres of new pending Developer role
  function transferOwnership(
    address newOwner
  ) external
    virtual
    override
    onlyRole(OWNERS) {
    address user = msg.sender;
    _grantRole(OWNERS, newOwner);
    _revokeRole(OWNERS, user);
  }

  // @dev: This accepts the push-pull method of onlyOwner()
  function acceptOwnership()
    external
    virtual
    override
    onlyRole(PENDING_OWNERS) {
    address user = msg.sender;
    _revokeRole(PENDING_OWNERS, user);
    _grantRole(OWNERS, user);
  }

  // @dev: This declines the push-pull method of onlyOwner()
  function declineOwnership()
    external
    virtual
    override
    onlyRole(PENDING_OWNERS) {
    address user = msg.sender;
    _revokeRole(PENDING_OWNERS, user);
  }

  // @dev: This starts the push-pull method of onlyOwner()
  // @param newOwner: addres of new pending developer role
  function pushOwnership(
    address newOwner
  ) external
    virtual
    override
    onlyRole(OWNERS) {
    _grantRole(PENDING_OWNERS, newOwner);
  }

  // @dev: This changes the display of Ownership()
  // @param newDisplay: new display addrss for Ownership()
  function setOwner(
    address newDisplay
  ) external
    onlyOwner() {
    if (!_checkRole(OWNERS, newDisplay)) {
        revert MaxSplaining({
          reason: string(
                    abi.encodePacked(
                      "MaxAccess: The address ",
                      Strings.toHexString(uint160(newDisplay), 20),
                      " is not an owner and does not have the role ",
                      Strings.toHexString(uint32(OWNERS), 4),
                      " there ",
                      Strings.toHexString(uint160(msg.sender), 20)
                    )
                  )
        });
    }
    TheOwner = newDisplay;
  }
}

File 26 of 40 : IRole.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: IRole.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for MaxAccess version of roles
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

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

interface IRole is IERC165 {

  // @dev: Returns `true` if `account` has been granted `role`.
  // @param role: Bytes4 of a role
  // @param account: Address to check
  // @return: bool true/false if account has role
  function hasRole(
    bytes4 role
  , address account
  ) external
    view
    returns (bool);

  // @dev: Returns the admin role that controls a role
  // @param role: Role to check
  // @return: admin role
  function getRoleAdmin(
    bytes4 role
  ) external
    view 
    returns (bytes4);

  // @dev: Grants `role` to `account`
  // @param role: Bytes4 of a role
  // @param account: account to give role to
  function grantRole(
    bytes4 role
  , address account
  ) external;

  // @dev: Revokes `role` from `account`
  // @param role: Bytes4 of a role
  // @param account: account to revoke role from
  function revokeRole(
    bytes4 role
  , address account
  ) external;

  // @dev: Renounces `role` from `account`
  // @param role: Bytes4 of a role
  // @param account: account to renounce role from
  function renounceRole(
    bytes4 role
  ) external;
}

File 27 of 40 : IOwnerV2.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: IOwnerV2.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface V2 for onlyOwner() role, suggested by Auditors...
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "./IOwner.sol";

interface IOwnerV2 is IOwner {

  // @dev: This accepts the push-pull method of onlyOwner()
  function acceptOwnership()
    external;

  // @dev: This declines the push-pull method of onlyOwner()
  function declineOwnership()
    external;

  // @dev: This starts the push-pull method of onlyOwner()
  // @param newOwner: addres of new pending owner role
  function pushOwnership(
    address newOwner
  ) external;
}

File 28 of 40 : IOwner.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#* 
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=: 
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%* 
 *
 * @title: IOwner.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for onlyOwner() role
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

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

interface IOwner is IERC165 {

  // @dev: Classic "EIP-173" getter for owner()
  // @return: owner of contract
  function owner()
    external
    view
    returns (address);

  // @dev: This is the classic "EIP-173" method of setting onlyOwner()  
  function renounceOwnership()
    external;


  // @dev: This is the classic "EIP-173" method of setting onlyOwner()
  // @param newOwner: addres of new pending owner role
  function transferOwnership(
    address newOwner
  ) external;
}

File 29 of 40 : IDeveloperV2.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: IDeveloperV2.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface V2 for onlyDev() role, suggested by Auditors...
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "./IDeveloper.sol";

interface IDeveloperV2 is IDeveloper {

  // @dev: This accepts the push-pull method of onlyDev()
  function acceptDeveloper()
    external;

  // @dev: This declines the push-pull method of onlyDev()
  function declineDeveloper()
    external;

  // @dev: This starts the push-pull method of onlyDev()
  // @param newDeveloper: addres of new pending developer role
  function pushDeveloper(
    address newDeveloper
  ) external;
}

File 30 of 40 : IDeveloper.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#* 
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=: 
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%* 
 *
 * @title: IDeveloper.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for onlyDev() role
 */

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

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

interface IDeveloper is IERC165 {


  // @dev: Classic "EIP-173" but for onlyDev()
  // @return: Developer of contract
  function developer()
    external
    view
    returns (address);

  // @dev: This renounces your role as onlyDev()
  function renounceDeveloper()
    external;

  // @dev: Classic "EIP-173" but for onlyDev()
  // @param newDeveloper: addres of new pending Developer role
  function transferDeveloper(
    address newDeveloper
  ) external;
}

File 31 of 40 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

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

File 32 of 40 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

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

File 33 of 40 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Strings.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

File 34 of 40 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Context.sol)

pragma solidity ^0.8.0;

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

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

File 35 of 40 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Address.sol)

pragma solidity ^0.8.0;

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

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

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

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

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

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

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

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

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 36 of 40 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

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

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

File 37 of 40 : ERC721Burnable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/extensions/ERC721Burnable.sol)

pragma solidity ^0.8.0;

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

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

File 38 of 40 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

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

File 39 of 40 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

File 40 of 40 : ERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;

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

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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        _approve(to, tokenId);
    }

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

        return _tokenApprovals[tokenId];
    }

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

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

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

        _transfer(from, to, tokenId);
    }

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

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

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        _beforeTokenTransfer(from, to, tokenId);

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

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

        emit Transfer(from, to, tokenId);
    }

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

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

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

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

Settings
{
  "remappings": [],
  "optimizer": {
    "enabled": true,
    "runs": 100
  },
  "evmVersion": "london",
  "libraries": {},
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"MaxSplaining","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"MaxSplaining","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"MaxSplaining","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"MaxSplaining","type":"error"},{"inputs":[{"internalType":"uint256","name":"yourTime","type":"uint256"},{"internalType":"uint256","name":"hitTime","type":"uint256"}],"name":"TooLateBoomer","type":"error"},{"inputs":[{"internalType":"uint256","name":"yourTime","type":"uint256"},{"internalType":"uint256","name":"hitTime","type":"uint256"}],"name":"TooSoonJunior","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_old","type":"string"},{"indexed":false,"internalType":"string","name":"_new","type":"string"}],"name":"ContractURIChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"MessageFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"PayeeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"PayeeRemoved","type":"event"},{"anonymous":false,"inputs":[],"name":"PayeesReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PaymentReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PaymentReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"start","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"length","type":"uint256"}],"name":"PresaleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"numberToMint","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endingID","type":"uint256"}],"name":"SetStartNumbers","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ThankYou","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_chainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_trustedRemote","type":"bytes"}],"name":"TrustedRemoteSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_old","type":"string"},{"indexed":false,"internalType":"string","name":"_new","type":"string"}],"name":"UpdatedBaseURI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"royalatiesSet","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"RevealProvenanceImages","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RevealProvenanceJSON","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RevealStartNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptDeveloper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSplit","type":"address"},{"internalType":"uint256","name":"newShares","type":"uint256"}],"name":"addSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clearRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clearSplits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentLZGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"declineDeveloper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"declineOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"developer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"donate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"failedMessages","outputs":[{"internalType":"uint256","name":"payloadLength","type":"uint256"},{"internalType":"bytes32","name":"payloadHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lzStartNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterCurrentMints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterMaximumCapacity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterMaximumTeamMints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterMintsRemaining","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterTeamMintsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterTeamMintsRemaining","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"onLzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"payee","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quant","type":"uint256"}],"name":"presaleMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"publicMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newDeveloper","type":"address"}],"name":"pushDeveloper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"pushOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"released","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"remSplit","type":"address"}],"name":"removeSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceDeveloper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"retryMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_base","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"URI","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newDisplay","type":"address"}],"name":"setDeveloper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newVal","type":"uint256"}],"name":"setGasForDestinationLzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startNumber","type":"uint256"},{"internalType":"uint256","name":"authMint","type":"uint256"},{"internalType":"uint256","name":"teamMints","type":"uint256"},{"internalType":"string","name":"img","type":"string"},{"internalType":"string","name":"json","type":"string"},{"internalType":"address","name":"newAddress","type":"address"}],"name":"setMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newDisplay","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"setPresale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"},{"internalType":"uint256","name":"permille","type":"uint256"}],"name":"setRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"permille","type":"uint256"}],"name":"setRoyaltiesThis","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"bytes","name":"_trustedRemote","type":"bytes"}],"name":"setTrustedRemote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"shares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"showPresaleStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"showPresaleTimes","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"showStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"teamMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReleased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newDeveloper","type":"address"}],"name":"transferDeveloper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"traverseChains","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"trustedRemoteLookup","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

6080604052600180546001600160a01b0319908116734ce69fd760ad0c07490178f9a47863dc0358cccd17909155600280549091167344f750eb065596c150b3479b1df6957da300a332179055620557306021553480156200006057600080fd5b506040518060400160405280600b81526020016a54696e794461656d6f6e7360a81b815250604051806040016040528060078152602001662a24a72ca226a760c91b815250620000c963f851a44060e01b3060006200014f60201b62002dd8179092919060201c565b600154620000e9906303e1469160e61b906001600160a01b03166200028e565b6002546200010990638da5cb5b60e01b906001600160a01b03166200028e565b600154620001299063ca4b208b60e01b906001600160a01b03166200028e565b601862000137838262000572565b50601962000146828262000572565b50505062000791565b6001600160a01b03811662000176576040516282b42960e81b815260040160405180910390fd5b62000183838383620002af565b156200021057620001aa816001600160a01b031660146200030d60201b62002eae1760201c565b620001cb8360e01c63ffffffff1660046200030d60201b62002eae1760201c565b604051602001620001de92919062000671565b60408051601f1981840301815290829052630330dbc960e11b82526200020791600401620006d9565b60405180910390fd5b6001600160a01b0381166000818152602085815260408083206001600160e01b03198716808552908352928190208054600160ff1990911681179091558151938452918301939093528183015290517fc8bed56f8e046b5a3f2c2b2be85045ea5c972dc18ad669157957897b4d26e9f79181900360600190a1505050565b620002ab828260006200014f60201b62002dd8179092919060201c565b5050565b60006001600160a01b038216620002d8576040516282b42960e81b815260040160405180910390fd5b506001600160a01b03166000908152602092835260408082206001600160e01b03199390931682529190925290205460ff1690565b606060006200031e83600262000724565b6200032b90600262000746565b6001600160401b03811115620003455762000345620004cd565b6040519080825280601f01601f19166020018201604052801562000370576020820181803683370190505b509050600360fc1b816000815181106200038e576200038e62000761565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110620003c057620003c062000761565b60200101906001600160f81b031916908160001a9053506000620003e684600262000724565b620003f390600162000746565b90505b600181111562000475576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106200042b576200042b62000761565b1a60f81b82828151811062000444576200044462000761565b60200101906001600160f81b031916908160001a90535060049490941c936200046d8162000777565b9050620003f6565b508315620004c65760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640162000207565b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620004f857607f821691505b6020821081036200051957634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200056d57600081815260208120601f850160051c81016020861015620005485750805b601f850160051c820191505b81811015620005695782815560010162000554565b5050505b505050565b81516001600160401b038111156200058e576200058e620004cd565b620005a6816200059f8454620004e3565b846200051f565b602080601f831160018114620005de5760008415620005c55750858301515b600019600386901b1c1916600185901b17855562000569565b600085815260208120601f198616915b828110156200060f57888601518255948401946001909101908401620005ee565b50858210156200062e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60005b838110156200065b57818101518382015260200162000641565b838111156200066b576000848401525b50505050565b6a02634b1102937b632b99d160ad1b8152600083516200069981600b8501602088016200063e565b7101030b63932b0b23c903430b9903937b632960751b600b918401918201528351620006cd81601d8401602088016200063e565b01601d01949350505050565b6020815260008251806020840152620006fa8160408501602087016200063e565b601f01601f19169190910160400192915050565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156200074157620007416200070e565b500290565b600082198211156200075c576200075c6200070e565b500190565b634e487b7160e01b600052603260045260246000fd5b6000816200078957620007896200070e565b506000190190565b615e4880620007a16000396000f3fe6080604052600436106104815760003560e01c80637544671611610255578063c87b56dd11610144578063de02cde7116100c1578063eb8d72b711610085578063eb8d72b714610db9578063ecc7afa914610dd9578063ed88c68e14610dee578063f2fde38b14610df6578063fd0198e814610e16578063ff70fa4914610e36576104c1565b8063de02cde714610d3a578063e33b7de314610d5a578063e68b796114610d6f578063e8a3d48514610d84578063e985e9c514610d99576104c1565b8063d1deba1f11610108578063d1deba1f14610cbd578063d39ce77c14610cd0578063d4d714be14610cf0578063d792d2a014610d10578063d95ae16214610d25576104c1565b8063c87b56dd14610c16578063c9b298f114610c36578063ca4b208b14610c56578063ce7c2ac214610c74578063cf89fa0314610caa576104c1565b806395d89b41116101d2578063aac3f28111610196578063aac3f28114610ba2578063ad6d9c1714610bb7578063ae47b2da14610bcc578063b88d4fde14610be1578063ba7a86b814610c01576104c1565b806395d89b4114610b0d5780639852595c14610b225780639c12b17f14610b58578063a22cb46514610b6d578063a86ff96014610b8d576104c1565b80638da5cb5b116102195780638da5cb5b14610a2f5780638ee7491214610a4d578063938e3d7b14610ab85780639435267614610ad8578063943fb87214610aed576104c1565b806375446716146109b057806378c5939b146109c557806379ba5097146109da5780638b83209b146109ef5780638c7ea24b14610a0f576104c1565b8063312744261161037157806355f804b3116102ee57806364cb4edb116102b257806364cb4edb1461091b57806366278a6c1461093b57806370a082311461095b578063715018a61461097b5780637533d78814610990576104c1565b806355f804b3146108665780635ba5e9f0146108865780635c17e370146108c65780636149d871146108db5780636352211e146108fb576104c1565b806342966c681161033557806342966c68146107e757806344faded014610807578063475de12e1461082757806348e3bab21461083c5780634e71d92d14610851576104c1565b8063312744261461075d57806331e26cfd1461077d5780633400ec63146107925780633a98ef39146107b257806342842e0e146107c7576104c1565b806313af4035116103ff57806323b872dd116103c357806323b872dd146106cd57806326092b83146106ed5780632a55205a146107025780632bfcf0f2146107305780632ecd28ab14610745576104c1565b806313af40351461064e57806318160ddd1461066e57806318a66a7e146106835780631c37a822146106985780631efb051a146106b8576104c1565b8063081812fc11610446578063081812fc146105a3578063095ea7b3146105db5780630f0efdbc146105fb57806310ab94321461061b57806312065fe01461063b576104c1565b80621d3567146104f2578063018f007e1461051457806301ffc9a71461053c578063049157bb1461056c57806306fdde0314610581576104c1565b366104c1577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be77033346040516104b7929190614559565b60405180910390a1005b7f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be77033346040516104b7929190614559565b3480156104fe57600080fd5b5061051261050d366004614642565b610e56565b005b34801561052057600080fd5b506105296110e3565b6040519081526020015b60405180910390f35b34801561054857600080fd5b5061055c6105573660046146dc565b6110f4565b6040519015158152602001610533565b34801561057857600080fd5b50601054610529565b34801561058d57600080fd5b506105966112b3565b6040516105339190614751565b3480156105af57600080fd5b506105c36105be366004614764565b611345565b6040516001600160a01b039091168152602001610533565b3480156105e757600080fd5b506105126105f6366004614792565b6113cd565b34801561060757600080fd5b50610512610616366004614792565b6114dd565b34801561062757600080fd5b5061055c6106363660046147be565b611518565b34801561064757600080fd5b5047610529565b34801561065a57600080fd5b506105126106693660046147f7565b61152b565b34801561067a57600080fd5b506105296115f6565b34801561068f57600080fd5b50610512611601565b3480156106a457600080fd5b506105126106b3366004614642565b611638565b3480156106c457600080fd5b50600e54610529565b3480156106d957600080fd5b506105126106e8366004614814565b6116be565b3480156106f957600080fd5b506105126116f0565b34801561070e57600080fd5b5061072261071d366004614855565b611815565b604051610533929190614559565b34801561073c57600080fd5b5061051261184b565b34801561075157600080fd5b5060155460ff1661055c565b34801561076957600080fd5b50610512610778366004614764565b6118da565b34801561078957600080fd5b50610512611911565b34801561079e57600080fd5b506105126107ad3660046147f7565b611951565b3480156107be57600080fd5b50600654610529565b3480156107d357600080fd5b506105126107e2366004614814565b611987565b3480156107f357600080fd5b50610512610802366004614764565b6119a2565b34801561081357600080fd5b506105126108223660046147be565b6119db565b34801561083357600080fd5b50602154610529565b34801561084857600080fd5b50601754610529565b34801561085d57600080fd5b50610512611adc565b34801561087257600080fd5b50610512610881366004614877565b611c23565b34801561089257600080fd5b506108ad6108a13660046146dc565b506303e1469160e61b90565b6040516001600160e01b03199091168152602001610533565b3480156108d257600080fd5b50610529611d2d565b3480156108e757600080fd5b506105126108f63660046147f7565b611d46565b34801561090757600080fd5b506105c3610916366004614764565b611d85565b34801561092757600080fd5b506105126109363660046147f7565b611dfc565b34801561094757600080fd5b506105126109563660046146dc565b611e4d565b34801561096757600080fd5b506105296109763660046147f7565b611e7f565b34801561098757600080fd5b50610512611f06565b34801561099c57600080fd5b506105966109ab3660046148ab565b611f46565b3480156109bc57600080fd5b50610529611fdf565b3480156109d157600080fd5b50600f54610529565b3480156109e657600080fd5b50610512611ff1565b3480156109fb57600080fd5b506105c3610a0a366004614764565b612042565b348015610a1b57600080fd5b50610512610a2a366004614792565b612072565b348015610a3b57600080fd5b506002546001600160a01b03166105c3565b348015610a5957600080fd5b50610aa3610a683660046148c6565b601f60209081526000938452604080852084518086018401805192815290840195840195909520945292905282529020805460019091015482565b60408051928352602083019190915201610533565b348015610ac457600080fd5b50610512610ad3366004614877565b6120a9565b348015610ae457600080fd5b506105966120df565b348015610af957600080fd5b50610512610b08366004614764565b6120f1565b348015610b1957600080fd5b50610596612123565b348015610b2e57600080fd5b50610529610b3d3660046147f7565b6001600160a01b031660009081526009602052604090205490565b348015610b6457600080fd5b50610aa3612132565b348015610b7957600080fd5b50610512610b8836600461491c565b612150565b348015610b9957600080fd5b5061051261215b565b348015610bae57600080fd5b50600354610529565b348015610bc357600080fd5b5061051261219b565b348015610bd857600080fd5b506105126121db565b348015610bed57600080fd5b50610512610bfc36600461494f565b612210565b348015610c0d57600080fd5b50610512612242565b348015610c2257600080fd5b50610596610c31366004614764565b61235d565b348015610c4257600080fd5b50610512610c51366004614764565b6123ff565b348015610c6257600080fd5b506001546001600160a01b03166105c3565b348015610c8057600080fd5b50610529610c8f3660046147f7565b6001600160a01b031660009081526008602052604090205490565b610512610cb83660046149ae565b612551565b610512610ccb366004614a12565b6127c9565b348015610cdc57600080fd5b50610512610ceb3660046147f7565b612994565b348015610cfc57600080fd5b50610512610d0b366004614855565b6129d3565b348015610d1c57600080fd5b50610596612a40565b348015610d3157600080fd5b50600d54610529565b348015610d4657600080fd5b50610512610d553660046147be565b612a52565b348015610d6657600080fd5b50600754610529565b348015610d7b57600080fd5b50610529612b5f565b348015610d9057600080fd5b50610596612b6b565b348015610da557600080fd5b5061055c610db4366004614a9d565b612b7a565b348015610dc557600080fd5b50610512610dd4366004614abb565b612ba8565b348015610de557600080fd5b50610529612c26565b610512612c3f565b348015610e0257600080fd5b50610512610e113660046147f7565b612c7a565b348015610e2257600080fd5b50610512610e31366004614b0d565b612ccb565b348015610e4257600080fd5b50610512610e513660046147f7565b612d34565b601e546001600160a01b03163314610ee757604051630330dbc960e11b81526020600482015260546024820152600080516020615dd383398151915260448201527f6520646964206e6f7420636f6d652066726f6d2074686520656e64706f696e746064820152732c20796f75206661696c65642c204920776f6e2160601b608482015260a4015b60405180910390fd5b61ffff8416600090815260208052604090208054610f0490614ba0565b90508351141580610f43575061ffff84166000908152602080526040908190209051610f309190614c4d565b6040518091039020838051906020012014155b15610fcb57604051630330dbc960e11b815260206004820152605a6024820152600080516020615dd383398151915260448201527f6520646964206e6f7420636f6d652066726f6d2061207472757374656420636f60648201527f6e74726163742c20796f75206661696c65642c204920776f6e21000000000000608482015260a401610ede565b604051630e1bd41160e11b81523090631c37a82290610ff4908790879087908790600401614c59565b600060405180830381600087803b15801561100e57600080fd5b505af192505050801561101f575060015b6110dd576040518060400160405280825181526020018280519060200120815250601f60008661ffff1661ffff168152602001908152602001600020846040516110699190614ca2565b9081526040805191829003602090810183206001600160401b038716600090815290825291909120835181559201516001909201919091557fe6f254030bcb01ffd20558175c13fcaed6d1520be7becee4c961b65f79243b0d906110d4908690869086908690614c59565b60405180910390a15b50505050565b60006110ef600d613049565b905090565b60006001600160e01b0319821663b7d1e49960e01b148061112557506001600160e01b031982166303edf24760e01b145b8061114057506001600160e01b03198216633daba23f60e11b145b8061115b57506001600160e01b03198216630704183b60e11b145b8061117657506001600160e01b031982166302494e8b60e01b145b8061119157506001600160e01b0319821663152a902d60e11b145b806111ac57506001600160e01b0319821663131e54b760e01b145b806111c757506001600160e01b031982166323a87ba160e01b145b806111e257506001600160e01b0319821663253f8c7960e11b145b806111fd57506001600160e01b031982166329499a2560e01b145b8061121857506001600160e01b031982166317573c7360e21b145b8061123357506001600160e01b03198216632471dd5960e11b145b8061124e57506001600160e01b03198216634ba1182b60e11b145b8061126957506001600160e01b0319821663e8a3d48560e01b145b8061128457506001600160e01b0319821663938e3d7b60e01b145b8061129e57506001600160e01b03198216621d356760e01b145b806112ad57506112ad82613056565b92915050565b6060601880546112c290614ba0565b80601f01602080910402602001604051908101604052809291908181526020018280546112ee90614ba0565b801561133b5780601f106113105761010080835404028352916020019161133b565b820191906000526020600020905b81548152906001019060200180831161131e57829003601f168201915b5050505050905090565b6000611350826130a6565b6113b15760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610ede565b506000908152601c60205260409020546001600160a01b031690565b60006113d882611d85565b9050806001600160a01b0316836001600160a01b0316036114455760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610ede565b336001600160a01b038216148061146157506114618133612b7a565b6114ce5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776044820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b6064820152608401610ede565b6114d883836130c3565b505050565b6114ee63ca4b208b60e01b33613131565b61150a576040516282b42960e81b815260040160405180910390fd5b611514828261313e565b5050565b60006115248383613131565b9392505050565b61153c638da5cb5b60e01b33613131565b611558576040516282b42960e81b815260040160405180910390fd5b611569638da5cb5b60e01b82613131565b6115d457611581816001600160a01b03166014612eae565b611590638da5cb5b6004612eae565b61159b336014612eae565b6040516020016115ad93929190614cbe565b60408051601f1981840301815290829052630330dbc960e11b8252610ede91600401614751565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b60006110ef60165490565b61161263ca4b208b60e01b33613131565b61162e576040516282b42960e81b815260040160405180910390fd5b6116366132b8565b565b3330146116b257604051630330dbc960e11b815260206004820152604d6024820152600080516020615dd383398151915260448201527f6520646964206e6f7420636f6d6520696e7465726e616c6c792c20796f75206660648201526c61696c65642c204920776f6e2160981b608482015260a401610ede565b6110dd84848484613347565b6116c9335b8261337c565b6116e55760405162461bcd60e51b8152600401610ede90614d77565b6114d883838361343e565b6004546003546117009190614dde565b42101561173a57426004546003546117189190614dde565b60405163f3f82ac560e01b815260048101929092526024820152604401610ede565b6003546000036117bf57604051630330dbc960e11b815260206004820152604360248201527f54696d65436f703a20596f75277665206265656e2054696d6520436f7070656460448201527f2e204e474c206f6e6c794465762829206861736e277420736574207468652074606482015262696d6560e81b608482015260a401610ede565b600a6117ca33611e7f565b106117fc576117da336014612eae565b6117eb6117e633611e7f565b6135cc565b6040516020016115ad929190614df6565b61180d336118086136cc565b6136e5565b6116366136ff565b600b54600c546001600160a01b03909116906000906103e8906118389085614e7b565b6118429190614eb0565b90509250929050565b636525904560e11b61185d8133613131565b8061187457506118746303e1469160e61b33613131565b1561189c573361188b636525904560e11b82613717565b61151463ca4b208b60e01b82613723565b6118ab60e082901c6004612eae565b6118ba63f851a4406004612eae565b6118c5336014612eae565b6040516020016115ad93929190614ec4565b50565b6118eb638da5cb5b60e01b33613131565b611907576040516282b42960e81b815260040160405180910390fd5b6118d7308261372f565b636525904560e11b6119238133613131565b8061193a575061193a6303e1469160e61b33613131565b1561189c5733611514636525904560e11b82613717565b61196263ca4b208b60e01b33613131565b61197e576040516282b42960e81b815260040160405180910390fd5b6118d7816137c2565b6114d883838360405180602001604052806000815250612210565b6119ab336116c3565b6119ca576119ba336014612eae565b6040516020016115ad9190614f51565b6119d38161390a565b6118d7613993565b816119e68133613131565b806119fd57506119fd6303e1469160e61b33613131565b1561189c57631ada6fbb60e11b6001600160e01b0319841601611a6a576001600160a01b0382163314611a6a57611a35336014612eae565b611a4460e085901c6004612eae565b611a58846001600160a01b03166014612eae565b6040516020016115ad93929190614feb565b63392d1a5360e11b6001600160e01b0319841601611ad2576001600160a01b0382163314611ad257611a9d336014612eae565b611aac60e085901c6004612eae565b611ac0846001600160a01b03166014612eae565b6040516020016115ad939291906150a4565b6114d88383613717565b336000818152600860205260408120549003611b0d57611afd336014612eae565b6040516020016115ad91906150af565b600060075447611b1d9190614dde565b6001600160a01b0383166000908152600960209081526040808320546006546008909352908320549394509192611b549085614e7b565b611b5e9190614eb0565b611b689190615101565b905080600003611b8d57611b7d336014612eae565b6040516020016115ad9190615118565b6001600160a01b038316600090815260096020526040902054611bb1908290614dde565b6001600160a01b038416600090815260096020526040902055600754611bd8908290614dde565b600755611be5838261399d565b7fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b0568382604051611c16929190614559565b60405180910390a1505050565b611c3463ca4b208b60e01b33613131565b611c50576040516282b42960e81b815260040160405180910390fd5b600060228054611c5f90614ba0565b80601f0160208091040260200160405190810160405280929190818152602001828054611c8b90614ba0565b8015611cd85780601f10611cad57610100808354040283529160200191611cd8565b820191906000526020600020905b815481529060010190602001808311611cbb57829003601f168201915b505050505090508160229081611cee91906151ca565b507fd2877107a884510f506ed0bd833e6601f4344691e32a0ce4bcdedb1d9d9d28e1816022604051611d21929190615300565b60405180910390a15050565b6000611d39600d613ab6565b6010546110ef9190615101565b63ca4b208b60e01b611d588133613131565b80611d6f5750611d6f6303e1469160e61b33613131565b1561189c57611514636525904560e11b83613723565b6000818152601a60205260408120546001600160a01b0316806112ad5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610ede565b63ca4b208b60e01b611e0e8133613131565b80611e255750611e256303e1469160e61b33613131565b1561189c5733611e3c63ca4b208b60e01b84613723565b6114d863ca4b208b60e01b82613717565b80611e588133613131565b80611e6f5750611e6f6303e1469160e61b33613131565b1561189c57336114d88382613717565b60006001600160a01b038216611eea5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610ede565b506001600160a01b03166000908152601b602052604090205490565b638da5cb5b60e01b611f188133613131565b80611f2f5750611f2f6303e1469160e61b33613131565b1561189c5733611514638da5cb5b60e01b82613717565b602080526000908152604090208054611f5e90614ba0565b80601f0160208091040260200160405190810160405280929190818152602001828054611f8a90614ba0565b8015611fd75780601f10611fac57610100808354040283529160200191611fd7565b820191906000526020600020905b815481529060010190602001808311611fba57829003601f168201915b505050505081565b60006004546003546110ef9190614dde565b6346d2e5ad60e11b6120038133613131565b8061201a575061201a6303e1469160e61b33613131565b1561189c57336120316346d2e5ad60e11b82613717565b611514638da5cb5b60e01b82613723565b6000600a82815481106120575761205761532e565b6000918252602090912001546001600160a01b031692915050565b612083638da5cb5b60e01b33613131565b61209f576040516282b42960e81b815260040160405180910390fd5b611514828261372f565b6120ba63ca4b208b60e01b33613131565b6120d6576040516282b42960e81b815260040160405180910390fd5b6118d781613ac3565b6060600d60050180546112c290614ba0565b612102638da5cb5b60e01b33613131565b61211e576040516282b42960e81b815260040160405180910390fd5b602155565b6060601980546112c290614ba0565b6000806003546004546003546121489190614dde565b915091509091565b611514338383613b94565b6346d2e5ad60e11b61216d8133613131565b8061218457506121846303e1469160e61b33613131565b1561189c57336115146346d2e5ad60e11b82613717565b63ca4b208b60e01b6121ad8133613131565b806121c457506121c46303e1469160e61b33613131565b1561189c573361151463ca4b208b60e01b82613717565b6121ec638da5cb5b60e01b33613131565b612208576040516282b42960e81b815260040160405180910390fd5b611636613c5e565b61221a338361337c565b6122365760405162461bcd60e51b8152600401610ede90614d77565b6110dd84848484613cac565b61225363ca4b208b60e01b33613131565b61226f576040516282b42960e81b815260040160405180910390fd5b6000306001600160a01b0316635c17e3706040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d39190615344565b905060005b818110156115145761234d306001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612321573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612345919061535d565b6118086136cc565b612355613cdf565b6001016122d8565b6060612368826130a6565b61238557612375826135cc565b6040516020016115ad919061537a565b600061238f613cf3565b604080518082019091526005815264173539b7b760d91b60208201528151919250906123ca57604051806020016040528060008152506123f7565b816123d4856135cc565b826040516020016123e7939291906153e6565b6040516020818303038152906040525b949350505050565b60035442101561242f5760035460405163f3f82ac560e01b81524260048201526024810191909152604401610ede565b60045460035461243f9190614dde565b421061247857426004546003546124569190614dde565b6040516343c540ef60e01b815260048101929092526024820152604401610ede565b600461248333611e7f565b106124b057612493336014612eae565b61249f6117e633611e7f565b6040516020016115ad929190615429565b60028111156124de576124c4336014612eae565b6124cd826135cc565b6040516020016115ad9291906154ac565b60005b818110156115145760046124f433611e7f565b1061253557612504336014612eae565b61250d836135cc565b61252361251933611e7f565b6117e69086614dde565b6040516020016115ad93929190615530565b612541336118086136cc565b6125496136ff565b6001016124e1565b61255a81611d85565b6001600160a01b0316336001600160a01b03161461258a576040516282b42960e81b815260040160405180910390fd5b61ffff82166000908152602080526040902080546125a790614ba0565b905060000361262b57604051630330dbc960e11b815260206004820152604360248201527f546f6b656e3a204f6b2074686520446576206469646e2774207365742074686960448201527f7320706172616d617465722c20636f6e74616374204d6178466c6f774f322e656064820152623a341760e91b608482015260a401610ede565b6126348161390a565b61263c613993565b60003382604051602001612651929190614559565b60408051601f1981840301815290829052602154600160f01b60208401526022830152915060019060009060420160408051601f1981840301815290829052601e5463040a7bb160e41b83529092506000916001600160a01b03909116906340a7bb10906126cb90899030908990879089906004016155f1565b6040805180830381865afa1580156126e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270b9190615645565b5090503481111561274557612721336014612eae565b61272a346135cc565b612733836135cc565b6040516020016115ad93929190615669565b601e5461ffff87166000908152602080526040808220905162c5803160e81b81526001600160a01b039093169263c580310092349261278f928c928b913391908b906004016156eb565b6000604051808303818588803b1580156127a857600080fd5b505af11580156127bc573d6000803e3d6000fd5b5050505050505050505050565b61ffff85166000908152601f602052604080822090516127ea908790614ca2565b90815260408051602092819003830190206001600160401b038716600090815292529020600181015490915061288a57604051630330dbc960e11b815260206004820152604a6024820152600080516020615dd383398151915260448201527f652077617320616c72656164792065786563757465642c20796f75206661696c60648201526965642c204920776f6e2160b01b608482015260a401610ede565b8054821415806128b55750806001015483836040516128aa929190615752565b604051809103902014155b1561292557604051630330dbc960e11b815260206004820152604460248201819052600080516020615dd3833981519152908201527f6520776173206e6f742073746f7265642c20796f75206661696c65642c204920606482015263776f6e2160e01b608482015260a401610ede565b60008082556001820155604051630e1bd41160e11b81523090631c37a8229061295a908990899089908990899060040161578b565b600060405180830381600087803b15801561297457600080fd5b505af1158015612988573d6000803e3d6000fd5b50505050505050505050565b638da5cb5b60e01b6129a68133613131565b806129bd57506129bd6303e1469160e61b33613131565b1561189c576115146346d2e5ad60e11b83613723565b6129e463ca4b208b60e01b33613131565b612a00576040516282b42960e81b815260040160405180910390fd5b6003829055600481905560408051838152602081018390527f5ef81ff0fe28d74938986521db9f3fb5637cae3d1cec04a94b4a0d3a3b0fc3c49101611d21565b6060600d60040180546112c290614ba0565b81612a5d8133613131565b80612a745750612a746303e1469160e61b33613131565b1561189c57631ada6fbb60e11b6001600160e01b0319841601612ae757612aa2636525904560e11b33613131565b15612ae757612ab2336014612eae565b612ac160e085901c6004612eae565b612ad5846001600160a01b03166014612eae565b6040516020016115ad939291906157ca565b63392d1a5360e11b6001600160e01b0319841601612b5557612b106346d2e5ad60e11b33613131565b15612b5557612b20336014612eae565b612b2f60e085901c6004612eae565b612b43846001600160a01b03166014612eae565b6040516020016115ad9392919061584b565b6114d88383613723565b60006110ef600d613ab6565b6060600580546112c290614ba0565b6001600160a01b039182166000908152601d6020908152604080832093909416825291909152205460ff1690565b612bb963ca4b208b60e01b33613131565b612bd5576040516282b42960e81b815260040160405180910390fd5b61ffff831660009081526020805260409020612bf2828483615856565b507f93c35c217d799290d33244ef8905b63167d13758ab18343cd8055ed1b8056748838383604051611c1693929190615910565b6000612c32600d613049565b600f546110ef9190615101565b7f9a064d674ddc42ac41b38566457161f1ded37e65a59162da003dd25bcb057b603334604051612c70929190614559565b60405180910390a1565b638da5cb5b60e01b612c8c8133613131565b80612ca35750612ca36303e1469160e61b33613131565b1561189c5733612cba638da5cb5b60e01b84613723565b6114d8638da5cb5b60e01b82613717565b612cdc63ca4b208b60e01b33613131565b612cf8576040516282b42960e81b815260040160405180910390fd5b612d03868686613d02565b612d0d8383613d65565b601e80546001600160a01b0319166001600160a01b03929092169190911790555050505050565b612d4563ca4b208b60e01b33613131565b612d61576040516282b42960e81b815260040160405180910390fd5b612d7263ca4b208b60e01b82613131565b612db657612d8a816001600160a01b03166014612eae565b612d9963ca4b208b6004612eae565b612da4336014612eae565b6040516020016115ad9392919061592e565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038116612dfe576040516282b42960e81b815260040160405180910390fd5b612e09838383613d85565b15612e4257612e22816001600160a01b03166014612eae565b612e3160e084901c6004612eae565b6040516020016115ad9291906159ea565b6001600160a01b0381166000908152602084815260408083206001600160e01b03198616845290915290819020805460ff1916600190811790915590517fc8bed56f8e046b5a3f2c2b2be85045ea5c972dc18ad669157957897b4d26e9f791611c169185918591615a4e565b60606000612ebd836002614e7b565b612ec8906002614dde565b6001600160401b03811115612edf57612edf614589565b6040519080825280601f01601f191660200182016040528015612f09576020820181803683370190505b509050600360fc1b81600081518110612f2457612f2461532e565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110612f5357612f5361532e565b60200101906001600160f81b031916908160001a9053506000612f77846002614e7b565b612f82906001614dde565b90505b6001811115612ffa576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612fb657612fb661532e565b1a60f81b828281518110612fcc57612fcc61532e565b60200101906001600160f81b031916908160001a90535060049490941c93612ff381615a7b565b9050612f85565b5083156115245760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610ede565b60006112ad826006015490565b60006001600160e01b031982166380ac58cd60e01b148061308757506001600160e01b03198216635b5e139f60e01b145b806112ad57506301ffc9a760e01b6001600160e01b03198316146112ad565b6000908152601a60205260409020546001600160a01b0316151590565b6000818152601c6020526040902080546001600160a01b0319166001600160a01b03841690811790915581906130f882611d85565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000611524818484613d85565b6001600160a01b03821661316557604051630330dbc960e11b8152600401610ede90615a92565b806000036131b657604051630330dbc960e11b815260206004820152601d60248201527f5061796d656e7453706c69747465723a207368617265732061726520300000006044820152606401610ede565b6001600160a01b0382166000908152600860205260409020541561321b576131e8826001600160a01b03166014612eae565b6001600160a01b03831660009081526008602052604090205461320a906135cc565b6040516020016115ad929190615ade565b600a8054600181019091557fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80180546001600160a01b0319166001600160a01b0384169081179091556000908152600860205260409020819055600654613283908290614dde565b6006556040517f40c340f65e17194d14ddddb073d3c9f888e3cb52b5aae0c6c7706b4fbc905fac90611d219084908490614559565b600a5460005b81811015613306576000600a82815481106132db576132db61532e565b60009182526020808320909101546001600160a01b03168252600890526040812055506001016132be565b50600660009055600a600061331b9190614527565b6040517f3407fd525bf6581e0ae8e3a3636bd90d02112bea34d66802743c28ced73f910e90600090a150565b6000808280602001905181019061335e9190615b58565b9150915061336c82826136e5565b613374613709565b505050505050565b6000613387826130a6565b6133e85760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610ede565b60006133f383611d85565b9050806001600160a01b0316846001600160a01b0316148061342e5750836001600160a01b031661342384611345565b6001600160a01b0316145b806123f757506123f78185612b7a565b826001600160a01b031661345182611d85565b6001600160a01b0316146134b95760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610ede565b6001600160a01b03821661351b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610ede565b6135266000826130c3565b6001600160a01b0383166000908152601b6020526040812080546001929061354f908490615101565b90915550506001600160a01b0382166000908152601b6020526040812080546001929061357d908490614dde565b90915550506000818152601a602052604080822080546001600160a01b0319166001600160a01b038681169182179092559151849391871691600080516020615df383398151915291a4505050565b6060816000036135f35750506040805180820190915260018152600360fc1b602082015290565b8160005b811561361d578061360781615b86565b91506136169050600a83614eb0565b91506135f7565b6000816001600160401b0381111561363757613637614589565b6040519080825280601f01601f191660200182016040528015613661576020820181803683370190505b5090505b84156123f757613676600183615101565b9150613683600a86615b9f565b61368e906030614dde565b60f81b8183815181106136a3576136a361532e565b60200101906001600160f81b031916908160001a9053506136c5600a86614eb0565b9450613665565b60006136d8600d613de2565b6017546110ef9190614dde565b611514828260405180602001604052806000815250613e0d565b613709600d613e40565b611636601680546001019055565b61151460008383613e50565b61151460008383612dd8565b6103e88110158061373e575080155b156137685761374e336014612eae565b613757826135cc565b6040516020016115ad929190615bb3565b600b80546001600160a01b0319166001600160a01b038416908117909155600c8290556040805183815260208101929092527f184520f1b2fcf99836992b9a6b987afc0e4867f26a00ef438c654318763fe1e39101611d21565b6001600160a01b0381166137e957604051630330dbc960e11b8152600401610ede90615a92565b60006137f482613f1d565b600a805491925060009161380a90600190615101565b8154811061381a5761381a61532e565b600091825260209091200154600a80546001600160a01b0390921692508291849081106138495761384961532e565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600a80548061388857613888615c42565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0385168252600890526040812080549190556006546138d5908290615101565b6006556040517f104b8837ec12e86f303ac7ce5e3bf20c6790f843fabd7451943f3390fc8376cb906110d49086908490614559565b600061391582611d85565b90506139226000836130c3565b6001600160a01b0381166000908152601b6020526040812080546001929061394b908490615101565b90915550506000828152601a602052604080822080546001600160a01b0319169055518391906001600160a01b03841690600080516020615df3833981519152908390a45050565b6116366016613f77565b804710156139ed5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610ede565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613a3a576040519150601f19603f3d011682016040523d82523d6000602084013e613a3f565b606091505b50509050806114d85760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610ede565b60006112ad826007015490565b600060058054613ad290614ba0565b80601f0160208091040260200160405190810160405280929190818152602001828054613afe90614ba0565b8015613b4b5780601f10613b2057610100808354040283529160200191613b4b565b820191906000526020600020905b815481529060010190602001808311613b2e57829003601f168201915b505050505090508160059081613b6191906151ca565b507f17f75bb1e35b058872a221a8c16d8b3e39eacbda214fd7da20f192b9291ecc3b816005604051611d21929190615300565b816001600160a01b0316836001600160a01b031603613bf15760405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b6044820152606401610ede565b6001600160a01b038381166000818152601d6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b600b80546001600160a01b03191690556000600c8190556040805182815260208101929092527f184520f1b2fcf99836992b9a6b987afc0e4867f26a00ef438c654318763fe1e39101612c70565b613cb784848461343e565b613cc384848484613fe0565b6110dd5760405162461bcd60e51b8152600401610ede90615c58565b613ce9600d613e40565b613709600d6140e1565b6060602280546112c290614ba0565b6017839055613d12600d836140f1565b613d1d600d82614131565b7f0e59e2733e85d32179b3dffa920faef60cc432823591194c4e5f0ac15db3dcec8284613d4a8183614dde565b60408051938452602084019290925290820152606001611c16565b613d70600d82614171565b613d7b600d83614245565b611514600d614319565b60006001600160a01b038216613dad576040516282b42960e81b815260040160405180910390fd5b506001600160a01b03166000908152602092835260408082206001600160e01b03199390931682529190925290205460ff1690565b60008160020154613df4836006015490565b8360010154613e039190614dde565b6112ad9190615b9f565b613e178383614406565b613e246000848484613fe0565b6114d85760405162461bcd60e51b8152600401610ede90615c58565b6118d78160060180546001019055565b6001600160a01b038116613e76576040516282b42960e81b815260040160405180910390fd5b613e81838383613d85565b613eb957613e99816001600160a01b03166014612eae565b613ea860e084901c6004612eae565b6040516020016115ad929190615caa565b6001600160a01b0381166000908152602084815260408083206001600160e01b031986168452909152808220805460ff19169055517fc8bed56f8e046b5a3f2c2b2be85045ea5c972dc18ad669157957897b4d26e9f791611c169185918591615a4e565b600a54600090815b81811015613f7057836001600160a01b0316600a8281548110613f4a57613f4a61532e565b6000918252602090912001546001600160a01b031603613f68578092505b600101613f25565b5050919050565b80546000819003613fd557604051630330dbc960e11b815260206004820152602160248201527f436f756e7465727356323a204e6f206e656761746976657320696e2075696e746044820152607360f81b6064820152608401610ede565b508054600019019055565b60006001600160a01b0384163b156140d657604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290614024903390899088908890600401615d10565b6020604051808303816000875af192505050801561405f575060408051601f3d908101601f1916820190925261405c91810190615d4d565b60015b6140bc573d80801561408d576040519150601f19603f3d011682016040523d82523d6000602084013e614092565b606091505b5080516000036140b45760405162461bcd60e51b8152600401610ede90615c58565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506123f7565b506001949350505050565b6118d78160070180546001019055565b6002820180549082905560408051838152602081018390527fe26aa1327aec5016c96875498202eebb896e3c2a79cd281ff17ed5bde4e545db9101611c16565b6003820180549082905560408051838152602081018390527fef40c7688f323b7ccad323bec82bfee336d16c0939c46bee1f3e5df296dadde39101611c16565b600082600501805461418290614ba0565b80601f01602080910402602001604051908101604052809291908181526020018280546141ae90614ba0565b80156141fb5780601f106141d0576101008083540402835291602001916141fb565b820191906000526020600020905b8154815290600101906020018083116141de57829003601f168201915b505050505090508183600501908161421391906151ca565b507f5769620297eb5047703c0ba55dd28b8ea50ba49818a91a43217fedce8eb69a308282604051611c16929190615d6a565b600082600401805461425690614ba0565b80601f016020809104026020016040519081016040528092919081815260200182805461428290614ba0565b80156142cf5780601f106142a4576101008083540402835291602001916142cf565b820191906000526020600020905b8154815290600101906020018083116142b257829003601f168201915b50505050509050818360040190816142e791906151ca565b507f7058c986a2931f38a70c3f70689d1f2bb75efb4d0082511082db4b2d40492b4f8282604051611c16929190615d6a565b806002015460000361438257604051630330dbc960e11b815260206004820152602b60248201527f50737565646f52616e646f6d204c69623a204d6178696d756d2043617061636960448201526a7479206e6f74207365742160a81b6064820152608401610ede565b806002015442338360040184600501446040516020016143a6959493929190615d8f565b6040516020818303038152906040528051906020012060001c6143c99190615b9f565b600182018190556040519081527f74d17dde2d5b61215fe87f93cddcd2470527e8b0381734da7d0dfeb3fcf6f8179060200160405180910390a150565b6001600160a01b03821661445c5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610ede565b614465816130a6565b156144b25760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610ede565b6001600160a01b0382166000908152601b602052604081208054600192906144db908490614dde565b90915550506000818152601a602052604080822080546001600160a01b0319166001600160a01b0386169081179091559051839290600080516020615df3833981519152908290a45050565b50805460008255906000526020600020908101906118d791905b808211156145555760008155600101614541565b5090565b6001600160a01b03929092168252602082015260400190565b803561ffff8116811461458457600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126145b057600080fd5b81356001600160401b03808211156145ca576145ca614589565b604051601f8301601f19908116603f011681019082821181831017156145f2576145f2614589565b8160405283815286602085880101111561460b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b80356001600160401b038116811461458457600080fd5b6000806000806080858703121561465857600080fd5b61466185614572565b935060208501356001600160401b038082111561467d57600080fd5b6146898883890161459f565b94506146976040880161462b565b935060608701359150808211156146ad57600080fd5b506146ba8782880161459f565b91505092959194509250565b6001600160e01b0319811681146118d757600080fd5b6000602082840312156146ee57600080fd5b8135611524816146c6565b60005b838110156147145781810151838201526020016146fc565b838111156110dd5750506000910152565b6000815180845261473d8160208601602086016146f9565b601f01601f19169290920160200192915050565b6020815260006115246020830184614725565b60006020828403121561477657600080fd5b5035919050565b6001600160a01b03811681146118d757600080fd5b600080604083850312156147a557600080fd5b82356147b08161477d565b946020939093013593505050565b600080604083850312156147d157600080fd5b82356147dc816146c6565b915060208301356147ec8161477d565b809150509250929050565b60006020828403121561480957600080fd5b81356115248161477d565b60008060006060848603121561482957600080fd5b83356148348161477d565b925060208401356148448161477d565b929592945050506040919091013590565b6000806040838503121561486857600080fd5b50508035926020909101359150565b60006020828403121561488957600080fd5b81356001600160401b0381111561489f57600080fd5b6123f78482850161459f565b6000602082840312156148bd57600080fd5b61152482614572565b6000806000606084860312156148db57600080fd5b6148e484614572565b925060208401356001600160401b038111156148ff57600080fd5b61490b8682870161459f565b925050604084013590509250925092565b6000806040838503121561492f57600080fd5b823561493a8161477d565b9150602083013580151581146147ec57600080fd5b6000806000806080858703121561496557600080fd5b84356149708161477d565b935060208501356149808161477d565b92506040850135915060608501356001600160401b038111156149a257600080fd5b6146ba8782880161459f565b600080604083850312156149c157600080fd5b6147b083614572565b60008083601f8401126149dc57600080fd5b5081356001600160401b038111156149f357600080fd5b602083019150836020828501011115614a0b57600080fd5b9250929050565b600080600080600060808688031215614a2a57600080fd5b614a3386614572565b945060208601356001600160401b0380821115614a4f57600080fd5b614a5b89838a0161459f565b9550614a696040890161462b565b94506060880135915080821115614a7f57600080fd5b50614a8c888289016149ca565b969995985093965092949392505050565b60008060408385031215614ab057600080fd5b82356147dc8161477d565b600080600060408486031215614ad057600080fd5b614ad984614572565b925060208401356001600160401b03811115614af457600080fd5b614b00868287016149ca565b9497909650939450505050565b60008060008060008060c08789031215614b2657600080fd5b86359550602087013594506040870135935060608701356001600160401b0380821115614b5257600080fd5b614b5e8a838b0161459f565b94506080890135915080821115614b7457600080fd5b50614b8189828a0161459f565b92505060a0870135614b928161477d565b809150509295509295509295565b600181811c90821680614bb457607f821691505b602082108103614bd457634e487b7160e01b600052602260045260246000fd5b50919050565b60008154614be781614ba0565b60018281168015614bff5760018114614c1457614c43565b60ff1984168752821515830287019450614c43565b8560005260208060002060005b85811015614c3a5781548a820152908401908201614c21565b50505082870194505b5050505092915050565b60006115248284614bda565b61ffff85168152608060208201526000614c766080830186614725565b6001600160401b03851660408401528281036060840152614c978185614725565b979650505050505050565b60008251614cb48184602087016146f9565b9190910192915050565b76026b0bc20b1b1b2b9b99d102a34329030b2323932b9b99604d1b815260008451614cf08160178501602089016146f9565b7f206973206e6f7420616e206f776e657220616e6420646f6573206e6f742068616017918401918201526b03b32903a3432903937b632960a51b60378201528451614d428160438401602089016146f9565b660103a3432b932960cd1b604392909101918201528351614d6a81604a8401602088016146f9565b01604a0195945050505050565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60008219821115614df157614df1614dc8565b500190565b6902a37b5b2b71d1027b5960b51b815260008351614e1b81600a8501602088016146f9565b690103cb7ba903430bb32960b51b600a918401918201528351614e458160148401602088016146f9565b7f206d6178696d756d20617420746869732074696d652069732031302e0000000060149290910191820152603001949350505050565b6000816000190483118215151615614e9557614e95614dc8565b500290565b634e487b7160e01b600052601260045260246000fd5b600082614ebf57614ebf614e9a565b500490565b7f4d61784163636573733a20596f75206172652061206e6f7420616e2000000000815260008451614efc81601c8501602089016146f9565b80830190506301037b9160e51b601c8201528451614f218160208401602089016146f9565b808201915050600160fd1b60208201528351614f448160218401602088016146f9565b0160210195945050505050565b6f022a9219b9918a13ab93730b136329d160851b815260008251614f7c8160108501602087016146f9565b7f206973206e6f74206f776e6572206e6f7220617070726f7665640000000000006010939091019283015250602a01919050565b7f4d61784163636573733a20596f752061726520612070656e64696e6720646576815268032b637b832b91414960bd1b602082015260290190565b6000614ff682614fb0565b8551615006818360208a016146f9565b780103cb7ba9031b0b7103737ba103932bb37b5b2903937b6329603d1b9101908152845161503b8160198401602089016146f9565b630103a37960e51b60199290910191820152835161506081601d8401602088016146f9565b01601d0195945050505050565b7f4d61784163636573733a20596f752061726520612070656e64696e67206f776e815264032b91414960dd1b602082015260250190565b6000614ff68261506d565b7002830bcb6b2b73a29b83634ba3a32b91d1607d1b8152600082516150db8160118501602087016146f9565b6e103430b99037379039b430b932b99760891b6011939091019283015250602001919050565b60008282101561511357615113614dc8565b500390565b7002830bcb6b2b73a29b83634ba3a32b91d1607d1b8152600082516151448160118501602087016146f9565b731034b9903737ba10323ab2903830bcb6b2b73a1760611b6011939091019283015250602501919050565b601f8211156114d857600081815260208120601f850160051c810160208610156151965750805b601f850160051c820191505b81811015613374578281556001016151a2565b600019600383901b1c191660019190911b1790565b81516001600160401b038111156151e3576151e3614589565b6151f7816151f18454614ba0565b8461516f565b602080601f83116001811461522657600084156152145750858301515b61521e85826151b5565b865550613374565b600085815260208120601f198616915b8281101561525557888601518255948401946001909101908401615236565b50858210156152735787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000815461529081614ba0565b8085526020600183811680156152ad57600181146152c7576152f5565b60ff1985168884015283151560051b8801830195506152f5565b866000528260002060005b858110156152ed5781548a82018601529083019084016152d2565b890184019650505b505050505092915050565b6040815260006153136040830185614725565b82810360208401526153258185615283565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561535657600080fd5b5051919050565b60006020828403121561536f57600080fd5b81516115248161477d565b7f4552433732314d657461646174613a2055524920717565727920666f722000008152600082516153b281601e8501602087016146f9565b7f2072657475726e73206e6f6e6578697374656e7420746f6b656e000000000000601e939091019283015250603801919050565b600084516153f88184602089016146f9565b84519083019061540c8183602089016146f9565b845191019061541f8183602088016146f9565b0195945050505050565b6902a37b5b2b71d1027b5960b51b81526000835161544e81600a8501602088016146f9565b690103cb7ba903430bb32960b51b600a9184019182015283516154788160148401602088016146f9565b7a1036b0bc34b6bab69030ba103a3434b9903a34b6b29034b9901a1760291b60149290910191820152602f01949350505050565b6902a37b5b2b71d1027b5960b51b8152600083516154d181600a8501602088016146f9565b730103cb7ba903bb0b73a32b2103a379036b4b73a160651b600a91840191820152835161550581601e8401602088016146f9565b7110191037b9103632b9b990383632b0b9b29760711b601e9290910191820152603001949350505050565b6902a37b5b2b71d1027b5960b51b81526000845161555581600a8501602089016146f9565b730103cb7ba903bb0b73a32b2103a379036b4b73a160651b600a91840191820152845161558981601e8401602089016146f9565b710103a3430ba10383aba39903cb7ba9030ba160751b601e929091019182015283516155bc8160308401602088016146f9565b7a1036b0bc34b6bab69030ba103a3434b9903a34b6b29034b9901a1760291b60309290910191820152604b0195945050505050565b61ffff861681526001600160a01b038516602082015260a06040820181905260009061561f90830186614725565b841515606084015282810360808401526156398185614725565b98975050505050505050565b6000806040838503121561565857600080fd5b505080516020909101519092909150565b6602a37b5b2b71d160cd1b81526000845161568b8160078501602089016146f9565b6501039b2b73a160d51b60079184019182015284516156b181600d8401602089016146f9565b6b01034b739ba32b0b21037b3160a51b600d929091019182015283516156de8160198401602088016146f9565b0160190195945050505050565b61ffff8716815260c06020820152600061570860c0830188615283565b828103604084015261571a8188614725565b6001600160a01b0387811660608601528616608085015283810360a085015290506157458185614725565b9998505050505050505050565b8183823760009101908152919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff861681526080602082015260006157a86080830187614725565b6001600160401b03861660408401528281036060840152615639818587615762565b60006157d582614fb0565b85516157e5818360208a016146f9565b770103cb7ba9031b0b7103737ba1033b930b73a103937b632960451b910190815284516158198160188401602089016146f9565b630103a37960e51b60189290910191820152835161583e81601c8401602088016146f9565b01601c0195945050505050565b60006157d58261506d565b6001600160401b0383111561586d5761586d614589565b6158818361587b8354614ba0565b8361516f565b6000601f8411600181146158af576000851561589d5750838201355b6158a786826151b5565b845550615909565b600083815260209020601f19861690835b828110156158e057868501358255602094850194600190920191016158c0565b50868210156158fd5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b61ffff84168152604060208201526000615325604083018486615762565b76026b0bc20b1b1b2b9b99d102a34329030b2323932b9b99604d1b8152600084516159608160178501602089016146f9565b7f206973206e6f74206120646576656c6f70657220616e6420646f6573206e6f746017918401918201526e0103430bb32903a3432903937b6329608d1b603782015284516159b58160468401602089016146f9565b660103a3432b932960cd1b6046929091019182015283516159dd81604d8401602088016146f9565b01604d0195945050505050565b6a02634b1102937b632b99d160ad1b815260008351615a1081600b8501602088016146f9565b7101030b63932b0b23c903430b9903937b632960751b600b918401918201528351615a4281601d8401602088016146f9565b01601d01949350505050565b6001600160e01b03199390931683526001600160a01b039190911660208301521515604082015260600190565b600081615a8a57615a8a614dc8565b506000190190565b6020808252602c908201527f5061796d656e7453706c69747465723a206163636f756e74206973207468652060408201526b7a65726f206164647265737360a01b606082015260800190565b7002830bcb6b2b73a29b83634ba3a32b91d1607d1b815260008351615b0a8160118501602088016146f9565b6c01030b63932b0b23c903430b99609d1b6011918401918201528351615b3781601e8401602088016146f9565b671039b430b932b99760c11b601e9290910191820152602601949350505050565b60008060408385031215615b6b57600080fd5b8251615b768161477d565b6020939093015192949293505050565b600060018201615b9857615b98614dc8565b5060010190565b600082615bae57615bae614e9a565b500690565b72022a921991c9c18a1b7b63632b1ba34b7b71d1606d1b815260008351615be18160138501602088016146f9565b6a01039bab136b4ba3a32b2160ad1b6013918401918201528351615c0c81601e8401602088016146f9565b7f20616e642074686174206973206f7574206f6620626f756e6473210000000000601e9290910191820152603901949350505050565b634e487b7160e01b600052603160045260246000fd5b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6a02634b1102937b632b99d160ad1b815260008351615cd081600b8501602088016146f9565b730103237b2b9903737ba103430bb32903937b632960651b600b918401918201528351615d0481601f8401602088016146f9565b01601f01949350505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615d4390830184614725565b9695505050505050565b600060208284031215615d5f57600080fd5b8151611524816146c6565b604081526000615d7d6040830185614725565b82810360208401526153258185614725565b8581526bffffffffffffffffffffffff198560601b1660208201526000615dc2615dbc6034840187614bda565b85614bda565b928352505060200194935050505056fe4e6f6e626c6f636b696e6752656365697665723a2054686973206d6573736167ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212203141b7ea1d69d1dba90a4aa8c8ceb739713a9cc2ac8d184bde9f9da53c19d3bb64736f6c634300080f0033

Deployed Bytecode

0x6080604052600436106104815760003560e01c80637544671611610255578063c87b56dd11610144578063de02cde7116100c1578063eb8d72b711610085578063eb8d72b714610db9578063ecc7afa914610dd9578063ed88c68e14610dee578063f2fde38b14610df6578063fd0198e814610e16578063ff70fa4914610e36576104c1565b8063de02cde714610d3a578063e33b7de314610d5a578063e68b796114610d6f578063e8a3d48514610d84578063e985e9c514610d99576104c1565b8063d1deba1f11610108578063d1deba1f14610cbd578063d39ce77c14610cd0578063d4d714be14610cf0578063d792d2a014610d10578063d95ae16214610d25576104c1565b8063c87b56dd14610c16578063c9b298f114610c36578063ca4b208b14610c56578063ce7c2ac214610c74578063cf89fa0314610caa576104c1565b806395d89b41116101d2578063aac3f28111610196578063aac3f28114610ba2578063ad6d9c1714610bb7578063ae47b2da14610bcc578063b88d4fde14610be1578063ba7a86b814610c01576104c1565b806395d89b4114610b0d5780639852595c14610b225780639c12b17f14610b58578063a22cb46514610b6d578063a86ff96014610b8d576104c1565b80638da5cb5b116102195780638da5cb5b14610a2f5780638ee7491214610a4d578063938e3d7b14610ab85780639435267614610ad8578063943fb87214610aed576104c1565b806375446716146109b057806378c5939b146109c557806379ba5097146109da5780638b83209b146109ef5780638c7ea24b14610a0f576104c1565b8063312744261161037157806355f804b3116102ee57806364cb4edb116102b257806364cb4edb1461091b57806366278a6c1461093b57806370a082311461095b578063715018a61461097b5780637533d78814610990576104c1565b806355f804b3146108665780635ba5e9f0146108865780635c17e370146108c65780636149d871146108db5780636352211e146108fb576104c1565b806342966c681161033557806342966c68146107e757806344faded014610807578063475de12e1461082757806348e3bab21461083c5780634e71d92d14610851576104c1565b8063312744261461075d57806331e26cfd1461077d5780633400ec63146107925780633a98ef39146107b257806342842e0e146107c7576104c1565b806313af4035116103ff57806323b872dd116103c357806323b872dd146106cd57806326092b83146106ed5780632a55205a146107025780632bfcf0f2146107305780632ecd28ab14610745576104c1565b806313af40351461064e57806318160ddd1461066e57806318a66a7e146106835780631c37a822146106985780631efb051a146106b8576104c1565b8063081812fc11610446578063081812fc146105a3578063095ea7b3146105db5780630f0efdbc146105fb57806310ab94321461061b57806312065fe01461063b576104c1565b80621d3567146104f2578063018f007e1461051457806301ffc9a71461053c578063049157bb1461056c57806306fdde0314610581576104c1565b366104c1577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be77033346040516104b7929190614559565b60405180910390a1005b7f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be77033346040516104b7929190614559565b3480156104fe57600080fd5b5061051261050d366004614642565b610e56565b005b34801561052057600080fd5b506105296110e3565b6040519081526020015b60405180910390f35b34801561054857600080fd5b5061055c6105573660046146dc565b6110f4565b6040519015158152602001610533565b34801561057857600080fd5b50601054610529565b34801561058d57600080fd5b506105966112b3565b6040516105339190614751565b3480156105af57600080fd5b506105c36105be366004614764565b611345565b6040516001600160a01b039091168152602001610533565b3480156105e757600080fd5b506105126105f6366004614792565b6113cd565b34801561060757600080fd5b50610512610616366004614792565b6114dd565b34801561062757600080fd5b5061055c6106363660046147be565b611518565b34801561064757600080fd5b5047610529565b34801561065a57600080fd5b506105126106693660046147f7565b61152b565b34801561067a57600080fd5b506105296115f6565b34801561068f57600080fd5b50610512611601565b3480156106a457600080fd5b506105126106b3366004614642565b611638565b3480156106c457600080fd5b50600e54610529565b3480156106d957600080fd5b506105126106e8366004614814565b6116be565b3480156106f957600080fd5b506105126116f0565b34801561070e57600080fd5b5061072261071d366004614855565b611815565b604051610533929190614559565b34801561073c57600080fd5b5061051261184b565b34801561075157600080fd5b5060155460ff1661055c565b34801561076957600080fd5b50610512610778366004614764565b6118da565b34801561078957600080fd5b50610512611911565b34801561079e57600080fd5b506105126107ad3660046147f7565b611951565b3480156107be57600080fd5b50600654610529565b3480156107d357600080fd5b506105126107e2366004614814565b611987565b3480156107f357600080fd5b50610512610802366004614764565b6119a2565b34801561081357600080fd5b506105126108223660046147be565b6119db565b34801561083357600080fd5b50602154610529565b34801561084857600080fd5b50601754610529565b34801561085d57600080fd5b50610512611adc565b34801561087257600080fd5b50610512610881366004614877565b611c23565b34801561089257600080fd5b506108ad6108a13660046146dc565b506303e1469160e61b90565b6040516001600160e01b03199091168152602001610533565b3480156108d257600080fd5b50610529611d2d565b3480156108e757600080fd5b506105126108f63660046147f7565b611d46565b34801561090757600080fd5b506105c3610916366004614764565b611d85565b34801561092757600080fd5b506105126109363660046147f7565b611dfc565b34801561094757600080fd5b506105126109563660046146dc565b611e4d565b34801561096757600080fd5b506105296109763660046147f7565b611e7f565b34801561098757600080fd5b50610512611f06565b34801561099c57600080fd5b506105966109ab3660046148ab565b611f46565b3480156109bc57600080fd5b50610529611fdf565b3480156109d157600080fd5b50600f54610529565b3480156109e657600080fd5b50610512611ff1565b3480156109fb57600080fd5b506105c3610a0a366004614764565b612042565b348015610a1b57600080fd5b50610512610a2a366004614792565b612072565b348015610a3b57600080fd5b506002546001600160a01b03166105c3565b348015610a5957600080fd5b50610aa3610a683660046148c6565b601f60209081526000938452604080852084518086018401805192815290840195840195909520945292905282529020805460019091015482565b60408051928352602083019190915201610533565b348015610ac457600080fd5b50610512610ad3366004614877565b6120a9565b348015610ae457600080fd5b506105966120df565b348015610af957600080fd5b50610512610b08366004614764565b6120f1565b348015610b1957600080fd5b50610596612123565b348015610b2e57600080fd5b50610529610b3d3660046147f7565b6001600160a01b031660009081526009602052604090205490565b348015610b6457600080fd5b50610aa3612132565b348015610b7957600080fd5b50610512610b8836600461491c565b612150565b348015610b9957600080fd5b5061051261215b565b348015610bae57600080fd5b50600354610529565b348015610bc357600080fd5b5061051261219b565b348015610bd857600080fd5b506105126121db565b348015610bed57600080fd5b50610512610bfc36600461494f565b612210565b348015610c0d57600080fd5b50610512612242565b348015610c2257600080fd5b50610596610c31366004614764565b61235d565b348015610c4257600080fd5b50610512610c51366004614764565b6123ff565b348015610c6257600080fd5b506001546001600160a01b03166105c3565b348015610c8057600080fd5b50610529610c8f3660046147f7565b6001600160a01b031660009081526008602052604090205490565b610512610cb83660046149ae565b612551565b610512610ccb366004614a12565b6127c9565b348015610cdc57600080fd5b50610512610ceb3660046147f7565b612994565b348015610cfc57600080fd5b50610512610d0b366004614855565b6129d3565b348015610d1c57600080fd5b50610596612a40565b348015610d3157600080fd5b50600d54610529565b348015610d4657600080fd5b50610512610d553660046147be565b612a52565b348015610d6657600080fd5b50600754610529565b348015610d7b57600080fd5b50610529612b5f565b348015610d9057600080fd5b50610596612b6b565b348015610da557600080fd5b5061055c610db4366004614a9d565b612b7a565b348015610dc557600080fd5b50610512610dd4366004614abb565b612ba8565b348015610de557600080fd5b50610529612c26565b610512612c3f565b348015610e0257600080fd5b50610512610e113660046147f7565b612c7a565b348015610e2257600080fd5b50610512610e31366004614b0d565b612ccb565b348015610e4257600080fd5b50610512610e513660046147f7565b612d34565b601e546001600160a01b03163314610ee757604051630330dbc960e11b81526020600482015260546024820152600080516020615dd383398151915260448201527f6520646964206e6f7420636f6d652066726f6d2074686520656e64706f696e746064820152732c20796f75206661696c65642c204920776f6e2160601b608482015260a4015b60405180910390fd5b61ffff8416600090815260208052604090208054610f0490614ba0565b90508351141580610f43575061ffff84166000908152602080526040908190209051610f309190614c4d565b6040518091039020838051906020012014155b15610fcb57604051630330dbc960e11b815260206004820152605a6024820152600080516020615dd383398151915260448201527f6520646964206e6f7420636f6d652066726f6d2061207472757374656420636f60648201527f6e74726163742c20796f75206661696c65642c204920776f6e21000000000000608482015260a401610ede565b604051630e1bd41160e11b81523090631c37a82290610ff4908790879087908790600401614c59565b600060405180830381600087803b15801561100e57600080fd5b505af192505050801561101f575060015b6110dd576040518060400160405280825181526020018280519060200120815250601f60008661ffff1661ffff168152602001908152602001600020846040516110699190614ca2565b9081526040805191829003602090810183206001600160401b038716600090815290825291909120835181559201516001909201919091557fe6f254030bcb01ffd20558175c13fcaed6d1520be7becee4c961b65f79243b0d906110d4908690869086908690614c59565b60405180910390a15b50505050565b60006110ef600d613049565b905090565b60006001600160e01b0319821663b7d1e49960e01b148061112557506001600160e01b031982166303edf24760e01b145b8061114057506001600160e01b03198216633daba23f60e11b145b8061115b57506001600160e01b03198216630704183b60e11b145b8061117657506001600160e01b031982166302494e8b60e01b145b8061119157506001600160e01b0319821663152a902d60e11b145b806111ac57506001600160e01b0319821663131e54b760e01b145b806111c757506001600160e01b031982166323a87ba160e01b145b806111e257506001600160e01b0319821663253f8c7960e11b145b806111fd57506001600160e01b031982166329499a2560e01b145b8061121857506001600160e01b031982166317573c7360e21b145b8061123357506001600160e01b03198216632471dd5960e11b145b8061124e57506001600160e01b03198216634ba1182b60e11b145b8061126957506001600160e01b0319821663e8a3d48560e01b145b8061128457506001600160e01b0319821663938e3d7b60e01b145b8061129e57506001600160e01b03198216621d356760e01b145b806112ad57506112ad82613056565b92915050565b6060601880546112c290614ba0565b80601f01602080910402602001604051908101604052809291908181526020018280546112ee90614ba0565b801561133b5780601f106113105761010080835404028352916020019161133b565b820191906000526020600020905b81548152906001019060200180831161131e57829003601f168201915b5050505050905090565b6000611350826130a6565b6113b15760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610ede565b506000908152601c60205260409020546001600160a01b031690565b60006113d882611d85565b9050806001600160a01b0316836001600160a01b0316036114455760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610ede565b336001600160a01b038216148061146157506114618133612b7a565b6114ce5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776044820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b6064820152608401610ede565b6114d883836130c3565b505050565b6114ee63ca4b208b60e01b33613131565b61150a576040516282b42960e81b815260040160405180910390fd5b611514828261313e565b5050565b60006115248383613131565b9392505050565b61153c638da5cb5b60e01b33613131565b611558576040516282b42960e81b815260040160405180910390fd5b611569638da5cb5b60e01b82613131565b6115d457611581816001600160a01b03166014612eae565b611590638da5cb5b6004612eae565b61159b336014612eae565b6040516020016115ad93929190614cbe565b60408051601f1981840301815290829052630330dbc960e11b8252610ede91600401614751565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b60006110ef60165490565b61161263ca4b208b60e01b33613131565b61162e576040516282b42960e81b815260040160405180910390fd5b6116366132b8565b565b3330146116b257604051630330dbc960e11b815260206004820152604d6024820152600080516020615dd383398151915260448201527f6520646964206e6f7420636f6d6520696e7465726e616c6c792c20796f75206660648201526c61696c65642c204920776f6e2160981b608482015260a401610ede565b6110dd84848484613347565b6116c9335b8261337c565b6116e55760405162461bcd60e51b8152600401610ede90614d77565b6114d883838361343e565b6004546003546117009190614dde565b42101561173a57426004546003546117189190614dde565b60405163f3f82ac560e01b815260048101929092526024820152604401610ede565b6003546000036117bf57604051630330dbc960e11b815260206004820152604360248201527f54696d65436f703a20596f75277665206265656e2054696d6520436f7070656460448201527f2e204e474c206f6e6c794465762829206861736e277420736574207468652074606482015262696d6560e81b608482015260a401610ede565b600a6117ca33611e7f565b106117fc576117da336014612eae565b6117eb6117e633611e7f565b6135cc565b6040516020016115ad929190614df6565b61180d336118086136cc565b6136e5565b6116366136ff565b600b54600c546001600160a01b03909116906000906103e8906118389085614e7b565b6118429190614eb0565b90509250929050565b636525904560e11b61185d8133613131565b8061187457506118746303e1469160e61b33613131565b1561189c573361188b636525904560e11b82613717565b61151463ca4b208b60e01b82613723565b6118ab60e082901c6004612eae565b6118ba63f851a4406004612eae565b6118c5336014612eae565b6040516020016115ad93929190614ec4565b50565b6118eb638da5cb5b60e01b33613131565b611907576040516282b42960e81b815260040160405180910390fd5b6118d7308261372f565b636525904560e11b6119238133613131565b8061193a575061193a6303e1469160e61b33613131565b1561189c5733611514636525904560e11b82613717565b61196263ca4b208b60e01b33613131565b61197e576040516282b42960e81b815260040160405180910390fd5b6118d7816137c2565b6114d883838360405180602001604052806000815250612210565b6119ab336116c3565b6119ca576119ba336014612eae565b6040516020016115ad9190614f51565b6119d38161390a565b6118d7613993565b816119e68133613131565b806119fd57506119fd6303e1469160e61b33613131565b1561189c57631ada6fbb60e11b6001600160e01b0319841601611a6a576001600160a01b0382163314611a6a57611a35336014612eae565b611a4460e085901c6004612eae565b611a58846001600160a01b03166014612eae565b6040516020016115ad93929190614feb565b63392d1a5360e11b6001600160e01b0319841601611ad2576001600160a01b0382163314611ad257611a9d336014612eae565b611aac60e085901c6004612eae565b611ac0846001600160a01b03166014612eae565b6040516020016115ad939291906150a4565b6114d88383613717565b336000818152600860205260408120549003611b0d57611afd336014612eae565b6040516020016115ad91906150af565b600060075447611b1d9190614dde565b6001600160a01b0383166000908152600960209081526040808320546006546008909352908320549394509192611b549085614e7b565b611b5e9190614eb0565b611b689190615101565b905080600003611b8d57611b7d336014612eae565b6040516020016115ad9190615118565b6001600160a01b038316600090815260096020526040902054611bb1908290614dde565b6001600160a01b038416600090815260096020526040902055600754611bd8908290614dde565b600755611be5838261399d565b7fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b0568382604051611c16929190614559565b60405180910390a1505050565b611c3463ca4b208b60e01b33613131565b611c50576040516282b42960e81b815260040160405180910390fd5b600060228054611c5f90614ba0565b80601f0160208091040260200160405190810160405280929190818152602001828054611c8b90614ba0565b8015611cd85780601f10611cad57610100808354040283529160200191611cd8565b820191906000526020600020905b815481529060010190602001808311611cbb57829003601f168201915b505050505090508160229081611cee91906151ca565b507fd2877107a884510f506ed0bd833e6601f4344691e32a0ce4bcdedb1d9d9d28e1816022604051611d21929190615300565b60405180910390a15050565b6000611d39600d613ab6565b6010546110ef9190615101565b63ca4b208b60e01b611d588133613131565b80611d6f5750611d6f6303e1469160e61b33613131565b1561189c57611514636525904560e11b83613723565b6000818152601a60205260408120546001600160a01b0316806112ad5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610ede565b63ca4b208b60e01b611e0e8133613131565b80611e255750611e256303e1469160e61b33613131565b1561189c5733611e3c63ca4b208b60e01b84613723565b6114d863ca4b208b60e01b82613717565b80611e588133613131565b80611e6f5750611e6f6303e1469160e61b33613131565b1561189c57336114d88382613717565b60006001600160a01b038216611eea5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610ede565b506001600160a01b03166000908152601b602052604090205490565b638da5cb5b60e01b611f188133613131565b80611f2f5750611f2f6303e1469160e61b33613131565b1561189c5733611514638da5cb5b60e01b82613717565b602080526000908152604090208054611f5e90614ba0565b80601f0160208091040260200160405190810160405280929190818152602001828054611f8a90614ba0565b8015611fd75780601f10611fac57610100808354040283529160200191611fd7565b820191906000526020600020905b815481529060010190602001808311611fba57829003601f168201915b505050505081565b60006004546003546110ef9190614dde565b6346d2e5ad60e11b6120038133613131565b8061201a575061201a6303e1469160e61b33613131565b1561189c57336120316346d2e5ad60e11b82613717565b611514638da5cb5b60e01b82613723565b6000600a82815481106120575761205761532e565b6000918252602090912001546001600160a01b031692915050565b612083638da5cb5b60e01b33613131565b61209f576040516282b42960e81b815260040160405180910390fd5b611514828261372f565b6120ba63ca4b208b60e01b33613131565b6120d6576040516282b42960e81b815260040160405180910390fd5b6118d781613ac3565b6060600d60050180546112c290614ba0565b612102638da5cb5b60e01b33613131565b61211e576040516282b42960e81b815260040160405180910390fd5b602155565b6060601980546112c290614ba0565b6000806003546004546003546121489190614dde565b915091509091565b611514338383613b94565b6346d2e5ad60e11b61216d8133613131565b8061218457506121846303e1469160e61b33613131565b1561189c57336115146346d2e5ad60e11b82613717565b63ca4b208b60e01b6121ad8133613131565b806121c457506121c46303e1469160e61b33613131565b1561189c573361151463ca4b208b60e01b82613717565b6121ec638da5cb5b60e01b33613131565b612208576040516282b42960e81b815260040160405180910390fd5b611636613c5e565b61221a338361337c565b6122365760405162461bcd60e51b8152600401610ede90614d77565b6110dd84848484613cac565b61225363ca4b208b60e01b33613131565b61226f576040516282b42960e81b815260040160405180910390fd5b6000306001600160a01b0316635c17e3706040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d39190615344565b905060005b818110156115145761234d306001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612321573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612345919061535d565b6118086136cc565b612355613cdf565b6001016122d8565b6060612368826130a6565b61238557612375826135cc565b6040516020016115ad919061537a565b600061238f613cf3565b604080518082019091526005815264173539b7b760d91b60208201528151919250906123ca57604051806020016040528060008152506123f7565b816123d4856135cc565b826040516020016123e7939291906153e6565b6040516020818303038152906040525b949350505050565b60035442101561242f5760035460405163f3f82ac560e01b81524260048201526024810191909152604401610ede565b60045460035461243f9190614dde565b421061247857426004546003546124569190614dde565b6040516343c540ef60e01b815260048101929092526024820152604401610ede565b600461248333611e7f565b106124b057612493336014612eae565b61249f6117e633611e7f565b6040516020016115ad929190615429565b60028111156124de576124c4336014612eae565b6124cd826135cc565b6040516020016115ad9291906154ac565b60005b818110156115145760046124f433611e7f565b1061253557612504336014612eae565b61250d836135cc565b61252361251933611e7f565b6117e69086614dde565b6040516020016115ad93929190615530565b612541336118086136cc565b6125496136ff565b6001016124e1565b61255a81611d85565b6001600160a01b0316336001600160a01b03161461258a576040516282b42960e81b815260040160405180910390fd5b61ffff82166000908152602080526040902080546125a790614ba0565b905060000361262b57604051630330dbc960e11b815260206004820152604360248201527f546f6b656e3a204f6b2074686520446576206469646e2774207365742074686960448201527f7320706172616d617465722c20636f6e74616374204d6178466c6f774f322e656064820152623a341760e91b608482015260a401610ede565b6126348161390a565b61263c613993565b60003382604051602001612651929190614559565b60408051601f1981840301815290829052602154600160f01b60208401526022830152915060019060009060420160408051601f1981840301815290829052601e5463040a7bb160e41b83529092506000916001600160a01b03909116906340a7bb10906126cb90899030908990879089906004016155f1565b6040805180830381865afa1580156126e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270b9190615645565b5090503481111561274557612721336014612eae565b61272a346135cc565b612733836135cc565b6040516020016115ad93929190615669565b601e5461ffff87166000908152602080526040808220905162c5803160e81b81526001600160a01b039093169263c580310092349261278f928c928b913391908b906004016156eb565b6000604051808303818588803b1580156127a857600080fd5b505af11580156127bc573d6000803e3d6000fd5b5050505050505050505050565b61ffff85166000908152601f602052604080822090516127ea908790614ca2565b90815260408051602092819003830190206001600160401b038716600090815292529020600181015490915061288a57604051630330dbc960e11b815260206004820152604a6024820152600080516020615dd383398151915260448201527f652077617320616c72656164792065786563757465642c20796f75206661696c60648201526965642c204920776f6e2160b01b608482015260a401610ede565b8054821415806128b55750806001015483836040516128aa929190615752565b604051809103902014155b1561292557604051630330dbc960e11b815260206004820152604460248201819052600080516020615dd3833981519152908201527f6520776173206e6f742073746f7265642c20796f75206661696c65642c204920606482015263776f6e2160e01b608482015260a401610ede565b60008082556001820155604051630e1bd41160e11b81523090631c37a8229061295a908990899089908990899060040161578b565b600060405180830381600087803b15801561297457600080fd5b505af1158015612988573d6000803e3d6000fd5b50505050505050505050565b638da5cb5b60e01b6129a68133613131565b806129bd57506129bd6303e1469160e61b33613131565b1561189c576115146346d2e5ad60e11b83613723565b6129e463ca4b208b60e01b33613131565b612a00576040516282b42960e81b815260040160405180910390fd5b6003829055600481905560408051838152602081018390527f5ef81ff0fe28d74938986521db9f3fb5637cae3d1cec04a94b4a0d3a3b0fc3c49101611d21565b6060600d60040180546112c290614ba0565b81612a5d8133613131565b80612a745750612a746303e1469160e61b33613131565b1561189c57631ada6fbb60e11b6001600160e01b0319841601612ae757612aa2636525904560e11b33613131565b15612ae757612ab2336014612eae565b612ac160e085901c6004612eae565b612ad5846001600160a01b03166014612eae565b6040516020016115ad939291906157ca565b63392d1a5360e11b6001600160e01b0319841601612b5557612b106346d2e5ad60e11b33613131565b15612b5557612b20336014612eae565b612b2f60e085901c6004612eae565b612b43846001600160a01b03166014612eae565b6040516020016115ad9392919061584b565b6114d88383613723565b60006110ef600d613ab6565b6060600580546112c290614ba0565b6001600160a01b039182166000908152601d6020908152604080832093909416825291909152205460ff1690565b612bb963ca4b208b60e01b33613131565b612bd5576040516282b42960e81b815260040160405180910390fd5b61ffff831660009081526020805260409020612bf2828483615856565b507f93c35c217d799290d33244ef8905b63167d13758ab18343cd8055ed1b8056748838383604051611c1693929190615910565b6000612c32600d613049565b600f546110ef9190615101565b7f9a064d674ddc42ac41b38566457161f1ded37e65a59162da003dd25bcb057b603334604051612c70929190614559565b60405180910390a1565b638da5cb5b60e01b612c8c8133613131565b80612ca35750612ca36303e1469160e61b33613131565b1561189c5733612cba638da5cb5b60e01b84613723565b6114d8638da5cb5b60e01b82613717565b612cdc63ca4b208b60e01b33613131565b612cf8576040516282b42960e81b815260040160405180910390fd5b612d03868686613d02565b612d0d8383613d65565b601e80546001600160a01b0319166001600160a01b03929092169190911790555050505050565b612d4563ca4b208b60e01b33613131565b612d61576040516282b42960e81b815260040160405180910390fd5b612d7263ca4b208b60e01b82613131565b612db657612d8a816001600160a01b03166014612eae565b612d9963ca4b208b6004612eae565b612da4336014612eae565b6040516020016115ad9392919061592e565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038116612dfe576040516282b42960e81b815260040160405180910390fd5b612e09838383613d85565b15612e4257612e22816001600160a01b03166014612eae565b612e3160e084901c6004612eae565b6040516020016115ad9291906159ea565b6001600160a01b0381166000908152602084815260408083206001600160e01b03198616845290915290819020805460ff1916600190811790915590517fc8bed56f8e046b5a3f2c2b2be85045ea5c972dc18ad669157957897b4d26e9f791611c169185918591615a4e565b60606000612ebd836002614e7b565b612ec8906002614dde565b6001600160401b03811115612edf57612edf614589565b6040519080825280601f01601f191660200182016040528015612f09576020820181803683370190505b509050600360fc1b81600081518110612f2457612f2461532e565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110612f5357612f5361532e565b60200101906001600160f81b031916908160001a9053506000612f77846002614e7b565b612f82906001614dde565b90505b6001811115612ffa576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612fb657612fb661532e565b1a60f81b828281518110612fcc57612fcc61532e565b60200101906001600160f81b031916908160001a90535060049490941c93612ff381615a7b565b9050612f85565b5083156115245760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610ede565b60006112ad826006015490565b60006001600160e01b031982166380ac58cd60e01b148061308757506001600160e01b03198216635b5e139f60e01b145b806112ad57506301ffc9a760e01b6001600160e01b03198316146112ad565b6000908152601a60205260409020546001600160a01b0316151590565b6000818152601c6020526040902080546001600160a01b0319166001600160a01b03841690811790915581906130f882611d85565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000611524818484613d85565b6001600160a01b03821661316557604051630330dbc960e11b8152600401610ede90615a92565b806000036131b657604051630330dbc960e11b815260206004820152601d60248201527f5061796d656e7453706c69747465723a207368617265732061726520300000006044820152606401610ede565b6001600160a01b0382166000908152600860205260409020541561321b576131e8826001600160a01b03166014612eae565b6001600160a01b03831660009081526008602052604090205461320a906135cc565b6040516020016115ad929190615ade565b600a8054600181019091557fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80180546001600160a01b0319166001600160a01b0384169081179091556000908152600860205260409020819055600654613283908290614dde565b6006556040517f40c340f65e17194d14ddddb073d3c9f888e3cb52b5aae0c6c7706b4fbc905fac90611d219084908490614559565b600a5460005b81811015613306576000600a82815481106132db576132db61532e565b60009182526020808320909101546001600160a01b03168252600890526040812055506001016132be565b50600660009055600a600061331b9190614527565b6040517f3407fd525bf6581e0ae8e3a3636bd90d02112bea34d66802743c28ced73f910e90600090a150565b6000808280602001905181019061335e9190615b58565b9150915061336c82826136e5565b613374613709565b505050505050565b6000613387826130a6565b6133e85760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610ede565b60006133f383611d85565b9050806001600160a01b0316846001600160a01b0316148061342e5750836001600160a01b031661342384611345565b6001600160a01b0316145b806123f757506123f78185612b7a565b826001600160a01b031661345182611d85565b6001600160a01b0316146134b95760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610ede565b6001600160a01b03821661351b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610ede565b6135266000826130c3565b6001600160a01b0383166000908152601b6020526040812080546001929061354f908490615101565b90915550506001600160a01b0382166000908152601b6020526040812080546001929061357d908490614dde565b90915550506000818152601a602052604080822080546001600160a01b0319166001600160a01b038681169182179092559151849391871691600080516020615df383398151915291a4505050565b6060816000036135f35750506040805180820190915260018152600360fc1b602082015290565b8160005b811561361d578061360781615b86565b91506136169050600a83614eb0565b91506135f7565b6000816001600160401b0381111561363757613637614589565b6040519080825280601f01601f191660200182016040528015613661576020820181803683370190505b5090505b84156123f757613676600183615101565b9150613683600a86615b9f565b61368e906030614dde565b60f81b8183815181106136a3576136a361532e565b60200101906001600160f81b031916908160001a9053506136c5600a86614eb0565b9450613665565b60006136d8600d613de2565b6017546110ef9190614dde565b611514828260405180602001604052806000815250613e0d565b613709600d613e40565b611636601680546001019055565b61151460008383613e50565b61151460008383612dd8565b6103e88110158061373e575080155b156137685761374e336014612eae565b613757826135cc565b6040516020016115ad929190615bb3565b600b80546001600160a01b0319166001600160a01b038416908117909155600c8290556040805183815260208101929092527f184520f1b2fcf99836992b9a6b987afc0e4867f26a00ef438c654318763fe1e39101611d21565b6001600160a01b0381166137e957604051630330dbc960e11b8152600401610ede90615a92565b60006137f482613f1d565b600a805491925060009161380a90600190615101565b8154811061381a5761381a61532e565b600091825260209091200154600a80546001600160a01b0390921692508291849081106138495761384961532e565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600a80548061388857613888615c42565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0385168252600890526040812080549190556006546138d5908290615101565b6006556040517f104b8837ec12e86f303ac7ce5e3bf20c6790f843fabd7451943f3390fc8376cb906110d49086908490614559565b600061391582611d85565b90506139226000836130c3565b6001600160a01b0381166000908152601b6020526040812080546001929061394b908490615101565b90915550506000828152601a602052604080822080546001600160a01b0319169055518391906001600160a01b03841690600080516020615df3833981519152908390a45050565b6116366016613f77565b804710156139ed5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610ede565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613a3a576040519150601f19603f3d011682016040523d82523d6000602084013e613a3f565b606091505b50509050806114d85760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610ede565b60006112ad826007015490565b600060058054613ad290614ba0565b80601f0160208091040260200160405190810160405280929190818152602001828054613afe90614ba0565b8015613b4b5780601f10613b2057610100808354040283529160200191613b4b565b820191906000526020600020905b815481529060010190602001808311613b2e57829003601f168201915b505050505090508160059081613b6191906151ca565b507f17f75bb1e35b058872a221a8c16d8b3e39eacbda214fd7da20f192b9291ecc3b816005604051611d21929190615300565b816001600160a01b0316836001600160a01b031603613bf15760405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b6044820152606401610ede565b6001600160a01b038381166000818152601d6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b600b80546001600160a01b03191690556000600c8190556040805182815260208101929092527f184520f1b2fcf99836992b9a6b987afc0e4867f26a00ef438c654318763fe1e39101612c70565b613cb784848461343e565b613cc384848484613fe0565b6110dd5760405162461bcd60e51b8152600401610ede90615c58565b613ce9600d613e40565b613709600d6140e1565b6060602280546112c290614ba0565b6017839055613d12600d836140f1565b613d1d600d82614131565b7f0e59e2733e85d32179b3dffa920faef60cc432823591194c4e5f0ac15db3dcec8284613d4a8183614dde565b60408051938452602084019290925290820152606001611c16565b613d70600d82614171565b613d7b600d83614245565b611514600d614319565b60006001600160a01b038216613dad576040516282b42960e81b815260040160405180910390fd5b506001600160a01b03166000908152602092835260408082206001600160e01b03199390931682529190925290205460ff1690565b60008160020154613df4836006015490565b8360010154613e039190614dde565b6112ad9190615b9f565b613e178383614406565b613e246000848484613fe0565b6114d85760405162461bcd60e51b8152600401610ede90615c58565b6118d78160060180546001019055565b6001600160a01b038116613e76576040516282b42960e81b815260040160405180910390fd5b613e81838383613d85565b613eb957613e99816001600160a01b03166014612eae565b613ea860e084901c6004612eae565b6040516020016115ad929190615caa565b6001600160a01b0381166000908152602084815260408083206001600160e01b031986168452909152808220805460ff19169055517fc8bed56f8e046b5a3f2c2b2be85045ea5c972dc18ad669157957897b4d26e9f791611c169185918591615a4e565b600a54600090815b81811015613f7057836001600160a01b0316600a8281548110613f4a57613f4a61532e565b6000918252602090912001546001600160a01b031603613f68578092505b600101613f25565b5050919050565b80546000819003613fd557604051630330dbc960e11b815260206004820152602160248201527f436f756e7465727356323a204e6f206e656761746976657320696e2075696e746044820152607360f81b6064820152608401610ede565b508054600019019055565b60006001600160a01b0384163b156140d657604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290614024903390899088908890600401615d10565b6020604051808303816000875af192505050801561405f575060408051601f3d908101601f1916820190925261405c91810190615d4d565b60015b6140bc573d80801561408d576040519150601f19603f3d011682016040523d82523d6000602084013e614092565b606091505b5080516000036140b45760405162461bcd60e51b8152600401610ede90615c58565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506123f7565b506001949350505050565b6118d78160070180546001019055565b6002820180549082905560408051838152602081018390527fe26aa1327aec5016c96875498202eebb896e3c2a79cd281ff17ed5bde4e545db9101611c16565b6003820180549082905560408051838152602081018390527fef40c7688f323b7ccad323bec82bfee336d16c0939c46bee1f3e5df296dadde39101611c16565b600082600501805461418290614ba0565b80601f01602080910402602001604051908101604052809291908181526020018280546141ae90614ba0565b80156141fb5780601f106141d0576101008083540402835291602001916141fb565b820191906000526020600020905b8154815290600101906020018083116141de57829003601f168201915b505050505090508183600501908161421391906151ca565b507f5769620297eb5047703c0ba55dd28b8ea50ba49818a91a43217fedce8eb69a308282604051611c16929190615d6a565b600082600401805461425690614ba0565b80601f016020809104026020016040519081016040528092919081815260200182805461428290614ba0565b80156142cf5780601f106142a4576101008083540402835291602001916142cf565b820191906000526020600020905b8154815290600101906020018083116142b257829003601f168201915b50505050509050818360040190816142e791906151ca565b507f7058c986a2931f38a70c3f70689d1f2bb75efb4d0082511082db4b2d40492b4f8282604051611c16929190615d6a565b806002015460000361438257604051630330dbc960e11b815260206004820152602b60248201527f50737565646f52616e646f6d204c69623a204d6178696d756d2043617061636960448201526a7479206e6f74207365742160a81b6064820152608401610ede565b806002015442338360040184600501446040516020016143a6959493929190615d8f565b6040516020818303038152906040528051906020012060001c6143c99190615b9f565b600182018190556040519081527f74d17dde2d5b61215fe87f93cddcd2470527e8b0381734da7d0dfeb3fcf6f8179060200160405180910390a150565b6001600160a01b03821661445c5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610ede565b614465816130a6565b156144b25760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610ede565b6001600160a01b0382166000908152601b602052604081208054600192906144db908490614dde565b90915550506000818152601a602052604080822080546001600160a01b0319166001600160a01b0386169081179091559051839290600080516020615df3833981519152908290a45050565b50805460008255906000526020600020908101906118d791905b808211156145555760008155600101614541565b5090565b6001600160a01b03929092168252602082015260400190565b803561ffff8116811461458457600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126145b057600080fd5b81356001600160401b03808211156145ca576145ca614589565b604051601f8301601f19908116603f011681019082821181831017156145f2576145f2614589565b8160405283815286602085880101111561460b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b80356001600160401b038116811461458457600080fd5b6000806000806080858703121561465857600080fd5b61466185614572565b935060208501356001600160401b038082111561467d57600080fd5b6146898883890161459f565b94506146976040880161462b565b935060608701359150808211156146ad57600080fd5b506146ba8782880161459f565b91505092959194509250565b6001600160e01b0319811681146118d757600080fd5b6000602082840312156146ee57600080fd5b8135611524816146c6565b60005b838110156147145781810151838201526020016146fc565b838111156110dd5750506000910152565b6000815180845261473d8160208601602086016146f9565b601f01601f19169290920160200192915050565b6020815260006115246020830184614725565b60006020828403121561477657600080fd5b5035919050565b6001600160a01b03811681146118d757600080fd5b600080604083850312156147a557600080fd5b82356147b08161477d565b946020939093013593505050565b600080604083850312156147d157600080fd5b82356147dc816146c6565b915060208301356147ec8161477d565b809150509250929050565b60006020828403121561480957600080fd5b81356115248161477d565b60008060006060848603121561482957600080fd5b83356148348161477d565b925060208401356148448161477d565b929592945050506040919091013590565b6000806040838503121561486857600080fd5b50508035926020909101359150565b60006020828403121561488957600080fd5b81356001600160401b0381111561489f57600080fd5b6123f78482850161459f565b6000602082840312156148bd57600080fd5b61152482614572565b6000806000606084860312156148db57600080fd5b6148e484614572565b925060208401356001600160401b038111156148ff57600080fd5b61490b8682870161459f565b925050604084013590509250925092565b6000806040838503121561492f57600080fd5b823561493a8161477d565b9150602083013580151581146147ec57600080fd5b6000806000806080858703121561496557600080fd5b84356149708161477d565b935060208501356149808161477d565b92506040850135915060608501356001600160401b038111156149a257600080fd5b6146ba8782880161459f565b600080604083850312156149c157600080fd5b6147b083614572565b60008083601f8401126149dc57600080fd5b5081356001600160401b038111156149f357600080fd5b602083019150836020828501011115614a0b57600080fd5b9250929050565b600080600080600060808688031215614a2a57600080fd5b614a3386614572565b945060208601356001600160401b0380821115614a4f57600080fd5b614a5b89838a0161459f565b9550614a696040890161462b565b94506060880135915080821115614a7f57600080fd5b50614a8c888289016149ca565b969995985093965092949392505050565b60008060408385031215614ab057600080fd5b82356147dc8161477d565b600080600060408486031215614ad057600080fd5b614ad984614572565b925060208401356001600160401b03811115614af457600080fd5b614b00868287016149ca565b9497909650939450505050565b60008060008060008060c08789031215614b2657600080fd5b86359550602087013594506040870135935060608701356001600160401b0380821115614b5257600080fd5b614b5e8a838b0161459f565b94506080890135915080821115614b7457600080fd5b50614b8189828a0161459f565b92505060a0870135614b928161477d565b809150509295509295509295565b600181811c90821680614bb457607f821691505b602082108103614bd457634e487b7160e01b600052602260045260246000fd5b50919050565b60008154614be781614ba0565b60018281168015614bff5760018114614c1457614c43565b60ff1984168752821515830287019450614c43565b8560005260208060002060005b85811015614c3a5781548a820152908401908201614c21565b50505082870194505b5050505092915050565b60006115248284614bda565b61ffff85168152608060208201526000614c766080830186614725565b6001600160401b03851660408401528281036060840152614c978185614725565b979650505050505050565b60008251614cb48184602087016146f9565b9190910192915050565b76026b0bc20b1b1b2b9b99d102a34329030b2323932b9b99604d1b815260008451614cf08160178501602089016146f9565b7f206973206e6f7420616e206f776e657220616e6420646f6573206e6f742068616017918401918201526b03b32903a3432903937b632960a51b60378201528451614d428160438401602089016146f9565b660103a3432b932960cd1b604392909101918201528351614d6a81604a8401602088016146f9565b01604a0195945050505050565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60008219821115614df157614df1614dc8565b500190565b6902a37b5b2b71d1027b5960b51b815260008351614e1b81600a8501602088016146f9565b690103cb7ba903430bb32960b51b600a918401918201528351614e458160148401602088016146f9565b7f206d6178696d756d20617420746869732074696d652069732031302e0000000060149290910191820152603001949350505050565b6000816000190483118215151615614e9557614e95614dc8565b500290565b634e487b7160e01b600052601260045260246000fd5b600082614ebf57614ebf614e9a565b500490565b7f4d61784163636573733a20596f75206172652061206e6f7420616e2000000000815260008451614efc81601c8501602089016146f9565b80830190506301037b9160e51b601c8201528451614f218160208401602089016146f9565b808201915050600160fd1b60208201528351614f448160218401602088016146f9565b0160210195945050505050565b6f022a9219b9918a13ab93730b136329d160851b815260008251614f7c8160108501602087016146f9565b7f206973206e6f74206f776e6572206e6f7220617070726f7665640000000000006010939091019283015250602a01919050565b7f4d61784163636573733a20596f752061726520612070656e64696e6720646576815268032b637b832b91414960bd1b602082015260290190565b6000614ff682614fb0565b8551615006818360208a016146f9565b780103cb7ba9031b0b7103737ba103932bb37b5b2903937b6329603d1b9101908152845161503b8160198401602089016146f9565b630103a37960e51b60199290910191820152835161506081601d8401602088016146f9565b01601d0195945050505050565b7f4d61784163636573733a20596f752061726520612070656e64696e67206f776e815264032b91414960dd1b602082015260250190565b6000614ff68261506d565b7002830bcb6b2b73a29b83634ba3a32b91d1607d1b8152600082516150db8160118501602087016146f9565b6e103430b99037379039b430b932b99760891b6011939091019283015250602001919050565b60008282101561511357615113614dc8565b500390565b7002830bcb6b2b73a29b83634ba3a32b91d1607d1b8152600082516151448160118501602087016146f9565b731034b9903737ba10323ab2903830bcb6b2b73a1760611b6011939091019283015250602501919050565b601f8211156114d857600081815260208120601f850160051c810160208610156151965750805b601f850160051c820191505b81811015613374578281556001016151a2565b600019600383901b1c191660019190911b1790565b81516001600160401b038111156151e3576151e3614589565b6151f7816151f18454614ba0565b8461516f565b602080601f83116001811461522657600084156152145750858301515b61521e85826151b5565b865550613374565b600085815260208120601f198616915b8281101561525557888601518255948401946001909101908401615236565b50858210156152735787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000815461529081614ba0565b8085526020600183811680156152ad57600181146152c7576152f5565b60ff1985168884015283151560051b8801830195506152f5565b866000528260002060005b858110156152ed5781548a82018601529083019084016152d2565b890184019650505b505050505092915050565b6040815260006153136040830185614725565b82810360208401526153258185615283565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561535657600080fd5b5051919050565b60006020828403121561536f57600080fd5b81516115248161477d565b7f4552433732314d657461646174613a2055524920717565727920666f722000008152600082516153b281601e8501602087016146f9565b7f2072657475726e73206e6f6e6578697374656e7420746f6b656e000000000000601e939091019283015250603801919050565b600084516153f88184602089016146f9565b84519083019061540c8183602089016146f9565b845191019061541f8183602088016146f9565b0195945050505050565b6902a37b5b2b71d1027b5960b51b81526000835161544e81600a8501602088016146f9565b690103cb7ba903430bb32960b51b600a9184019182015283516154788160148401602088016146f9565b7a1036b0bc34b6bab69030ba103a3434b9903a34b6b29034b9901a1760291b60149290910191820152602f01949350505050565b6902a37b5b2b71d1027b5960b51b8152600083516154d181600a8501602088016146f9565b730103cb7ba903bb0b73a32b2103a379036b4b73a160651b600a91840191820152835161550581601e8401602088016146f9565b7110191037b9103632b9b990383632b0b9b29760711b601e9290910191820152603001949350505050565b6902a37b5b2b71d1027b5960b51b81526000845161555581600a8501602089016146f9565b730103cb7ba903bb0b73a32b2103a379036b4b73a160651b600a91840191820152845161558981601e8401602089016146f9565b710103a3430ba10383aba39903cb7ba9030ba160751b601e929091019182015283516155bc8160308401602088016146f9565b7a1036b0bc34b6bab69030ba103a3434b9903a34b6b29034b9901a1760291b60309290910191820152604b0195945050505050565b61ffff861681526001600160a01b038516602082015260a06040820181905260009061561f90830186614725565b841515606084015282810360808401526156398185614725565b98975050505050505050565b6000806040838503121561565857600080fd5b505080516020909101519092909150565b6602a37b5b2b71d160cd1b81526000845161568b8160078501602089016146f9565b6501039b2b73a160d51b60079184019182015284516156b181600d8401602089016146f9565b6b01034b739ba32b0b21037b3160a51b600d929091019182015283516156de8160198401602088016146f9565b0160190195945050505050565b61ffff8716815260c06020820152600061570860c0830188615283565b828103604084015261571a8188614725565b6001600160a01b0387811660608601528616608085015283810360a085015290506157458185614725565b9998505050505050505050565b8183823760009101908152919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff861681526080602082015260006157a86080830187614725565b6001600160401b03861660408401528281036060840152615639818587615762565b60006157d582614fb0565b85516157e5818360208a016146f9565b770103cb7ba9031b0b7103737ba1033b930b73a103937b632960451b910190815284516158198160188401602089016146f9565b630103a37960e51b60189290910191820152835161583e81601c8401602088016146f9565b01601c0195945050505050565b60006157d58261506d565b6001600160401b0383111561586d5761586d614589565b6158818361587b8354614ba0565b8361516f565b6000601f8411600181146158af576000851561589d5750838201355b6158a786826151b5565b845550615909565b600083815260209020601f19861690835b828110156158e057868501358255602094850194600190920191016158c0565b50868210156158fd5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b61ffff84168152604060208201526000615325604083018486615762565b76026b0bc20b1b1b2b9b99d102a34329030b2323932b9b99604d1b8152600084516159608160178501602089016146f9565b7f206973206e6f74206120646576656c6f70657220616e6420646f6573206e6f746017918401918201526e0103430bb32903a3432903937b6329608d1b603782015284516159b58160468401602089016146f9565b660103a3432b932960cd1b6046929091019182015283516159dd81604d8401602088016146f9565b01604d0195945050505050565b6a02634b1102937b632b99d160ad1b815260008351615a1081600b8501602088016146f9565b7101030b63932b0b23c903430b9903937b632960751b600b918401918201528351615a4281601d8401602088016146f9565b01601d01949350505050565b6001600160e01b03199390931683526001600160a01b039190911660208301521515604082015260600190565b600081615a8a57615a8a614dc8565b506000190190565b6020808252602c908201527f5061796d656e7453706c69747465723a206163636f756e74206973207468652060408201526b7a65726f206164647265737360a01b606082015260800190565b7002830bcb6b2b73a29b83634ba3a32b91d1607d1b815260008351615b0a8160118501602088016146f9565b6c01030b63932b0b23c903430b99609d1b6011918401918201528351615b3781601e8401602088016146f9565b671039b430b932b99760c11b601e9290910191820152602601949350505050565b60008060408385031215615b6b57600080fd5b8251615b768161477d565b6020939093015192949293505050565b600060018201615b9857615b98614dc8565b5060010190565b600082615bae57615bae614e9a565b500690565b72022a921991c9c18a1b7b63632b1ba34b7b71d1606d1b815260008351615be18160138501602088016146f9565b6a01039bab136b4ba3a32b2160ad1b6013918401918201528351615c0c81601e8401602088016146f9565b7f20616e642074686174206973206f7574206f6620626f756e6473210000000000601e9290910191820152603901949350505050565b634e487b7160e01b600052603160045260246000fd5b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6a02634b1102937b632b99d160ad1b815260008351615cd081600b8501602088016146f9565b730103237b2b9903737ba103430bb32903937b632960651b600b918401918201528351615d0481601f8401602088016146f9565b01601f01949350505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615d4390830184614725565b9695505050505050565b600060208284031215615d5f57600080fd5b8151611524816146c6565b604081526000615d7d6040830185614725565b82810360208401526153258185614725565b8581526bffffffffffffffffffffffff198560601b1660208201526000615dc2615dbc6034840187614bda565b85614bda565b928352505060200194935050505056fe4e6f6e626c6f636b696e6752656365697665723a2054686973206d6573736167ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212203141b7ea1d69d1dba90a4aa8c8ceb739713a9cc2ac8d184bde9f9da53c19d3bb64736f6c634300080f0033

Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.