ETH Price: $3,488.45 (+0.96%)

Contract

0x13a1a089454daa9a11f3682467E29aD76b3bFe1a
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Approval For...214569172024-12-22 8:42:472 days ago1734856967IN
0x13a1a089...76b3bFe1a
0 ETH0.000277946.01503491
Set Approval For...214464812024-12-20 21:40:474 days ago1734730847IN
0x13a1a089...76b3bFe1a
0 ETH0.000344314.17124356
Set Approval For...214139902024-12-16 8:49:478 days ago1734338987IN
0x13a1a089...76b3bFe1a
0 ETH0.000389628.43201219
Set Approval For...214088402024-12-15 15:33:599 days ago1734276839IN
0x13a1a089...76b3bFe1a
0 ETH0.0004709410.19186557
Set Approval For...214066382024-12-15 8:10:119 days ago1734250211IN
0x13a1a089...76b3bFe1a
0 ETH0.000298436.45858004
Set Approval For...213829562024-12-12 0:50:5912 days ago1733964659IN
0x13a1a089...76b3bFe1a
0 ETH0.0006385113.79317998
Set Approval For...213810672024-12-11 18:30:5913 days ago1733941859IN
0x13a1a089...76b3bFe1a
0 ETH0.0015631333.82819425
Set Approval For...213797592024-12-11 14:07:4713 days ago1733926067IN
0x13a1a089...76b3bFe1a
0 ETH0.0021432246.38209062
Set Approval For...213777462024-12-11 7:21:4713 days ago1733901707IN
0x13a1a089...76b3bFe1a
0 ETH0.0005183811.19812325
Set Approval For...213777202024-12-11 7:16:3513 days ago1733901395IN
0x13a1a089...76b3bFe1a
0 ETH0.0005238311.31596142
Set Approval For...213493452024-12-07 8:12:3517 days ago1733559155IN
0x13a1a089...76b3bFe1a
0 ETH0.0007826916.93849516
Set Approval For...213475232024-12-07 2:06:3517 days ago1733537195IN
0x13a1a089...76b3bFe1a
0 ETH0.0045159297.73031693
Set Approval For...213475182024-12-07 2:05:3517 days ago1733537135IN
0x13a1a089...76b3bFe1a
0 ETH0.0044996497.06714708
Set Approval For...213473302024-12-07 1:27:2317 days ago1733534843IN
0x13a1a089...76b3bFe1a
0 ETH0.0006993715.10789016
Set Approval For...213362062024-12-05 12:10:2319 days ago1733400623IN
0x13a1a089...76b3bFe1a
0 ETH0.0009634320.85004366
Set Approval For...213074612024-12-01 11:48:3523 days ago1733053715IN
0x13a1a089...76b3bFe1a
0 ETH0.000372298.05683603
Set Approval For...213000692024-11-30 11:02:5924 days ago1732964579IN
0x13a1a089...76b3bFe1a
0 ETH0.000377628.15746473
Safe Transfer Fr...212919792024-11-29 7:52:1125 days ago1732866731IN
0x13a1a089...76b3bFe1a
0 ETH0.000438866.85322858
Set Approval For...212899632024-11-29 1:06:1125 days ago1732842371IN
0x13a1a089...76b3bFe1a
0 ETH0.000248425.37631535
Set Approval For...212871502024-11-28 15:40:1126 days ago1732808411IN
0x13a1a089...76b3bFe1a
0 ETH0.0007309915.8195851
Set Approval For...212523942024-11-23 19:00:5931 days ago1732388459IN
0x13a1a089...76b3bFe1a
0 ETH0.0006193413.37912527
Transfer From212392672024-11-21 23:03:1132 days ago1732230191IN
0x13a1a089...76b3bFe1a
0 ETH0.0008165114.6412208
Set Approval For...212370502024-11-21 15:38:2333 days ago1732203503IN
0x13a1a089...76b3bFe1a
0 ETH0.0012325426.67394502
Set Approval For...212331762024-11-21 2:38:4733 days ago1732156727IN
0x13a1a089...76b3bFe1a
0 ETH0.0007011915.1746939
Set Approval For...212113142024-11-18 1:28:3536 days ago1731893315IN
0x13a1a089...76b3bFe1a
0 ETH0.000449059.71821582
View all transactions

Latest 23 internal transactions

Advanced mode:
Parent Transaction Hash Block
From
To
190579622024-01-21 21:50:47338 days ago1705873847
0x13a1a089...76b3bFe1a
1.6 ETH
190572262024-01-21 19:15:47338 days ago1705864547
0x13a1a089...76b3bFe1a
1.5 ETH
190570672024-01-21 18:39:23338 days ago1705862363
0x13a1a089...76b3bFe1a
1.5 ETH
190570462024-01-21 18:34:35338 days ago1705862075
0x13a1a089...76b3bFe1a
1.5 ETH
190569772024-01-21 18:18:23338 days ago1705861103
0x13a1a089...76b3bFe1a
1.5 ETH
190550092024-01-21 11:42:35338 days ago1705837355
0x13a1a089...76b3bFe1a
1.8 ETH
190512162024-01-20 23:00:23338 days ago1705791623
0x13a1a089...76b3bFe1a
1.5 ETH
190495752024-01-20 17:29:35339 days ago1705771775
0x13a1a089...76b3bFe1a
1.5 ETH
190495302024-01-20 17:20:23339 days ago1705771223
0x13a1a089...76b3bFe1a
1.5 ETH
190430892024-01-19 19:46:23340 days ago1705693583
0x13a1a089...76b3bFe1a
0.5 ETH
190430552024-01-19 19:39:23340 days ago1705693163
0x13a1a089...76b3bFe1a
0.5 ETH
190430372024-01-19 19:35:47340 days ago1705692947
0x13a1a089...76b3bFe1a
0.5 ETH
190430312024-01-19 19:34:35340 days ago1705692875
0x13a1a089...76b3bFe1a
0.5 ETH
190430052024-01-19 19:29:23340 days ago1705692563
0x13a1a089...76b3bFe1a
0.5 ETH
190429232024-01-19 19:12:59340 days ago1705691579
0x13a1a089...76b3bFe1a
0.1 ETH
190363752024-01-18 21:17:35341 days ago1705612655
0x13a1a089...76b3bFe1a
0.5 ETH
190361042024-01-18 20:23:11341 days ago1705609391
0x13a1a089...76b3bFe1a
1.5 ETH
190338192024-01-18 12:42:47341 days ago1705581767
0x13a1a089...76b3bFe1a
0.2 ETH
190206722024-01-16 16:33:35343 days ago1705422815
0x13a1a089...76b3bFe1a
1.1 ETH
190205952024-01-16 16:18:11343 days ago1705421891
0x13a1a089...76b3bFe1a
1.6 ETH
189948582024-01-13 2:01:35346 days ago1705111295
0x13a1a089...76b3bFe1a
0.5 ETH
189945452024-01-13 0:58:47346 days ago1705107527
0x13a1a089...76b3bFe1a
0.5 ETH
189939872024-01-12 23:06:35346 days ago1705100795
0x13a1a089...76b3bFe1a
3.077 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
HOW

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 1000 runs

Other Settings:
london EvmVersion
File 1 of 24 : Homies.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: [EIP721] HOW NFT
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice ERC721 Implementation with:
 *         Enhanced EIP173 - Ownership via roles
 *         EIP2981 - NFT Royalties
 *         PaymentSplitter v2 - For "ETH" payments
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.17 <0.9.0;

import "./Max-721-2981-PSv2.sol";
import "./lib/721.sol";
import "./lib/Lists.sol";
import "./lib/CountersV2.sol";
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "@openzeppelin/contracts/utils/Base64.sol";

contract HOW is Max721 {

  using Lib721 for Lib721.Token;
  using Lists for Lists.Access;
  using CountersV2 for CountersV2.Counter;

  CountersV2.Counter internal theTokenID;

  event Claimed(uint256 index, address account, uint256 amount, string what);

  constructor(
    string memory _name
  , string memory _symbol
  , address _admin
  , address _dev
  , address _owner
  , uint256 _start
  ) {
      __Max721_init(_name, _symbol, _admin, _dev, _owner);
      theTokenID.set(_start);
  }

  // set time block
  modifier preSale() {
    if (block.timestamp < startTime + period && block.timestamp >= startTime) {
      _;
    } else {
    revert Unauthorized();
    }
  }

  modifier Sale() {
    if (block.timestamp >= startTime + period) {
      _;
    } else {
    revert Unauthorized();
    }
  }

  function setTime(
    uint256 _start
  , uint256 _period
  ) external
    onlyDev() {
    startTime = _start;
    period = _period;
  }

  function showTimes()
    external
    view
    returns (uint256, uint256) {
    return (startTime, startTime + period);
  }

  function setCap(
    uint256 _amount
  ) external
    onlyDev() {
    maxCap = _amount;
  }

  function setMerks(
    bytes32 _admin
  , bytes32 _homies
  , bytes32 _normies
  ) external
    onlyDev() {
    admin = _admin;
    homies = _homies;
    normies = _normies;
  }

  function isClaimedAdmin(
    uint256 index
  ) public
    view
    returns (bool) {
    uint256 claimedWordIndex = index / 256;
    uint256 claimedBitIndex = index % 256;
    uint256 claimedWord = claimedAdmin[claimedWordIndex];
    uint256 mask = (1 << claimedBitIndex);
    return claimedWord & mask == mask;
  }

  function isClaimedHomies(
    uint256 index
  ) public
    view
    returns (bool) {
    uint256 claimedWordIndex = index / 256;
    uint256 claimedBitIndex = index % 256;
    uint256 claimedWord = claimedHomies[claimedWordIndex];
    uint256 mask = (1 << claimedBitIndex);
    return claimedWord & mask == mask;
  }

  function isClaimedNormies(
    uint256 index
  ) public
    view
    returns (bool) {
    uint256 claimedWordIndex = index / 256;
    uint256 claimedBitIndex = index % 256;
    uint256 claimedWord = claimedNormies[claimedWordIndex];
    uint256 mask = (1 << claimedBitIndex);
    return claimedWord & mask == mask;
  }

  function _setClaimedAdmin(
    uint256 index
  ) internal {
    uint256 claimedWordIndex = index / 256;
    uint256 claimedBitIndex = index % 256;
    claimedAdmin[claimedWordIndex] = claimedAdmin[claimedWordIndex] | (1 << claimedBitIndex);
  }

  function _setClaimedHomies(
    uint256 index
  ) internal {
    uint256 claimedWordIndex = index / 256;
    uint256 claimedBitIndex = index % 256;
    claimedHomies[claimedWordIndex] = claimedHomies[claimedWordIndex] | (1 << claimedBitIndex);
  }

  function _setClaimedNormies(
    uint256 index
  ) internal {
    uint256 claimedWordIndex = index / 256;
    uint256 claimedBitIndex = index % 256;
    claimedNormies[claimedWordIndex] = claimedNormies[claimedWordIndex] | (1 << claimedBitIndex);
  }

  function adminMint(
    uint256 index
  , address account
  , uint256 amount
  , bytes32[] calldata merkleProof
  ) external
    preSale() {
    if (startTime == 0) {
      revert Unauthorized();
    }
    if (isClaimedAdmin(index)) {
      revert MaxSplaining({
        reason: "Already Claimed"
      });
    }

    // Verify the merkle proof.
    bytes32 node = keccak256(abi.encodePacked(index, account, amount));
    if (!MerkleProof.verify(merkleProof, admin, node)) {
      revert MaxSplaining({
        reason: "Invalid Proof"
      });
    }

    // Mark it claimed and send the token.
    _setClaimedAdmin(index);
    if (token721.getSupply() + amount > maxCap) {
      revert Unauthorized();
    } else {
      for (uint c = 0; c < amount;) {
        // mint each
        token721.mint(account, theTokenID.current());
        emit Transfer(address(0), account, theTokenID.current());
        theTokenID.increment();
        unchecked { ++c; }
      }
    }
    emit Claimed(index, account, amount, "Admin");
  }

  function homiesMint(
    uint256 index
  , address account
  , bytes32[] calldata merkleProof
  ) external
    preSale() {
    if (startTime == 0) {
      revert Unauthorized();
    }
    if (isClaimedHomies(index)) {
      revert MaxSplaining({
        reason: "Already Claimed"
      });
    }

    // Verify the merkle proof.
    bytes32 node = keccak256(abi.encodePacked(index, account));
    if (!MerkleProof.verify(merkleProof, homies, node)) {
      revert MaxSplaining({
        reason: "Invalid Proof"
      });
    }

    // Mark it claimed and send the token.
    _setClaimedHomies(index);
    if (token721.getSupply() + 1 > maxCap) {
      revert Unauthorized();
    } else {
      token721.mint(account, theTokenID.current());
      emit Transfer(address(0), account, theTokenID.current());
      theTokenID.increment();
    }
    emit Claimed(index, account, 1, "Homies");
  }

  function normiesMint(
    uint256 index
  , address account
  , bytes32[] calldata merkleProof
  ) external
    payable
    preSale() {
    if (startTime == 0) {
      revert Unauthorized();
    }
    if (msg.value != normiesCost) {
      revert MaxSplaining ({
        reason: "msg.value too low"
      });
    }
    if (isClaimedNormies(index)) {
      revert MaxSplaining({
        reason: "Already Claimed"
      });
    }

    // Verify the merkle proof.
    bytes32 node = keccak256(abi.encodePacked(index, account));
    if (!MerkleProof.verify(merkleProof, normies, node)) {
      revert MaxSplaining({
        reason: "Invalid Proof"
      });
    }

    // Mark it claimed and send the token.
    _setClaimedNormies(index);
    if (token721.getSupply() + 1 > maxCap) {
      revert Unauthorized();
    } else {
      token721.mint(account, theTokenID.current());
      emit Transfer(address(0), account, theTokenID.current());
      theTokenID.increment();
    }
    emit Claimed(index, account, 1, "Normies");
  }

  function publicMint(
    uint256 quant
  ) external
    payable
    Sale() {
    if (quant > 5) {
      revert Unauthorized();
    }
    if (startTime == 0) {
      revert Unauthorized();
    }
    if (msg.value != publicCost * quant) {
      revert MaxSplaining ({
        reason: "msg.value too low"
      });
    }
    if (token721.getSupply() + quant > maxCap) {
      revert Unauthorized();
    } else {
      for (uint c = 0; c < quant;) {
        // mint each
        token721.mint(msg.sender, theTokenID.current());
        emit Transfer(address(0), msg.sender, theTokenID.current());
        theTokenID.increment();
        unchecked { ++c; }
      }
    }
  }

  function setFees(
    uint256 _normies
  , uint256 _public
  ) external
    onlyDev() {
    normiesCost = _normies;
    publicCost = _public;
  }

  function setContractURI(
    string memory newURI
  ) external
    onlyDev() {
    contractURL = newURI;
  }

  function contractURI()
    public
    view
    returns (string memory) {
    return contractURL;
  }

  function setJSON(
    string memory _description
  , string memory _image
  , string memory _animation
  ) external
    onlyDev() {
    description = _description;
    image = _image;
    animationURI = _animation;
  }

  function tokenURI(
    uint256 tokenId
  ) public
    view
    virtual
    override
    returns (string memory) {
    bytes memory json = abi.encodePacked(
      "{",
      '"name": "Homies Genesis #',
      Strings.toString(uint256(tokenId)),
      '",',
      '"description": "',
      description,
      '",',
      '"image": "',
      image,
      '",',
      '"animation_url": "',
      animationURI,
      '"',
      "}"
    );

    return string(
      abi.encodePacked(
        "data:application/json;base64,",
        Base64.encode(json)
      )
    );
  }

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

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

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

File 2 of 24 : ISplitter.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: [Not an EIP] Payment Splitter, interface for ether payments
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for Payment Splitter
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "../../eip/165/IERC165.sol";

interface ISplitter is IERC165 {

  /// @dev returns total shares
  /// @return uint256 of all shares on contract
  function totalShares()
    external
    view
    returns (uint256);

  /// @dev returns shares of an address
  /// @param payee address of payee to return
  /// @return mapping(address => uint) of _shares
  function shares(
    address payee
  ) external
    view
    returns (uint256);

  /// @dev returns total releases in "eth"
  /// @return uint256 of all "eth" released in wei
  function totalReleased()
    external
    view
    returns (uint256);

  /// @dev returns released "eth" of an payee
  /// @param payee address of payee to look up
  /// @return mapping(address => uint) of _released
  function released(
    address payee
  ) external
    view
    returns (uint256);

  /// @dev returns amount of "eth" that can be released to payee
  /// @param payee address of payee to look up
  /// @return uint in wei of "eth" to release
  function releasable(
    address payee
  ) external
    view
    returns (uint256);

  /// @dev returns index number of payee
  /// @param payee number of index
  /// @return address at _payees[index]
  function payeeIndex(
    address payee
  ) external
    view
    returns (uint256);

  /// @dev this returns the array of payees[]
  /// @return address[] payees
  function payees()
    external
    view
    returns (address[] memory);

  /// @dev this claims all "eth" on contract for msg.sender
  function claim()
    external;

  /// @dev This pays all payees
  function payClaims()
    external;

  /// @dev This adds a payee
  /// @param payee Address of payee
  /// @param _shares Shares to send user
  function addPayee(
    address payee
  , uint256 _shares
  ) external;

  /// @dev This removes a payee
  /// @param payee Address of payee to remove
  /// @dev use payPayees() prior to use if anything is on the contract
  function removePayee(
    address payee
  ) external;

  /// @dev This removes all payees
  /// @dev use payPayees() prior to use if anything is on the contract
  function clearPayees()
    external;
}

File 3 of 24 : MaxAccess.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: [Not an EIP]: MaxFlow's 173/Dev/Roles Interface
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for MaxAccess
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "./IMAX173.sol";
import "./IMAXDEV.sol";
import "./IRoles.sol";

interface MaxAccess is IMAX173
                     , IMAXDEV
                     , IRoles {

  ///@dev this just imports all 3 and pushes to Implementation

}

File 4 of 24 : IRoles.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: [Not an EIP]: Contract Roles Standard
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for MaxAccess version of Roles
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "../../eip/165/IERC165.sol";

interface IRoles 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
  function renounceRole(
    bytes4 role
  ) external;
}

File 5 of 24 : IMAXDEV.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#* 
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=: 
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%* 
 *
 * @title: [Not an EIP]: Contract Developer Standard
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for onlyDev() role
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "../../eip/165/IERC165.sol";

interface IMAXDEV 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;

  /// @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 6 of 24 : IMAX173.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#* 
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=: 
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%* 
 *
 * @title:  EIP-173: Contract Ownership Standard, MaxFlowO2's extension
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Interface for enhancing EIP-173
 * @custom:change-log UUPS Upgradable
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "../../eip/173/IERC173.sol";

interface IMAX173 is IERC173 {

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

  /// @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 7 of 24 : IERC2981Admin.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: EIP-2981: NFT Royalty Standard, admin extension
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: the ERC-165 identifier for this interface is unknown.
 * @custom:source https://eips.ethereum.org/EIPS/eip-2981
 * @custom:change-log MIT -> Apache-2.0
 *
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright and related rights waived via CC0.                               *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "../../eip/2981/IERC2981.sol";

interface IERC2981Admin is IERC2981 {

  /// @dev function (state storage) sets the royalty data for a token
  /// @param tokenId uint256 for the token
  /// @param receiver address for the royalty reciever for token
  /// @param permille uint16 for the permille of royalties 20 -> 2.0%
  function setRoyalties(
    uint256 tokenId
  , address receiver
  , uint16 permille
  ) external;

  /// @dev function (state storage) revokes the royalty data for a token
  /// @param tokenId uint256 for the token
  function revokeRoyalties(
    uint256 tokenId
  ) external;

  /// @dev function (state storage) sets the royalty data for a collection
  /// @param receiver address for the royalty reciever for token
  /// @param permille uint16 for the permille of royalties 20 -> 2.0%
  function setRoyalties(
    address receiver
  , uint16 permille
  ) external;

  /// @dev function (state storage) revokes the royalty data for a collection
  function revokeRoyalties()
    external;
}

File 8 of 24 : Strings.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: Strings
 * @author: OpenZeppelin
 * @notice: Strings Library
 * @custom:source https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts-upgradeable/v4.7.3/contracts/utils/StringsUpgradeable.sol
 * @custom:change-log Readable, External/Public, Removed code comments, MIT -> Apache-2.0
 * @custom:change-log Added MaxSplaining
 * @custom:error-code Str:1 "hex length insufficient"
 *
 * Include with 'using Strings for <insert type>'
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

library Strings {

  bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
  uint8 private constant _ADDRESS_LENGTH = 20;

  error MaxSplaining(string reason);

  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);
  }

  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);
  }

  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;
    }
    if (value != 0) {
      revert MaxSplaining({
        reason: "Str:1"
      });
    }
    return string(buffer);
  }

  function toHexString(
    address addr
  ) internal
    pure
    returns (string memory) {
    return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
  }
}

File 9 of 24 : Roles.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: Roles.sol
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Library for MaxAcess.sol
 * @custom:change-log cleaned up variables
 *
 * Include with 'using Roles for Roles.Role;'
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

library Roles {

  bytes4 constant internal DEVS = 0xca4b208b;
  bytes4 constant internal OWNERS = 0x8da5cb5b;
  bytes4 constant internal ADMIN = 0xf851a440;

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

  event RoleChanged(bytes4 _role, address _user, bool _status);
  event AdminTransferred(address indexed previousAdmin, address indexed newAdmin);
  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
  event DeveloperTransferred(address indexed previousDeveloper, address indexed newDeveloper);

  error Unauthorized();

  function add(
    Role storage role
  , bytes4 userRole
  , address account
  ) internal {
    if (account == address(0)) {
      revert Unauthorized();
    } else if (has(role, userRole, account)) {
      revert Unauthorized();
    }
    role.bearer[account][userRole] = true;
    emit RoleChanged(userRole, account, true);
  }

  function remove(
    Role storage role
  , bytes4 userRole
  , address account
  ) internal {
    if (account == address(0)) {
      revert Unauthorized();
    } else if (!has(role, userRole, account)) {
      revert Unauthorized();
    }
    role.bearer[account][userRole] = false;
    emit RoleChanged(userRole, account, false);
  }

  function has(
    Role storage role
  , bytes4  userRole
  , address account
  ) internal
    view
    returns (bool) {
    if (account == address(0)) {
      revert Unauthorized();
    }
    return role.bearer[account][userRole];
  }

  function setAdmin(
    Role storage role
  , address account
  ) internal {
    if (has(role, ADMIN, account)) {
      address old = role.admin;
      role.admin = account;
      emit AdminTransferred(old, role.admin);
    } else if (account == address(0)) {
      address old = role.admin;
      role.admin = account;
      emit AdminTransferred(old, role.admin);
    } else {
      revert Unauthorized();
    }
  }

  function setDeveloper(
    Role storage role
  , address account
  ) internal {
    if (has(role, DEVS, account)) {
      address old = role.developer;
      role.developer = account;
      emit DeveloperTransferred(old, role.developer);
    } else if (account == address(0)) {
      address old = role.admin;
      role.admin = account;
      emit AdminTransferred(old, role.admin);
    } else {
      revert Unauthorized();
    }
  }

  function setOwner(
    Role storage role
  , address account
  ) internal {
    if (has(role, OWNERS, account)) {
      address old = role.owner;
      role.owner = account;
      emit OwnershipTransferred(old, role.owner);
    } else if (account == address(0)) {
      address old = role.admin;
      role.admin = account;
      emit AdminTransferred(old, role.admin);
    } else {
      revert Unauthorized();
    }
  }

  function getAdmin(
    Role storage role
  ) internal 
    view
    returns (address) {
    return role.admin;
  }

  function getDeveloper(
    Role storage role
  ) internal
    view
    returns (address) {
    return role.developer;
  }

  function getOwner(
    Role storage role
  ) internal
    view
    returns (address) {
    return role.owner;
  }
}

File 10 of 24 : Payments.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: [Not an EIP] Payment Splitter
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Library for two structs one with "ERC-20's" and one without
 * @custom:error-code PS:1 No Shares for address
 * @custom:error-code PS:2 No payment due for address
 * @custom:error-code PS:3 Can not use address(0)
 * @custom:error-code PS:4 Shares can not be 0
 * @custom:error-code PS:5 User has shares already
 * @custom:error-code PS:6 User not in payees
 * @custom:change-log added custom error-codes above
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

library Payments {

  struct GasTokens {
    uint256 totalShares;
    uint256 totalReleased;
    mapping(address => uint256) shares;
    mapping(address => uint256) released;
    address[] payees;
  }

  event PayeeAdded(address account, uint256 _shares);
  event PayeeRemoved(address account, uint256 _shares);
  event PayeesReset();
  event PaymentReleased(address to, uint256 amount);

  error MaxSplaining(string reason);

  function findIndex(
    address[] memory array
  , address query
  ) internal
    pure
    returns (bool found, uint256 index) {
    uint256 len = array.length;
    for (uint x = 0; x < len;) {
      if (array[x] == query) {
        found = true;
        index = x;
      }
      unchecked { ++x; }
    }
  }

  function getTotalReleased(
    GasTokens storage gasTokens
  ) internal
    view
    returns (uint256) {
    return gasTokens.totalReleased;
  }

  function getTotalShares(
    GasTokens storage gasTokens
  ) internal
    view
    returns (uint256) {
    return gasTokens.totalShares;
  }

  function payeeShares(
    GasTokens storage gasTokens
  , address payee
  ) internal
    view
    returns (uint256) {
    return gasTokens.shares[payee];
  }

  function payeeReleased(
    GasTokens storage gasTokens
  , address payee
  ) internal
    view
    returns (uint256) {
    return gasTokens.released[payee];
  }

  function payeeIndex(
    GasTokens storage gasTokens
  , address payee
  ) internal
    view
    returns (uint256) {
    (bool found, uint256 index) = findIndex(gasTokens.payees, payee);
    if (found) {
      return index;
    } else {
      revert MaxSplaining({
        reason: "PS:6"
      });
    }
  }

  function allPayees(
    GasTokens storage gasTokens
  ) internal
    view
    returns (address[] memory) {
    return gasTokens.payees;
  }

  function addPayee(
    GasTokens storage gasTokens
  , address payee
  , uint256 _shares
  ) internal {
    if (payee == address(0)) {
      revert MaxSplaining({
        reason: "PS:3"
      });
    } else if (_shares == 0) {
      revert MaxSplaining({
        reason: "PS:4"
      });
    } else if (gasTokens.shares[payee] > 0) {
      revert MaxSplaining({
        reason: "PS:5"
      });
    }
    gasTokens.payees.push(payee);
    gasTokens.shares[payee] = _shares;
    gasTokens.totalShares += _shares;
    emit PayeeAdded(payee, _shares);
  }

  function getPayees(
    GasTokens storage gasTokens
  ) internal
    view
    returns (address[] memory) {
    return gasTokens.payees;
  }

  function removePayee(
    GasTokens storage gasTokens
  , address payee
  ) internal {
    if (payee == address(0)) {
      revert MaxSplaining({
        reason: "PS:3"
      });
    }
    uint256 whacked = payeeIndex(gasTokens, payee);
    address last = gasTokens.payees[gasTokens.payees.length -1];
    gasTokens.payees[whacked] = last;
    gasTokens.payees.pop();
    uint256 whackedShares = gasTokens.shares[payee];
    delete gasTokens.shares[payee];
    gasTokens.totalShares -= whackedShares;
    emit PayeeRemoved(payee, whackedShares);
  }

  function clearPayees(
    GasTokens storage gasTokens
  ) internal {
    uint256 len = gasTokens.payees.length;
    for (uint x = 0; x < len;) {
      address whacked = gasTokens.payees[x];
      delete gasTokens.shares[whacked];
      unchecked { ++x; }
    }
    delete gasTokens.totalShares;
    delete gasTokens.payees;
    emit PayeesReset();
  }

  function processPayment(
    GasTokens storage gasTokens
  , address payee
  , uint256 payment
  ) internal {
    gasTokens.totalReleased += payment;
    gasTokens.released[payee] += payment;
    emit PaymentReleased(payee, payment);
  }
}

File 11 of 24 : Lists.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: [Not an EIP]: Access lists
 * @author: @MaxFlowO2 on bird app/GitHub
 * @notice: Formerly whitelists, now allowlist, or whatever it's called.
 * @custom:change-log removed end variable/functions (un-needed)
 * @custom:change-log variables renamed from lib whitelist
 * @custom:change-log internal -> internal
 * @custom:error-code A:1 "(user) is already whitelisted."
 * @custom:error-code A:2 "(user) is not whitelisted."
 * @custom:error-code A:3 "Whitelist already enabled."
 * @custom:error-code A:4 "Whitelist already disabled."
 * @custom:change-log added custom error codes
 * @custom:change-log removed import "./Strings.sol"; (un-needed)
 *
 * Include with 'using Lists for Lists.Access;'
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "./CountersV2.sol";

library Lists {

  using CountersV2 for CountersV2.Counter;

  event ListChanged(bool _old, bool _new, address _address);
  event ListStatus(bool _old, bool _new);

  error MaxSplaining(string reason);

  struct Access {
    bool _status;
    CountersV2.Counter added;
    CountersV2.Counter removed;
    mapping(address => bool) allowed;
  }

  function add(
    Access storage list
  , address user
  ) internal {
    if (list.allowed[user]) {
      revert  MaxSplaining({
        reason : "A:1"
      });
    }
    // since now all previous values are false no need for another variable
    // and add them to the list!
    list.allowed[user] = true;
    // increment counter
    list.added.increment();
    // emit event
    emit ListChanged(false, list.allowed[user], user);
  }

  function remove(
    Access storage list
  , address user
  ) internal {
    if (!list.allowed[user]) {
      revert  MaxSplaining({
        reason : "A:2"
      });
    }
    // since now all previous values are true no need for another variable
    // and remove them from the list!
    list.allowed[user] = false;
    // increment counter
    list.removed.increment();
    // emit event
    emit ListChanged(true, list.allowed[user], user);
  }

  function enable(
    Access storage list
  ) internal {
    if (list._status) {
      revert  MaxSplaining({
        reason : "A:3"
      });
    }
    list._status = true;
    emit ListStatus(false, list._status);
  }

  function disable(
    Access storage list
  ) internal {
    if (!list._status) {
      revert  MaxSplaining({
        reason : "A:4"
      });
    }
    list._status = false;
    emit ListStatus(true, list._status);
  }

  function status(
    Access storage list
  ) internal
    view
    returns (bool) {
    return list._status;
  }

  function totalAdded(
    Access storage list
  ) internal
    view
    returns (uint) {
    return list.added.current();
  }

  function totalRemoved(
    Access storage list
  ) internal
    view
    returns (uint) {
    return list.removed.current();
  }

  function onList(
    Access storage list
  , address user
  ) internal
    view
    returns (bool) {
    return list.allowed[user];
  }
}

File 12 of 24 : CountersV2.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: CountersV2.sol
 * @author Matt Condon (@shrugs)
 * @notice 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.
 * @custom:change-log MIT -> Apache-2.0
 * @custom:change-log Edited for more NFT functionality added .set(uint)
 * @custom:change-log added event CounterNumberChangedTo(uint _number).
 * @custom:change-log added error MaxSplaining(string reason).
 * @custom:change-log internal -> internal functions
 * @custom:error-code C2:1 "No negatives in uints" - overflow protection
 *
 * Include with `using CountersV2 for CountersV2.Counter;`
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

library CountersV2 {

  struct Counter {
    uint256 value;
  }

  event CounterNumberChangedTo(uint _number);

  error MaxSplaining(string reason);

  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 {
    if (counter.value == 0) {
      revert MaxSplaining({
        reason : "C2:1"
      });
    }
    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 13 of 24 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

    /**
     * @notice : Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.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");
    }

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

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

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

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

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

    /**
     * @notice : Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

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

    /**
     * @notice : Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

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

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

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 14 of 24 : 721.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: Library 721
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Library for EIP 721
 * @custom:error-code L:1 "non-existent tokenId" 
 * @custom:error-code L:2 "approval to current owner"
 * @custom:error-code L:3 "approve caller is not token owner nor approved for all"
 * @custom:error-code L:4 "approve to caller"
 * @custom:error-code L:5 "caller is not token owner nor approved"
 * @custom:error-code L:6 "transfer from incorrect owner"
 * @custom:error-code L:7 "transfer to the zero address"
 * @custom:error-code L:8 "mint to the zero address"
 * @custom:error-code L:9 "token already minted"
 * @custom:change-log Custom errors added above
 *
 * Include with 'using Lib721 for Lib721.Token;'
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "./Strings.sol";
import "./CountersV2.sol";

library Lib721 {

  using Strings for uint256;
  using CountersV2 for CountersV2.Counter;

  struct Token {
    mapping(uint256 => address) owners;
    mapping(address => uint256) balances;
    mapping(uint256 => address) tokenApprovals;
    mapping(address => mapping(address => bool)) operatorApprovals;
    string name;
    string symbol;
    string baseURI;
    CountersV2.Counter supply;
  }

  event NameSet(string name);
  event SymbolSet(string symbol);
  event NewBaseURI(string baseURI);

  error MaxSplaining(string reason);

  function getBalanceOf(
    Token storage token
  , address owner
  ) internal
    view
    returns (uint256) {
    return token.balances[owner];
  }

  function getOwnerOf(
    Token storage token
  , uint256 tokenId
  ) internal 
    view
    returns (address) {
    return token.owners[tokenId];
  }

  function setName(
    Token storage token
  , string memory newName
  ) internal {
    token.name = newName;
    emit NameSet(newName);
  }

  function getName(
   Token storage token
  ) internal
    view
    returns (string memory) {
    return token.name;
  }

  function setSymbol(
    Token storage token
  , string memory newSymbol
  ) internal {
    token.symbol = newSymbol;
    emit SymbolSet(newSymbol);
  }

  function getSymbol(
   Token storage token
  ) internal
    view
    returns (string memory) {
    return token.symbol;
  }

  function getSupply(
   Token storage token
  ) internal
    view
    returns (uint256) {
    return token.supply.current();
  }

  function setBaseURI(
    Token storage token
  , string memory newURI
  ) internal {
    token.baseURI = newURI;
    emit NewBaseURI(newURI);
  }

  function getTokenURI(
    Token storage token
  , uint256 tokenId
  ) internal
    view
    returns (string memory) {
    if (getOwnerOf(token, tokenId) == address(0)) {
      revert MaxSplaining({
        reason: "L:1"
      });
    }
    return bytes(token.baseURI).length > 0 ? string(abi.encodePacked(token.baseURI, tokenId.toString())) : "";
  }

  function setApprove(
    Token storage token
  , address to
  , address by
  , uint256 tokenId
  ) internal {
    address owner = getOwnerOf(token, tokenId);
    if (to == owner) {
      revert MaxSplaining({
        reason: "L:2"
      });
    } else if (!isApprovedOrOwner(token, by, tokenId)) {
      revert MaxSplaining({
        reason: "L:3"
      });
    }
    token.tokenApprovals[tokenId] = to;
  }

  function getApproved(
    Token storage token
  , uint256 tokenId
  ) internal
    view
    returns (address) {
    if (getOwnerOf(token, tokenId) == address(0)) {
      revert MaxSplaining({
        reason: "L:1"
      });
    }
    return token.tokenApprovals[tokenId];
  }

  function setApprovalForAll(
    Token storage token
  , address operator
  , address from
  , bool approved
  ) internal {
    if (from == operator) {
      revert MaxSplaining({
        reason: "L:4"
      });
    }
    token.operatorApprovals[from][operator] = approved;
  }

  function isApprovedForAll(
    Token storage token
  , address owner
  , address operator
  ) internal
    view
    returns (bool) {
    return token.operatorApprovals[owner][operator];
  }

  function isApprovedOrOwner(
    Token storage token
  , address spender
  , uint256 tokenId
  ) internal
    view
    returns (bool) {
    address owner = getOwnerOf(token, tokenId);
    return (
      spender == owner ||
      isApprovedForAll(token, owner, spender) ||
      getApproved(token, tokenId) == spender
    );
  }

  function doTransferFrom(
    Token storage token
  , address from
  , address to
  , address by
  , uint256 tokenId
  ) internal {
    if (!isApprovedOrOwner(token, by, tokenId)) {
      revert MaxSplaining({
        reason: "L:5"
      });
    }
    address owner = getOwnerOf(token, tokenId);
    if (owner != from) {
      revert MaxSplaining({
        reason: "L:6"
      });
    } else if (to == address(0)) {
      revert MaxSplaining({
        reason: "L:7"
      });
    }
    // Clear approvals from the previous owner
    setApprove(token, address(0), by, tokenId);
    // Change balances
    token.balances[from] -= 1;
    token.balances[to] += 1;
    // Move tokenId
    token.owners[tokenId] = to;
  }

  function mint(
    Token storage token
  , address to
  , uint256 tokenId
  ) internal {
    if (to == address(0)) {
      revert MaxSplaining({
        reason: "L:8"
      });
    } else if (getOwnerOf(token, tokenId) != address(0)) {
      revert MaxSplaining({
        reason: "L:9"
      });
    }
    token.balances[to] += 1;
    token.owners[tokenId] = to;
    token.supply.increment();
  }

  function burn(
    Token storage token
  , address by
  , uint256 tokenId
  ) internal {
    address owner = getOwnerOf(token, tokenId);
    // Clear approvals
    setApprove(token, address(0), by, tokenId);
    // Change balances
    token.balances[owner] -= 1;
    delete token.owners[tokenId];
    token.supply.decrement();
  }
}

File 15 of 24 : 2981c.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: Library 2981
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice: Library for EIP 2981
 * @custom:error-code R:1 Permille out of bounds
 * @custom:change-log Custom errors added above
 *
 * Include with 'using Lib2981 for Lib2981.Royalties;' -- unique per collection
 * Include with 'using Lib2981 for Lib2981.MappedRoyalties;' -- unique per token
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

library Lib2981c {

  struct Royalties {
    address receiver;
    uint16 permille;
  }

  event RoyaltiesSet(uint256 token, address recipient, uint16 value);
  event RoyaltiesSet(address recipient, uint16 value);

  error MaxSplaining(string reason);

  function setRoyalties(
    Royalties storage royalties
  , address receiver
  , uint16 permille
  ) internal {
    if (permille >= 1000 ||  permille == 0) {
      revert MaxSplaining({
        reason: "R:1"
      });
    }
    royalties.receiver = receiver;
    royalties.permille = permille;
    emit RoyaltiesSet(
           royalties.receiver
         , royalties.permille
         );
  }

  function revokeRoyalties(
    Royalties storage royalties
  ) internal {
    delete royalties.receiver;
    delete royalties.permille;
    emit RoyaltiesSet(
           royalties.receiver
         , royalties.permille
         );
  }

  function royaltyInfo(
    Royalties storage royalties
  , uint256 tokenId
  , uint256 salePrice
  ) internal
    view
    returns (
      address receiver
    , uint256 royaltyAmount
    ) {
    receiver = royalties.receiver;
    royaltyAmount = salePrice * royalties.permille / 1000;
  }
}

File 16 of 24 : IERC721TokenReceiver.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: ERC-721 Non-Fungible Token Standard, required wallet interface
 * @author: William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs
 * @notice: the ERC-165 identifier for this interface is 0x150b7a02.
 * @custom:source https://eips.ethereum.org/EIPS/eip-721
 * @custom:change-log interface ERC721TokenReceiver -> interface IERC721TokenReceiver
 * @custom:change-log readability enhanced
 * @custom:change-log MIT -> Apache-2.0
 * @custom:change-log TypeError: Data location must be "memory" or "calldata" for parameter (line 60)
 *
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright and related rights waived via CC0.                               *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "../165/IERC165.sol";

interface IERC721TokenReceiver is IERC165 {

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

File 17 of 24 : IERC721Metadata.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @author: William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs
 * @notice: the ERC-165 identifier for this interface is 0x5b5e139f.
 * @custom:source https://eips.ethereum.org/EIPS/eip-721
 * @custom:change-log interface ERC721Metadata * is ERC721 * -> interface IERC721Metadata
 * @custom:change-log readability enhanced
 * @custom:change-log MIT -> Apache-2.0
 * @custom:change-log  Data location must be "memory" or "calldata" for return parameter (lines 48, 54, 64)
 *
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright and related rights waived via CC0.                               *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "./IERC721.sol";

interface IERC721Metadata is IERC721 {

  /// @notice A descriptive name for a collection of NFTs in this contract
  function name()
    external
    view
    returns (string memory _name);

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

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

File 18 of 24 : IERC721.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: ERC-721 Non-Fungible Token Standard
 * @author: William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs
 * @notice: the ERC-165 identifier for this interface is 0x80ac58cd.
 * @custom:source https://eips.ethereum.org/EIPS/eip-721
 * @custom:change-log interface ERC721 * is ERC165 * -> interface IERC721
 * @custom:change-log removed payable from IERC721 
 * @custom:change-log removed events from IERC721 (handled in Lib721)
 * @custom:change-log readability enhanced
 * @custom:change-log MIT -> Apache-2.0
 * @custom:change-log TypeError: Data location must be "memory" or "calldata" for parameter (line 84)
 *
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright and related rights waived via CC0.                               *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "../165/IERC165.sol";

interface IERC721 is IERC165 {

  /// @dev This emits when ownership of any NFT changes by any mechanism.
  ///  This event emits when NFTs are created (`from` == 0) and destroyed
  ///  (`to` == 0). Exception: during contract creation, any number of NFTs
  ///  may be created and assigned without emitting Transfer. At the time of
  ///  any transfer, the approved address for that NFT (if any) is reset to none.
  event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);

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

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

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

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

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

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

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

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

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

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

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

File 19 of 24 : IERC2981.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: EIP-2981: NFT Royalty Standard
 * @author: Zach Burks, James Morgan, Blaine Malone, James Seibel
 * @notice: the ERC-165 identifier for this interface is 0x2a55205a.
 * @custom:source https://eips.ethereum.org/EIPS/eip-2981
 * @custom:change-log MIT -> Apache-2.0
 *
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright and related rights waived via CC0.                               *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "../165/IERC165.sol";

interface IERC2981 is IERC165 {

  /// ERC165 bytes to add to interface array - set in parent contract
  /// implementing this standard

  /// bytes4(keccak256("royaltyInfo(uint256,uint256)")) == 0x2a55205a
  /// bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;
  /// _registerInterface(_INTERFACE_ID_ERC2981);

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

File 20 of 24 : IERC173.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: EIP-173: Contract Ownership Standard
 * @author: Nick Mudge, Dan Finlay
 * @notice: This specification defines standard functions for owning or controlling a contract.
 *          the ERC-165 identifier for this interface is 0x7f5828d0
 * @custom:URI https://eips.ethereum.org/EIPS/eip-173
 * @custom:change-log MIT -> Apache-2.0
 * @custom:change-log readability modification
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright and related rights waived via CC0.                               *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

import "../../eip/165/IERC165.sol";

interface IERC173 is IERC165 {

  /// @dev This emits when ownership of a contract changes.    
  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  /// @notice Get the address of the owner    
  /// @return The address of the owner.
  function owner()
    view
    external
    returns(address);
	
  /// @notice Set the address of the new owner of the contract
  /// @dev Set _newOwner to address(0) to renounce any ownership.
  /// @param _newOwner The address of the new owner of the contract    
  function transferOwnership(
    address _newOwner
  ) external;	
}

File 21 of 24 : IERC165.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: EIP-165: Standard Interface Detection
 * @author: Christian Reitwießner, Nick Johnson, Fabian Vogelsteller, Jordi Baylina, Konrad Feldmeier, William Entriken
 * @notice: Creates a standard method to publish and detect what interfaces a smart contract implements.
 * @custom:source https://eips.ethereum.org/EIPS/eip-165
 * @custom:change-log interface ERC165 -> interface IERC165
 * @custom:change-log readability enhanced
 * @custom:change-log MIT -> Apache-2.0

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright and related rights waived via CC0.                               *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.0 <0.9.0;

interface IERC165 {

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

File 22 of 24 : Max-721-2981-PSv2.sol
/*     +%%#-                           ##.        =+.    .+#%#+:       *%%#:    .**+-      =+
 *   .%@@*#*:                          @@: *%-   #%*=  .*@@=.  =%.   .%@@*%*   +@@=+=%   .%##
 *  .%@@- -=+                         *@% :@@-  #@=#  -@@*     +@-  :@@@: ==* -%%. ***   #@=*
 *  %@@:  -.*  :.                    +@@-.#@#  =@%#.   :.     -@*  :@@@.  -:# .%. *@#   *@#*
 * *%@-   +++ +@#.-- .*%*. .#@@*@#  %@@%*#@@: .@@=-.         -%-   #%@:   +*-   =*@*   -@%=:
 * @@%   =##  +@@#-..%%:%.-@@=-@@+  ..   +@%  #@#*+@:      .*=     @@%   =#*   -*. +#. %@#+*@
 * @@#  +@*   #@#  +@@. -+@@+#*@% =#:    #@= :@@-.%#      -=.  :   @@# .*@*  =@=  :*@:=@@-:@+
 * -#%+@#-  :@#@@+%++@*@*:=%+..%%#=      *@  *@++##.    =%@%@%%#-  =#%+@#-   :*+**+=: %%++%*
 *
 * @title: [EIP721] Max-721 Implementation, using EIP 1822
 * @author: Max Flow O2 -> @MaxFlowO2 on bird app/GitHub
 * @notice ERC721 Implementation with:
 *         Enhanced EIP173 - Ownership via roles
 *         EIP2981 - NFT Royalties
 *         PsuedoRandom Engine - Expansion of BAYC engine
 *         TimeCop + Lists - For presales
 *         PaymentSplitter v2 - For "ETH" payments
 */

// SPDX-License-Identifier: Apache-2.0

/******************************************************************************
 * Copyright 2022 Max Flow O2                                                 *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License");            *
 * you may not use this file except in compliance with the License.           *
 * You may obtain a copy of the License at                                    *
 *                                                                            *
 *     http://www.apache.org/licenses/LICENSE-2.0                             *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

pragma solidity >=0.8.17 <0.9.0;

import "./eip/721/IERC721TokenReceiver.sol";//
import "./eip/721/IERC721Metadata.sol";//
import "./eip/721/IERC721.sol";//
import "./modules/2981/IERC2981Admin.sol";//
import "./modules/access/MaxAccess.sol";//
import "./modules/splitter/ISplitter.sol";//
import "./lib/Address.sol";//
import "./lib/721.sol";//
import "./lib/Roles.sol";//
import "./lib/2981c.sol";//
import "./lib/Payments.sol";//

abstract contract Max721 is MaxAccess
                          , IERC721
                          , IERC721Metadata
                          , IERC721TokenReceiver
                          , IERC2981Admin
                          , ISplitter {

  using Lib721 for Lib721.Token;
  using Roles for Roles.Role;
  using Lib2981c for Lib2981c.Royalties;
  using Payments for Payments.GasTokens;
  using Address for address;

  // The Structs...
  Lib721.Token internal token721;
  Roles.Role internal contractRoles;
  Lib2981c.Royalties internal royalties;
  Payments.GasTokens internal splitter;

  // The rest (got to have a few)
  bytes4 constant internal DEVS = 0xca4b208b;
  bytes4 constant internal PENDING_DEVS = 0xca4b208a; // DEVS - 1
  bytes4 constant internal OWNERS = 0x8da5cb5b;
  bytes4 constant internal PENDING_OWNERS = 0x8da5cb5a; // OWNERS - 1
  bytes4 constant internal ADMIN = 0xf851a440;

  uint256 startTime; // Set to opening (can +48h for secondary)
  uint256 period; // Set to the period
  uint256 maxCap; // Cpacity of minter
  bytes32 internal admin;
  mapping(uint256 => uint256) internal claimedAdmin;
  bytes32 internal homies;
  mapping(uint256 => uint256) internal claimedHomies;
  bytes32 internal normies;
  mapping(uint256 => uint256) internal claimedNormies;
  string internal contractURL;
  string internal image;
  string internal description;
  string internal animationURI;
  uint256 public normiesCost = 0.069 ether;
  uint256 public publicCost = 0.1 ether;

  event PaymentReceived(address indexed _payee, uint256 _amount);

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

  ///////////////////////
  /// MAX-721: Modifiers
  ///////////////////////

  modifier onlyRole(bytes4 role) {
    if (contractRoles.has(role, msg.sender) || contractRoles.has(ADMIN, msg.sender)) {
      _;
    } else {
    revert Unauthorized();
    }
  }

  modifier onlyOwner() {
    if (contractRoles.has(OWNERS, msg.sender)) {
      _;
    } else {
    revert Unauthorized();
    }
  }

  modifier onlyDev() {
    if (contractRoles.has(DEVS, msg.sender)) {
      _;
    } else {
    revert Unauthorized();
    }
  }

  ///////////////////////
  /// MAX-721: Internals
  ///////////////////////

  function __Max721_init(
    string memory _name
  , string memory _symbol
  , address _admin
  , address _dev
  , address _owner
  ) internal {
    token721.setName(_name);
    token721.setSymbol(_symbol);
    contractRoles.add(ADMIN, _admin);
    contractRoles.setAdmin(_admin);
    contractRoles.add(DEVS, _dev);
    contractRoles.setDeveloper(_dev);
    contractRoles.add(OWNERS, _owner);
    contractRoles.setOwner(_owner);
  }

  function safeHook(
    address from,
    address to,
    uint256 tokenId,
    bytes memory data
  ) internal
    returns (bool) {
    if (to.isContract()) {
      try IERC721TokenReceiver(to).onERC721Received(msg.sender, from, tokenId, data)
        returns (bytes4 retval) {
        return retval == IERC721TokenReceiver.onERC721Received.selector;
      } catch (bytes memory reason) {
        if (reason.length == 0) {
          revert Unauthorized();
        } else {
          assembly {
            revert(add(32, reason), mload(reason))
          }
        }
      }
    } else {
      return true;
    }
  }

  /////////////////////////////////////////
  /// EIP-173: Contract Ownership Standard
  /////////////////////////////////////////

  /// @notice Get the address of the owner    
  /// @return The address of the owner.
  function owner()
    view
    external
    returns(address) {
    return contractRoles.getOwner();
  }
	
  /// @notice Set the address of the new owner of the contract
  /// @dev Set _newOwner to address(0) to renounce any ownership.
  /// @param _newOwner The address of the new owner of the contract    
  function transferOwnership(
    address _newOwner
  ) external
    onlyRole(OWNERS) {
    contractRoles.add(OWNERS, _newOwner);
    contractRoles.setOwner(_newOwner);
    contractRoles.remove(OWNERS, msg.sender);
  }

  ////////////////////////////////////////////////////////////////
  /// EIP-173: Contract Ownership Standard, MaxFlowO2's extension
  ////////////////////////////////////////////////////////////////

  /// @dev This is the classic "EIP-173" method of renouncing onlyOwner()  
  function renounceOwnership()
    external 
    onlyRole(OWNERS) {
    contractRoles.setOwner(address(0));
    contractRoles.remove(OWNERS, msg.sender);
  }

  /// @dev This accepts the push-pull method of onlyOwner()
  function acceptOwnership()
    external
    onlyRole(PENDING_OWNERS) {
    contractRoles.add(OWNERS, msg.sender);
    contractRoles.setOwner(msg.sender);
    contractRoles.remove(PENDING_OWNERS, msg.sender);
  }

  /// @dev This declines the push-pull method of onlyOwner()
  function declineOwnership()
    external
    onlyRole(PENDING_OWNERS) {
    contractRoles.remove(PENDING_OWNERS, msg.sender);
  }

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

  //////////////////////////////////////////////
  /// [Not an EIP]: Contract Developer Standard
  //////////////////////////////////////////////

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

  /// @dev This renounces your role as onlyDev()
  function renounceDeveloper()
    external
    onlyRole(DEVS) {
    contractRoles.setDeveloper(address(0));
    contractRoles.remove(DEVS, msg.sender);
  }

  /// @dev Classic "EIP-173" but for onlyDev()
  /// @param newDeveloper: addres of new pending Developer role
  function transferDeveloper(
    address newDeveloper
  ) external
    onlyRole(DEVS) {
    contractRoles.add(DEVS, newDeveloper);
    contractRoles.setDeveloper(newDeveloper);
    contractRoles.remove(DEVS, msg.sender);
  }

  /// @dev This accepts the push-pull method of onlyDev()
  function acceptDeveloper()
    external
    onlyRole(PENDING_DEVS) {
    contractRoles.add(DEVS, msg.sender);
    contractRoles.setDeveloper(msg.sender);
    contractRoles.remove(PENDING_DEVS, msg.sender);
  }

  /// @dev This declines the push-pull method of onlyDev()
  function declineDeveloper()
    external
    onlyRole(PENDING_DEVS) {
    contractRoles.remove(PENDING_DEVS, msg.sender);
  }

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

  //////////////////////////////////////////
  /// [Not an EIP]: Contract Roles Standard
  //////////////////////////////////////////

  /// @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) {
    return contractRoles.has(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 
    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
    onlyRole(role) {
    if (role == PENDING_DEVS || role == PENDING_OWNERS) {
      revert Unauthorized();
    } else {
      contractRoles.add(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
    onlyRole(role) {
    if (role == PENDING_DEVS || role == PENDING_OWNERS) {
      if (account == msg.sender) {
        contractRoles.remove(role, account);
      } else {
        revert Unauthorized();
      }
    } else {
      contractRoles.remove(role, account);
    }
  }

  /// @dev Renounces `role` from `account`
  /// @param role: Bytes4 of a role
  function renounceRole(
    bytes4 role
  ) external
    onlyRole(role) {
    contractRoles.remove(role, msg.sender);
  }

  ////////////////////////////////////////////////////////////////////////
  /// ERC-721 Non-Fungible Token Standard, optional enumeration extension
  /// @dev may be added, but not fully supported see ERC-165 below
  ////////////////////////////////////////////////////////////////////////

  /// @notice Count NFTs tracked by this contract
  /// @return A count of valid NFTs tracked by this contract, where each one of
  ///  them has an assigned and queryable owner not equal to the zero address
  function totalSupply()
    external
    view
    virtual
    returns (uint256) {
    return token721.getSupply();
  }

  /////////////////////////////////////////////////
  /// ERC721 Metadata, optional metadata extension
  /////////////////////////////////////////////////

  /// @notice A descriptive name for a collection of NFTs in this contract
  function name()
    external
    view
    virtual
    override
    returns (string memory _name) {
    return token721.getName();
  }

  /// @notice An abbreviated name for NFTs in this contract
  function symbol()
    external
    view
    virtual
    override
    returns (string memory _symbol) {
    return token721.getSymbol();
  }

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

  ////////////////////////////////////////
  /// ERC-721 Non-Fungible Token Standard
  ////////////////////////////////////////

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

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

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

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

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

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

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

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

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

  ///////////////////////////////////////////////////////////////////
  /// ERC-721 Non-Fungible Token Standard, required wallet interface
  /// @dev This is to disable all safe transfers to this contract
  ///////////////////////////////////////////////////////////////////

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

  ///////////////////////////////////
  /// EIP-2981: NFT Royalty Standard
  ///////////////////////////////////

  /// @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
    virtual
    override
    returns (
      address receiver,
      uint256 royaltyAmount
    ) {
    (receiver, royaltyAmount) = royalties.royaltyInfo(_tokenId,_salePrice);
  }

  ////////////////////////////////////////////////////
  /// EIP-2981: NFT Royalty Standard, admin extension
  /// @dev Using the collection standard
  ////////////////////////////////////////////////////

  /// @dev function (state storage) sets the royalty data for a token
  /// @param tokenId uint256 for the token
  /// @param receiver address for the royalty reciever for token
  /// @param permille uint16 for the permille of royalties 20 -> 2.0%
  function setRoyalties(
    uint256 tokenId
  , address receiver
  , uint16 permille
  ) external
    virtual
    override {
    revert Unauthorized();
  }

  /// @dev function (state storage) revokes the royalty data for a token
  /// @param tokenId uint256 for the token
  function revokeRoyalties(
    uint256 tokenId
  ) external
    virtual
    override {
    revert Unauthorized();
  }

  /// @dev function (state storage) sets the royalty data for a collection
  /// @param receiver address for the royalty reciever for token
  /// @param permille uint16 for the permille of royalties 20 -> 2.0%
  function setRoyalties(
    address receiver
  , uint16 permille
  ) external
    virtual
    onlyOwner()
    override {
    royalties.setRoyalties(receiver, permille);
  }

  /// @dev function (state storage) revokes the royalty data for a collection
  function revokeRoyalties()
    external
    virtual
    onlyOwner()
    override {
    royalties.revokeRoyalties();
  }

  ////////////////////////////////////////////////////////////////
  /// [Not an EIP] Payment Splitter, interface for ether payments
  ////////////////////////////////////////////////////////////////

  /// @dev returns total shares
  /// @return uint256 of all shares on contract
  function totalShares()
    external
    view
    virtual
    override
    returns (uint256) {
    return splitter.getTotalShares();
  }

  /// @dev returns shares of an address
  /// @param payee address of payee to return
  /// @return mapping(address => uint) of _shares
  function shares(
    address payee
  ) external
    view
    virtual
    override
    returns (uint256) {
    return splitter.payeeShares(payee);
  }

  /// @dev returns total releases in "eth"
  /// @return uint256 of all "eth" released in wei
  function totalReleased()
    external
    view
    virtual
    override
    returns (uint256) {
    return splitter.getTotalReleased();
  }

  /// @dev returns released "eth" of an payee
  /// @param payee address of payee to look up
  /// @return mapping(address => uint) of _released
  function released(
    address payee
  ) external
    view
    virtual
    override
    returns (uint256) {
    return splitter.payeeReleased(payee);
  }

  /// @dev returns amount of "eth" that can be released to payee
  /// @param payee address of payee to look up
  /// @return uint in wei of "eth" to release
  function releasable(
    address payee
  ) external
    view
    virtual
    override
    returns (uint256) {
    uint totalReceived
      = address(this).balance
      + this.totalReleased();
    return 
      totalReceived
    * this.shares(payee)
    / this.totalShares()
    - this.released(payee);
  }

  /// @dev returns index number of payee
  /// @param payee number of index
  /// @return address at _payees[index]
  function payeeIndex(
    address payee
  ) external
    view
    virtual
    override
    returns (uint256) {
    return splitter.payeeIndex(payee);
  }

  /// @dev this returns the array of payees[]
  /// @return address[] payees
  function payees()
    external
    view
    virtual
    override
    returns (address[] memory) {
    return splitter.getPayees();
  }

  /// @dev this claims all "eth" on contract for msg.sender
  function claim()
    external
    virtual
    override {
    if (this.shares(msg.sender) == 0) {
      revert Unauthorized();
    }
    uint256 payment = this.releasable(msg.sender);
    if (payment == 0) {
      revert Unauthorized();
    }
    splitter.processPayment(msg.sender, payment);
    Address.sendValue(payable(msg.sender), payment);
  }

  /// @dev This pays all payees
  function payClaims()
    external
    virtual
    override {
    address[] memory toPay = splitter.getPayees();
    uint256 len = toPay.length;
    for (uint x = 0 ; x < len ;) {
      uint256 payment = this.releasable(toPay[x]);
      splitter.processPayment(toPay[x], payment);
      Address.sendValue(payable(toPay[x]), payment);
      unchecked { ++x; }
    }
  }

  /// @dev This adds a payee
  /// @param payee Address of payee
  /// @param _shares Shares to send user
  function addPayee(
    address payee
  , uint256 _shares
  ) external
    virtual
    onlyDev()
    override {
    splitter.addPayee(payee, _shares);
  }

  /// @dev This removes a payee
  /// @param payee Address of payee to remove
  /// @notice use payPayees() prior to use if anything is on the contract
  function removePayee(
    address payee
  ) external
    virtual
    onlyDev()
    override {
    splitter.removePayee(payee);
  }

  /// @dev This removes all payees
  /// @notice use payPayees() prior to use if anything is on the contract
  function clearPayees()
    external
    virtual
    onlyDev()
    override {
    splitter.clearPayees();
  }

  //////////////////////////////////////////
  /// EIP-165: Standard Interface Detection
  //////////////////////////////////////////

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

File 23 of 24 : MerkleProof.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The tree and the proofs can be generated using our
 * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
 * You will find a quickstart guide in the readme.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 * OpenZeppelin's JavaScript library generates merkle trees that are safe
 * against this attack out of the box.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Calldata version of {verify}
     *
     * _Available since v4.7._
     */
    function verifyCalldata(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

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

    /**
     * @dev Calldata version of {processProof}
     *
     * _Available since v4.7._
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * _Available since v4.7._
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Calldata version of {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

File 24 of 24 : Base64.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides a set of functions to operate with Base64 strings.
 *
 * _Available since v4.5._
 */
library Base64 {
    /**
     * @dev Base64 Encoding/Decoding Table
     */
    string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    /**
     * @dev Converts a `bytes` to its Bytes64 `string` representation.
     */
    function encode(bytes memory data) internal pure returns (string memory) {
        /**
         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
         */
        if (data.length == 0) return "";

        // Loads the table into memory
        string memory table = _TABLE;

        // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter
        // and split into 4 numbers of 6 bits.
        // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up
        // - `data.length + 2`  -> Round up
        // - `/ 3`              -> Number of 3-bytes chunks
        // - `4 *`              -> 4 characters for each chunk
        string memory result = new string(4 * ((data.length + 2) / 3));

        /// @solidity memory-safe-assembly
        assembly {
            // Prepare the lookup table (skip the first "length" byte)
            let tablePtr := add(table, 1)

            // Prepare result pointer, jump over length
            let resultPtr := add(result, 32)

            // Run over the input, 3 bytes at a time
            for {
                let dataPtr := data
                let endPtr := add(data, mload(data))
            } lt(dataPtr, endPtr) {

            } {
                // Advance 3 bytes
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                // To write each character, shift the 3 bytes (18 bits) chunk
                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
                // and apply logical AND with 0x3F which is the number of
                // the previous character in the ASCII table prior to the Base64 Table
                // The result is then added to the table to get the character to write,
                // and finally write it in the result pointer but with a left shift
                // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits

                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance
            }

            // When data `bytes` is not exactly 3 bytes long
            // it is padded with `=` characters at the end
            switch mod(mload(data), 3)
            case 1 {
                mstore8(sub(resultPtr, 1), 0x3d)
                mstore8(sub(resultPtr, 2), 0x3d)
            }
            case 2 {
                mstore8(sub(resultPtr, 1), 0x3d)
            }
        }

        return result;
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_dev","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_start","type":"uint256"}],"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":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"string","name":"what","type":"string"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_payee","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"PaymentReceived","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"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptDeveloper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"payee","type":"address"},{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"addPayee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"adminMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_approved","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":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clearPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"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":[{"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":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"homiesMint","outputs":[],"stateMutability":"nonpayable","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":"uint256","name":"index","type":"uint256"}],"name":"isClaimedAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"isClaimedHomies","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"isClaimedNormies","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"_name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"normiesCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"normiesMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"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":[],"name":"payClaims","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"payee","type":"address"}],"name":"payeeIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payees","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quant","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"payable","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":"payee","type":"address"}],"name":"releasable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"payee","type":"address"}],"name":"released","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"payee","type":"address"}],"name":"removePayee","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":"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"}],"name":"revokeRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revokeRoyalties","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":"uint256","name":"_amount","type":"uint256"}],"name":"setCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newURI","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_normies","type":"uint256"},{"internalType":"uint256","name":"_public","type":"uint256"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_description","type":"string"},{"internalType":"string","name":"_image","type":"string"},{"internalType":"string","name":"_animation","type":"string"}],"name":"setJSON","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_admin","type":"bytes32"},{"internalType":"bytes32","name":"_homies","type":"bytes32"},{"internalType":"bytes32","name":"_normies","type":"bytes32"}],"name":"setMerks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint16","name":"permille","type":"uint16"}],"name":"setRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint16","name":"permille","type":"uint16"}],"name":"setRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"setTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"payee","type":"address"}],"name":"shares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"showTimes","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"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":"_symbol","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"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"},{"stateMutability":"payable","type":"receive"}]

608060405266f5232269808000601f5567016345785d8a00006020553480156200002857600080fd5b5060405162005171380380620051718339810160408190526200004b9162000612565b6200005a868686868662000081565b620000758160216200017260201b620026031790919060201c565b5050505050506200084c565b6200009c856000620001ad60201b6200263e1790919060201c565b620000b7846000620001ef60201b6200267c1790919060201c565b620000d860086303e1469160e61b8562000231602090811b620026ba17901c565b620000f38360086200030160201b6200278a1790919060201c565b62000114600863ca4b208b60e01b8462000231602090811b620026ba17901c565b6200012f826008620003ec60201b620028591790919060201c565b620001506008638da5cb5b60e01b8362000231602090811b620026ba17901c565b6200016b8160086200045b60201b620028c51790919060201c565b5050505050565b8082556040518181527f83b179bd5cb3a111f82ac98510d3c66f48f77679e657302f4f253d4c32d6d672906020015b60405180910390a15050565b60048201620001bd82826200074b565b507f13c98778b0c1a086bb98d7f1986e15788b5d3a1ad4c492e1d78f1c4cc51c20cf81604051620001a1919062000817565b60058201620001ff82826200074b565b507f3e46ff90086ee29856e77591e82c82ff8ed513379b0fd82e84fc5290dd633c9981604051620001a1919062000817565b6001600160a01b03811662000258576040516282b42960e81b815260040160405180910390fd5b62000265838383620004ca565b1562000283576040516282b42960e81b815260040160405180910390fd5b6001600160a01b0381166000818152602085815260408083206001600160e01b03198716808552908352928190208054600160ff1990911681179091558151938452918301939093528183015290517fc8bed56f8e046b5a3f2c2b2be85045ea5c972dc18ad669157957897b4d26e9f79181900360600190a1505050565b62000315826303e1469160e61b83620004ca565b1562000370576003820180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec690600090a3505050565b6001600160a01b038116620003d4576003820180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec690600090a3505050565b6040516282b42960e81b815260040160405180910390fd5b620004008263ca4b208b60e01b83620004ca565b1562000370576002820180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f2cfca82ac51c2fc6b6db547820d28d526a505e12d230afb8bf112a5aeefa9a4c90600090a3505050565b6200046f82638da5cb5b60e01b83620004ca565b1562000370576001820180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60006001600160a01b038216620004f3576040516282b42960e81b815260040160405180910390fd5b506001600160a01b03166000908152602092835260408082206001600160e01b03199390931682529190925290205460ff1690565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200055b57818101518382015260200162000541565b50506000910152565b600082601f8301126200057657600080fd5b81516001600160401b038082111562000593576200059362000528565b604051601f8301601f19908116603f01168101908282118183101715620005be57620005be62000528565b81604052838152866020858801011115620005d857600080fd5b620005eb8460208301602089016200053e565b9695505050505050565b80516001600160a01b03811681146200060d57600080fd5b919050565b60008060008060008060c087890312156200062c57600080fd5b86516001600160401b03808211156200064457600080fd5b620006528a838b0162000564565b975060208901519150808211156200066957600080fd5b506200067889828a0162000564565b9550506200068960408801620005f5565b93506200069960608801620005f5565b9250620006a960808801620005f5565b915060a087015190509295509295509295565b600181811c90821680620006d157607f821691505b602082108103620006f257634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200074657600081815260208120601f850160051c81016020861015620007215750805b601f850160051c820191505b8181101562000742578281556001016200072d565b5050505b505050565b81516001600160401b0381111562000767576200076762000528565b6200077f81620007788454620006bc565b84620006f8565b602080601f831160018114620007b757600084156200079e5750858301515b600019600386901b1c1916600185901b17855562000742565b600085815260208120601f198616915b82811015620007e857888601518255948401946001909101908401620007c7565b5085821015620008075787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6020815260008251806020840152620008388160408501602087016200053e565b601f01601f19169190910160400192915050565b614915806200085c6000396000f3fe6080604052600436106104185760003560e01c806376d7fc0711610228578063b88d4fde11610128578063dcd4ab77116100bb578063e8a3d4851161008a578063ec1ffdd81161006f578063ec1ffdd814610c1a578063f2fde38b14610c44578063f950233314610c6457610455565b8063e8a3d48514610be5578063e985e9c514610bfa57610455565b8063dcd4ab7714610b7b578063de02cde714610b90578063e33b7de314610bb0578063e7b7544014610bc557610455565b8063ca4b208b116100f7578063ca4b208b14610b0a578063ce7c2ac214610b28578063d39ce77c14610b48578063d601f1dc14610b6857610455565b8063b88d4fde14610a8a578063bb5027f714610aaa578063c3b8e34514610aca578063c87b56dd14610aea57610455565b806396d32915116101bb578063a22cb4651161018a578063a6b6cb371161016f578063a6b6cb3714610a4a578063a86ff96014610a60578063ad6d9c1714610a7557610455565b8063a22cb46514610a0a578063a3f8eace14610a2a57610455565b806396d329151461098f5780639852595c146109af5780639bce3944146109cf578063a0355eca146109ea57610455565b80638bb2b65a116101f75780638bb2b65a1461091c5780638da5cb5b1461093c578063938e3d7b1461095a57806395d89b411461097a57610455565b806376d7fc07146108bc57806379ba5097146108d15780638159324c146108e65780638693da201461090657610455565b80632db11544116103335780634e8086aa116102c65780636352211e1161029557806366278a6c1161027a57806366278a6c1461086757806370a0823114610887578063715018a6146108a757610455565b80636352211e1461082757806364cb4edb1461084757610455565b80634e8086aa1461079e57806350d604e3146107c05780635ba5e9f0146107e05780636149d8711461080757610455565b806342842e0e1161030257806342842e0e1461072957806344faded01461074957806347786d37146107695780634e71d92d1461078957610455565b80632db11544146106cc57806331e26cfd146106df5780633a98ef39146106f45780633ed358551461070957610455565b8063150b7a02116103ab57806323b872dd1161037a57806323b872dd14610643578063266dcbf6146106635780632a55205a146106785780632bfcf0f2146106b757610455565b8063150b7a02146105b557806318160ddd146105ee57806318f9b023146106035780631fcb02f31461062357610455565b80630b78f9c0116103e75780630b78f9c0146105385780630c222ee51461055857806310ab94321461057857806312065fe01461059857610455565b806301ffc9a71461048757806306fdde03146104bc578063081812fc146104de578063095ea7b31461051657610455565b366104555760405134815233907f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be770906020015b60405180910390a2005b60405134815233907f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be7709060200161044b565b34801561049357600080fd5b506104a76104a2366004613df4565b610c84565b60405190151581526020015b60405180910390f35b3480156104c857600080fd5b506104d1610d55565b6040516104b39190613e61565b3480156104ea57600080fd5b506104fe6104f9366004613e74565b610d66565b6040516001600160a01b0390911681526020016104b3565b34801561052257600080fd5b50610536610531366004613ea9565b610d72565b005b34801561054457600080fd5b50610536610553366004613ed3565b610dbb565b34801561056457600080fd5b50610536610573366004613f07565b610df6565b34801561058457600080fd5b506104a7610593366004613f3a565b610e1e565b3480156105a457600080fd5b50475b6040519081526020016104b3565b3480156105c157600080fd5b506105d56105d0366004613f66565b610e33565b6040516001600160e01b031990911681526020016104b3565b3480156105fa57600080fd5b506105a7610e4d565b34801561060f57600080fd5b5061053661061e366004613ea9565b610e59565b34801561062f57600080fd5b5061053661063e366004614001565b610dde565b34801561064f57600080fd5b5061053661065e36600461403d565b610e7d565b34801561066f57600080fd5b50610536610ed1565b34801561068457600080fd5b50610698610693366004613ed3565b610fe6565b604080516001600160a01b0390931683526020830191909152016104b3565b3480156106c357600080fd5b50610536611000565b6105366106da366004613e74565b611066565b3480156106eb57600080fd5b506105366111be565b34801561070057600080fd5b506105a7611203565b34801561071557600080fd5b50610536610724366004614079565b61120e565b34801561073557600080fd5b5061053661074436600461403d565b611231565b34801561075557600080fd5b50610536610764366004613f3a565b6112c5565b34801561077557600080fd5b50610536610784366004613e74565b61134c565b34801561079557600080fd5b50610536611369565b3480156107aa57600080fd5b506107b361149a565b6040516104b39190614094565b3480156107cc57600080fd5b506104a76107db366004613e74565b6114a6565b3480156107ec57600080fd5b506105d56107fb366004613df4565b506303e1469160e61b90565b34801561081357600080fd5b50610536610822366004614079565b6114e7565b34801561083357600080fd5b506104fe610842366004613e74565b61152c565b34801561085357600080fd5b50610536610862366004614079565b611549565b34801561087357600080fd5b50610536610882366004613df4565b6115ac565b34801561089357600080fd5b506105a76108a2366004614079565b6115e3565b3480156108b357600080fd5b50610536611601565b3480156108c857600080fd5b50610536611652565b3480156108dd57600080fd5b50610536611676565b3480156108f257600080fd5b5061053661090136600461412d565b6116d9565b34801561091257600080fd5b506105a760205481565b34801561092857600080fd5b50610536610937366004614238565b61195f565b34801561094857600080fd5b506009546001600160a01b03166104fe565b34801561096657600080fd5b506105366109753660046142c0565b6119a3565b34801561098657600080fd5b506104d16119c7565b34801561099b57600080fd5b506104a76109aa366004613e74565b6119d3565b3480156109bb57600080fd5b506105a76109ca366004614079565b611a14565b3480156109db57600080fd5b5061053661063e366004613e74565b3480156109f657600080fd5b50610536610a05366004613ed3565b611a32565b348015610a1657600080fd5b50610536610a253660046142f5565b611a55565b348015610a3657600080fd5b506105a7610a45366004614079565b611aa8565b348015610a5657600080fd5b506105a7601f5481565b348015610a6c57600080fd5b50610536611c83565b348015610a8157600080fd5b50610536611cc8565b348015610a9657600080fd5b50610536610aa5366004613f66565b611d19565b348015610ab657600080fd5b50610536610ac5366004614331565b611db2565b348015610ad657600080fd5b506104a7610ae5366004613e74565b612024565b348015610af657600080fd5b506104d1610b05366004613e74565b612065565b348015610b1657600080fd5b50600a546001600160a01b03166104fe565b348015610b3457600080fd5b506105a7610b43366004614079565b6120cc565b348015610b5457600080fd5b50610536610b63366004614079565b6120ea565b610536610b76366004614331565b61212f565b348015610b8757600080fd5b506105366123e8565b348015610b9c57600080fd5b50610536610bab366004613f3a565b61240a565b348015610bbc57600080fd5b50600e546105a7565b348015610bd157600080fd5b506105a7610be0366004614079565b61248d565b348015610bf157600080fd5b506104d161249a565b348015610c0657600080fd5b506104a7610c1536600461438b565b61252c565b348015610c2657600080fd5b50610c2f61255c565b604080519283526020830191909152016104b3565b348015610c5057600080fd5b50610536610c5f366004614079565b61257a565b348015610c7057600080fd5b50610536610c7f3660046143a7565b6125dd565b60006001600160e01b031982167f7f5828d0000000000000000000000000000000000000000000000000000000001480610ce757506001600160e01b031982167f80ac58cd00000000000000000000000000000000000000000000000000000000145b80610d1b57506001600160e01b031982167f2a55205a00000000000000000000000000000000000000000000000000000000145b80610d4f57506001600160e01b031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b92915050565b6060610d616000612931565b905090565b6000610d4f81836129c7565b610d7f6000833384612a4c565b60405181906001600160a01b0384169033907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590600090a45050565b610dce600863ca4b208b60e01b33612b45565b15610dde57601f91909155602055565b6040516282b42960e81b815260040160405180910390fd5b610e096008638da5cb5b60e01b33612b45565b15610dde57610e1a600c8383612ba2565b5050565b6000610e2c60088484612b45565b9392505050565b60006040516282b42960e81b815260040160405180910390fd5b6000610d616000612c83565b610e6c600863ca4b208b60e01b33612b45565b15610dde57610e1a600d8383612c90565b610e8b600084843385612e27565b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000610edd600d612fe4565b805190915060005b81811015610fe1576000306001600160a01b031663a3f8eace858481518110610f1057610f106143d3565b60200260200101516040518263ffffffff1660e01b8152600401610f4391906001600160a01b0391909116815260200190565b602060405180830381865afa158015610f60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8491906143e9565b9050610fb5848381518110610f9b57610f9b6143d3565b602002602001015182600d6130499092919063ffffffff16565b610fd8848381518110610fca57610fca6143d3565b6020026020010151826130d0565b50600101610ee5565b505050565b600080610ff5600c85856131e9565b909590945092505050565b636525904560e11b61101460088233612b45565b8061102d575061102d60086303e1469160e61b33612b45565b15610dde57611045600863ca4b208b60e01b336126ba565b611050600833612859565b6110636008636525904560e11b33613226565b50565b6013546012546110769190614418565b4210610dde57600581111561109d576040516282b42960e81b815260040160405180910390fd5b6012546000036110bf576040516282b42960e81b815260040160405180910390fd5b806020546110cd919061442b565b341461112157604051630330dbc960e11b815260206004820152601160248201527f6d73672e76616c756520746f6f206c6f7700000000000000000000000000000060448201526064015b60405180910390fd5b6014548161112f6000612c83565b6111399190614418565b1115611157576040516282b42960e81b815260040160405180910390fd5b60005b81811015610e1a576111783361116f60215490565b600091906132e2565b60215460405133906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a46111b6602180546001019055565b60010161115a565b636525904560e11b6111d260088233612b45565b806111eb57506111eb60086303e1469160e61b33612b45565b15610dde576110636008636525904560e11b33613226565b6000610d61600d5490565b611221600863ca4b208b60e01b33612b45565b15610dde57611063600d82613407565b6040517fb88d4fde0000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604481018290526080606482015260006084820152309063b88d4fde9060a401600060405180830381600087803b1580156112a857600080fd5b505af11580156112bc573d6000803e3d6000fd5b50505050505050565b816112d260088233612b45565b806112eb57506112eb60086303e1469160e61b33612b45565b15610dde576001600160e01b03198316636525904560e11b148061131f57506001600160e01b031983166346d2e5ad60e11b145b1561134057336001600160a01b03831603610dde57610fe160088484613226565b610fe160088484613226565b61135f600863ca4b208b60e01b33612b45565b15610dde57601455565b60405163673e156160e11b8152336004820152309063ce7c2ac290602401602060405180830381865afa1580156113a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c891906143e9565b6000036113e7576040516282b42960e81b815260040160405180910390fd5b6040517fa3f8eace000000000000000000000000000000000000000000000000000000008152336004820152600090309063a3f8eace90602401602060405180830381865afa15801561143e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146291906143e9565b905080600003611484576040516282b42960e81b815260040160405180910390fd5b611490600d3383613049565b61106333826130d0565b6060610d61600d612fe4565b6000806114b561010084614458565b905060006114c56101008561446c565b60009283526016602052604090922054600190921b9182169091149392505050565b63ca4b208b60e01b6114fb60088233612b45565b80611514575061151460086303e1469160e61b33612b45565b15610dde57610e1a6008636525904560e11b846126ba565b6000818152602081905260408120546001600160a01b0316610d4f565b63ca4b208b60e01b61155d60088233612b45565b80611576575061157660086303e1469160e61b33612b45565b15610dde5761158e600863ca4b208b60e01b846126ba565b611599600883612859565b610e1a600863ca4b208b60e01b33613226565b806115b960088233612b45565b806115d257506115d260086303e1469160e61b33612b45565b15610dde57610e1a60088333613226565b6001600160a01b038116600090815260016020526040812054610d4f565b638da5cb5b60e01b61161560088233612b45565b8061162e575061162e60086303e1469160e61b33612b45565b15610dde5761163f600860006128c5565b6110636008638da5cb5b60e01b33613226565b611665600863ca4b208b60e01b33612b45565b15610dde57611674600d613587565b565b6346d2e5ad60e11b61168a60088233612b45565b806116a357506116a360086303e1469160e61b33612b45565b15610dde576116bb6008638da5cb5b60e01b336126ba565b6116c66008336128c5565b61106360086346d2e5ad60e11b33613226565b6013546012546116e99190614418565b421080156116f957506012544210155b15610dde57601254600003611720576040516282b42960e81b815260040160405180910390fd5b611729856114a6565b1561176957604051630330dbc960e11b815260206004820152600f60248201526e105b1c9958591e4810db185a5b5959608a1b6044820152606401611118565b60408051602081018790526bffffffffffffffffffffffff19606087901b1691810191909152605481018490526000906074016040516020818303038152906040528051906020012090506117f583838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050601554915084905061361c565b61183257604051630330dbc960e11b815260206004820152600d60248201526c24b73b30b634b210283937b7b360991b6044820152606401611118565b61183b86613632565b601454846118496000612c83565b6118539190614418565b1115611871576040516282b42960e81b815260040160405180910390fd5b60005b848110156118d8576118898661116f60215490565b6021546040516001600160a01b038816906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a46118d0602180546001019055565b600101611874565b50604080518781526001600160a01b03871660208201529081018590526080606082018190526005908201527f41646d696e00000000000000000000000000000000000000000000000000000060a08201527fee563d8e532abc293fca2fdeb41c25180305bddcf9206c167dab3e155aaf17139060c00160405180910390a1505050505050565b611972600863ca4b208b60e01b33612b45565b15610dde57601d6119838482614508565b50601c6119908382614508565b50601e61199d8282614508565b50505050565b6119b6600863ca4b208b60e01b33612b45565b15610dde57601b610e1a8282614508565b6060610d616000613670565b6000806119e261010084614458565b905060006119f26101008561446c565b6000928352601a602052604090922054600190921b9182169091149392505050565b6001600160a01b038116600090815260106020526040812054610d4f565b611a45600863ca4b208b60e01b33612b45565b15610dde57601291909155601355565b611a626000833384613681565b60405181151581526001600160a01b0383169033907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319060200160405180910390a35050565b600080306001600160a01b031663e33b7de36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0d91906143e9565b611b179047614418565b6040517f9852595c0000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201529091503090639852595c90602401602060405180830381865afa158015611b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9b91906143e9565b306001600160a01b0316633a98ef396040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bfd91906143e9565b60405163673e156160e11b81526001600160a01b0386166004820152309063ce7c2ac290602401602060405180830381865afa158015611c41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6591906143e9565b611c6f908461442b565b611c799190614458565b610e2c91906145c8565b6346d2e5ad60e11b611c9760088233612b45565b80611cb05750611cb060086303e1469160e61b33612b45565b15610dde5761106360086346d2e5ad60e11b33613226565b63ca4b208b60e01b611cdc60088233612b45565b80611cf55750611cf560086303e1469160e61b33612b45565b15610dde57611d0660086000612859565b611063600863ca4b208b60e01b33613226565b611d27600086863387612e27565b611d6985858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061372192505050565b5082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050565b601354601254611dc29190614418565b42108015611dd257506012544210155b15610dde57601254600003611df9576040516282b42960e81b815260040160405180910390fd5b611e0284612024565b15611e4257604051630330dbc960e11b815260206004820152600f60248201526e105b1c9958591e4810db185a5b5959608a1b6044820152606401611118565b60008484604051602001611e7292919091825260601b6bffffffffffffffffffffffff1916602082015260340190565b604051602081830303815290604052805190602001209050611ecb83838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050601754915084905061361c565b611f0857604051630330dbc960e11b815260206004820152600d60248201526c24b73b30b634b210283937b7b360991b6044820152606401611118565b611f1185613823565b601454611f1e6000612c83565b611f29906001614418565b1115611f47576040516282b42960e81b815260040160405180910390fd5b611f548461116f60215490565b6021546040516001600160a01b038616906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4611f9b602180546001019055565b604080518681526001600160a01b03861660208201526001918101919091526080606082018190526006908201527f486f6d696573000000000000000000000000000000000000000000000000000060a08201527fee563d8e532abc293fca2fdeb41c25180305bddcf9206c167dab3e155aaf17139060c0015b60405180910390a15050505050565b60008061203361010084614458565b905060006120436101008561446c565b60009283526018602052604090922054600190921b9182169091149392505050565b6060600061207283613861565b601d601c601e60405160200161208b949392919061464e565b60405160208183030381529060405290506120a581613996565b6040516020016120b591906147d2565b604051602081830303815290604052915050919050565b6001600160a01b0381166000908152600f6020526040812054610d4f565b638da5cb5b60e01b6120fe60088233612b45565b80612117575061211760086303e1469160e61b33612b45565b15610dde57610e1a60086346d2e5ad60e11b846126ba565b60135460125461213f9190614418565b4210801561214f57506012544210155b15610dde57601254600003612176576040516282b42960e81b815260040160405180910390fd5b601f5434146121c857604051630330dbc960e11b815260206004820152601160248201527f6d73672e76616c756520746f6f206c6f770000000000000000000000000000006044820152606401611118565b6121d1846119d3565b1561221157604051630330dbc960e11b815260206004820152600f60248201526e105b1c9958591e4810db185a5b5959608a1b6044820152606401611118565b6000848460405160200161224192919091825260601b6bffffffffffffffffffffffff1916602082015260340190565b60405160208183030381529060405280519060200120905061229a83838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050601954915084905061361c565b6122d757604051630330dbc960e11b815260206004820152600d60248201526c24b73b30b634b210283937b7b360991b6044820152606401611118565b6122e085613ae9565b6014546122ed6000612c83565b6122f8906001614418565b1115612316576040516282b42960e81b815260040160405180910390fd5b6123238461116f60215490565b6021546040516001600160a01b038616906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a461236a602180546001019055565b604080518681526001600160a01b03861660208201526001918101919091526080606082018190526007908201527f4e6f726d6965730000000000000000000000000000000000000000000000000060a08201527fee563d8e532abc293fca2fdeb41c25180305bddcf9206c167dab3e155aaf17139060c001612015565b6123fb6008638da5cb5b60e01b33612b45565b15610dde57611674600c613b27565b8161241760088233612b45565b80612430575061243060086303e1469160e61b33612b45565b15610dde576001600160e01b03198316636525904560e11b148061246457506001600160e01b031983166346d2e5ad60e11b145b15612481576040516282b42960e81b815260040160405180910390fd5b610fe1600884846126ba565b6000610d4f600d83613b8c565b6060601b80546124a990614480565b80601f01602080910402602001604051908101604052809291908181526020018280546124d590614480565b80156125225780601f106124f757610100808354040283529160200191612522565b820191906000526020600020905b81548152906001019060200180831161250557829003601f168201915b5050505050905090565b6001600160a01b03808316600090815260036020908152604080832093851683529290529081205460ff16610e2c565b6000806012546013546012546125729190614418565b915091509091565b638da5cb5b60e01b61258e60088233612b45565b806125a757506125a760086303e1469160e61b33612b45565b15610dde576125bf6008638da5cb5b60e01b846126ba565b6125ca6008836128c5565b610e1a6008638da5cb5b60e01b33613226565b6125f0600863ca4b208b60e01b33612b45565b15610dde57601592909255601755601955565b8082556040518181527f83b179bd5cb3a111f82ac98510d3c66f48f77679e657302f4f253d4c32d6d672906020015b60405180910390a15050565b6004820161264c8282614508565b507f13c98778b0c1a086bb98d7f1986e15788b5d3a1ad4c492e1d78f1c4cc51c20cf816040516126329190613e61565b6005820161268a8282614508565b507f3e46ff90086ee29856e77591e82c82ff8ed513379b0fd82e84fc5290dd633c99816040516126329190613e61565b6001600160a01b0381166126e0576040516282b42960e81b815260040160405180910390fd5b6126eb838383612b45565b15612708576040516282b42960e81b815260040160405180910390fd5b6001600160a01b0381166000818152602085815260408083206001600160e01b0319871680855290835292819020805460ff19166001908117909155815193845291830193909352918101919091527fc8bed56f8e046b5a3f2c2b2be85045ea5c972dc18ad669157957897b4d26e9f7906060015b60405180910390a1505050565b61279c826303e1469160e61b83612b45565b156127f6576003820180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec690600090a3505050565b6001600160a01b038116610dde576003820180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec690600090a3505050565b61286b8263ca4b208b60e01b83612b45565b156127f6576002820180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f2cfca82ac51c2fc6b6db547820d28d526a505e12d230afb8bf112a5aeefa9a4c90600090a3505050565b6128d782638da5cb5b60e01b83612b45565b156127f6576001820180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b606081600401805461294290614480565b80601f016020809104026020016040519081016040528092919081815260200182805461296e90614480565b80156129bb5780601f10612990576101008083540402835291602001916129bb565b820191906000526020600020905b81548152906001019060200180831161299e57829003601f168201915b50505050509050919050565b6000818152602083905260408120546001600160a01b0316612a2c57604051630330dbc960e11b815260206004820152600360248201527f4c3a3100000000000000000000000000000000000000000000000000000000006044820152606401611118565b50600090815260029190910160205260409020546001600160a01b031690565b6000818152602085905260409020546001600160a01b03908116908416819003612ab957604051630330dbc960e11b815260206004820152600360248201527f4c3a3200000000000000000000000000000000000000000000000000000000006044820152606401611118565b612ac4858484613c55565b612b1157604051630330dbc960e11b815260206004820152600360248201527f4c3a3300000000000000000000000000000000000000000000000000000000006044820152606401611118565b50600090815260029390930160205250604090912080546001600160a01b0319166001600160a01b03909216919091179055565b60006001600160a01b038216612b6d576040516282b42960e81b815260040160405180910390fd5b506001600160a01b03166000908152602092835260408082206001600160e01b03199390931682529190925290205460ff1690565b6103e88161ffff16101580612bb9575061ffff8116155b15612c0757604051630330dbc960e11b815260206004820152600360248201527f523a3100000000000000000000000000000000000000000000000000000000006044820152606401611118565b82546001600160a01b0383811675ffffffffffffffffffffffffffffffffffffffffffff1990921691909117600160a01b61ffff84811682029290921780875560408051948216855291900490911660208301527f712ca2ffb17da9e3b90d98d54938dee8be84b528cbdec691d680c1df8b78538a910161277d565b6000610d4f826007015490565b6001600160a01b038216612cd057604051630330dbc960e11b81526004016111189060208082526004908201526350533a3360e01b604082015260600190565b80600003612d2357604051630330dbc960e11b81526004016111189060208082526004908201527f50533a3400000000000000000000000000000000000000000000000000000000604082015260600190565b6001600160a01b038216600090815260028401602052604090205415612d8e57604051630330dbc960e11b81526004016111189060208082526004908201527f50533a3500000000000000000000000000000000000000000000000000000000604082015260600190565b6004830180546001810182556000918252602080832090910180546001600160a01b0319166001600160a01b038616908117909155825260028501905260408120829055835482918591612de3908490614418565b9091555050604080516001600160a01b0384168152602081018390527f40c340f65e17194d14ddddb073d3c9f888e3cb52b5aae0c6c7706b4fbc905fac910161277d565b612e32858383613c55565b612e7f57604051630330dbc960e11b815260206004820152600360248201527f4c3a3500000000000000000000000000000000000000000000000000000000006044820152606401611118565b6000818152602086905260409020546001600160a01b039081169085168114612eeb57604051630330dbc960e11b815260206004820152600360248201527f4c3a3600000000000000000000000000000000000000000000000000000000006044820152606401611118565b6001600160a01b038416612f4257604051630330dbc960e11b815260206004820152600360248201527f4c3a3700000000000000000000000000000000000000000000000000000000006044820152606401611118565b612f4f8660008585612a4c565b6001600160a01b0385166000908152600187810160205260408220805491929091612f7b9084906145c8565b90915550506001600160a01b0384166000908152600187810160205260408220805491929091612fac908490614418565b909155505050600090815260209490945250604090922080546001600160a01b0319166001600160a01b039093169290921790915550565b6060816004018054806020026020016040519081016040528092919081815260200182805480156129bb57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116130205750505050509050919050565b8083600101600082825461305d9190614418565b90915550506001600160a01b03821660009081526003840160205260408120805483929061308c908490614418565b9091555050604080516001600160a01b0384168152602081018390527fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b056910161277d565b804710156131205760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401611118565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461316d576040519150601f19603f3d011682016040523d82523d6000602084013e613172565b606091505b5050905080610fe15760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401611118565b82546001600160a01b038116906000906103e89061321290600160a01b900461ffff168561442b565b61321c9190614458565b9050935093915050565b6001600160a01b03811661324c576040516282b42960e81b815260040160405180910390fd5b613257838383612b45565b613273576040516282b42960e81b815260040160405180910390fd5b6001600160a01b0381166000818152602085815260408083206001600160e01b03198716808552908352818420805460ff19169055815190815291820193909352918201527fc8bed56f8e046b5a3f2c2b2be85045ea5c972dc18ad669157957897b4d26e9f79060600161277d565b6001600160a01b03821661333957604051630330dbc960e11b815260206004820152600360248201527f4c3a3800000000000000000000000000000000000000000000000000000000006044820152606401611118565b6000818152602084905260409020546001600160a01b03161561339f57604051630330dbc960e11b815260206004820152600360248201527f4c3a3900000000000000000000000000000000000000000000000000000000006044820152606401611118565b6001600160a01b03821660009081526001848101602052604082208054919290916133cb908490614418565b9091555050600081815260208490526040902080546001600160a01b0319166001600160a01b0384161790556007830180546001019055505050565b6001600160a01b03811661344757604051630330dbc960e11b81526004016111189060208082526004908201526350533a3360e01b604082015260600190565b60006134538383613b8c565b60048401805491925060009161346b906001906145c8565b8154811061347b5761347b6143d3565b6000918252602090912001546004850180546001600160a01b0390921692508291849081106134ac576134ac6143d3565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550836004018054806134ed576134ed614817565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0385168252600286019052604081208054908290558554909182918791906135439084906145c8565b9091555050604080516001600160a01b0386168152602081018390527f104b8837ec12e86f303ac7ce5e3bf20c6790f843fabd7451943f3390fc8376cb9101612015565b600481015460005b818110156135db5760008360040182815481106135ae576135ae6143d3565b60009182526020808320909101546001600160a01b0316825260028601905260408120555060010161358f565b5060008083556135ef906004840190613dac565b6040517f3407fd525bf6581e0ae8e3a3636bd90d02112bea34d66802743c28ced73f910e90600090a15050565b6000826136298584613cd4565b14949350505050565b600061364061010083614458565b905060006136506101008461446c565b6000928352601660205260409092208054600190931b9092179091555050565b606081600501805461294290614480565b826001600160a01b0316826001600160a01b0316036136e357604051630330dbc960e11b815260206004820152600360248201527f4c3a3400000000000000000000000000000000000000000000000000000000006044820152606401611118565b6001600160a01b0391821660009081526003949094016020908152604080862094909316855292909252909120805460ff1916911515919091179055565b60006001600160a01b0384163b1561381757604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061376590339089908890889060040161482d565b6020604051808303816000875af19250505080156137a0575060408051601f3d908101601f1916820190925261379d91810190614869565b60015b6137fd573d8080156137ce576040519150601f19603f3d011682016040523d82523d6000602084013e6137d3565b606091505b5080516000036137f5576040516282b42960e81b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061381b565b5060015b949350505050565b600061383161010083614458565b905060006138416101008461446c565b6000928352601860205260409092208054600190931b9092179091555050565b6060816000036138a457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156138ce57806138b881614886565b91506138c79050600a83614458565b91506138a8565b60008167ffffffffffffffff8111156138e9576138e9614195565b6040519080825280601f01601f191660200182016040528015613913576020820181803683370190505b5090505b841561381b576139286001836145c8565b9150613935600a8661446c565b613940906030614418565b60f81b818381518110613955576139556143d3565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061398f600a86614458565b9450613917565b606081516000036139b557505060408051602081019091526000815290565b60006040518060600160405280604081526020016148a060409139905060006003845160026139e49190614418565b6139ee9190614458565b6139f990600461442b565b67ffffffffffffffff811115613a1157613a11614195565b6040519080825280601f01601f191660200182016040528015613a3b576020820181803683370190505b509050600182016020820185865187015b80821015613aa7576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f8116850151845350600183019250613a4c565b5050600386510660018114613ac35760028114613ad657613ade565b603d6001830353603d6002830353613ade565b603d60018303535b509195945050505050565b6000613af761010083614458565b90506000613b076101008461446c565b6000928352601a60205260409092208054600190931b9092179091555050565b805475ffffffffffffffffffffffffffffffffffffffffffff19168082556040805160008152600160a01b90920461ffff1660208301527f712ca2ffb17da9e3b90d98d54938dee8be84b528cbdec691d680c1df8b78538a910160405180910390a150565b6000806000613bf785600401805480602002602001604051908101604052809291908181526020018280548015613bec57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613bce575b505050505085613d21565b915091508115613c0a579150610d4f9050565b604051630330dbc960e11b81526004016111189060208082526004908201527f50533a3600000000000000000000000000000000000000000000000000000000604082015260600190565b6000818152602084905260408120546001600160a01b03908116908416811480613ca657506001600160a01b03808216600090815260038701602090815260408083209388168352929052205460ff165b80613ccb5750836001600160a01b0316613cc086856129c7565b6001600160a01b0316145b95945050505050565b600081815b8451811015613d1957613d0582868381518110613cf857613cf86143d3565b6020026020010151613d7d565b915080613d1181614886565b915050613cd9565b509392505050565b81516000908190815b81811015613d7457846001600160a01b0316868281518110613d4e57613d4e6143d3565b60200260200101516001600160a01b031603613d6c57600193508092505b600101613d2a565b50509250929050565b6000818310613d99576000828152602084905260409020610e2c565b6000838152602083905260409020610e2c565b508054600082559060005260206000209081019061106391905b80821115613dda5760008155600101613dc6565b5090565b6001600160e01b03198116811461106357600080fd5b600060208284031215613e0657600080fd5b8135610e2c81613dde565b60005b83811015613e2c578181015183820152602001613e14565b50506000910152565b60008151808452613e4d816020860160208601613e11565b601f01601f19169290920160200192915050565b602081526000610e2c6020830184613e35565b600060208284031215613e8657600080fd5b5035919050565b80356001600160a01b0381168114613ea457600080fd5b919050565b60008060408385031215613ebc57600080fd5b613ec583613e8d565b946020939093013593505050565b60008060408385031215613ee657600080fd5b50508035926020909101359150565b803561ffff81168114613ea457600080fd5b60008060408385031215613f1a57600080fd5b613f2383613e8d565b9150613f3160208401613ef5565b90509250929050565b60008060408385031215613f4d57600080fd5b8235613f5881613dde565b9150613f3160208401613e8d565b600080600080600060808688031215613f7e57600080fd5b613f8786613e8d565b9450613f9560208701613e8d565b935060408601359250606086013567ffffffffffffffff80821115613fb957600080fd5b818801915088601f830112613fcd57600080fd5b813581811115613fdc57600080fd5b896020828501011115613fee57600080fd5b9699959850939650602001949392505050565b60008060006060848603121561401657600080fd5b8335925061402660208501613e8d565b915061403460408501613ef5565b90509250925092565b60008060006060848603121561405257600080fd5b61405b84613e8d565b925061406960208501613e8d565b9150604084013590509250925092565b60006020828403121561408b57600080fd5b610e2c82613e8d565b6020808252825182820181905260009190848201906040850190845b818110156140d55783516001600160a01b0316835292840192918401916001016140b0565b50909695505050505050565b60008083601f8401126140f357600080fd5b50813567ffffffffffffffff81111561410b57600080fd5b6020830191508360208260051b850101111561412657600080fd5b9250929050565b60008060008060006080868803121561414557600080fd5b8535945061415560208701613e8d565b935060408601359250606086013567ffffffffffffffff81111561417857600080fd5b614184888289016140e1565b969995985093965092949392505050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126141bc57600080fd5b813567ffffffffffffffff808211156141d7576141d7614195565b604051601f8301601f19908116603f011681019082821181831017156141ff576141ff614195565b8160405283815286602085880101111561421857600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561424d57600080fd5b833567ffffffffffffffff8082111561426557600080fd5b614271878388016141ab565b9450602086013591508082111561428757600080fd5b614293878388016141ab565b935060408601359150808211156142a957600080fd5b506142b6868287016141ab565b9150509250925092565b6000602082840312156142d257600080fd5b813567ffffffffffffffff8111156142e957600080fd5b61381b848285016141ab565b6000806040838503121561430857600080fd5b61431183613e8d565b91506020830135801515811461432657600080fd5b809150509250929050565b6000806000806060858703121561434757600080fd5b8435935061435760208601613e8d565b9250604085013567ffffffffffffffff81111561437357600080fd5b61437f878288016140e1565b95989497509550505050565b6000806040838503121561439e57600080fd5b613f5883613e8d565b6000806000606084860312156143bc57600080fd5b505081359360208301359350604090920135919050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156143fb57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610d4f57610d4f614402565b8082028115828204841417610d4f57610d4f614402565b634e487b7160e01b600052601260045260246000fd5b60008261446757614467614442565b500490565b60008261447b5761447b614442565b500690565b600181811c9082168061449457607f821691505b6020821081036144b457634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610fe157600081815260208120601f850160051c810160208610156144e15750805b601f850160051c820191505b81811015614500578281556001016144ed565b505050505050565b815167ffffffffffffffff81111561452257614522614195565b614536816145308454614480565b846144ba565b602080601f83116001811461456b57600084156145535750858301515b600019600386901b1c1916600185901b178555614500565b600085815260208120601f198616915b8281101561459a5788860151825594840194600190910190840161457b565b50858210156145b85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b81810381811115610d4f57610d4f614402565b600081546145e881614480565b60018281168015614600576001811461461557614644565b60ff1984168752821515830287019450614644565b8560005260208060002060005b8581101561463b5781548a820152908401908201614622565b50505082870194505b5050505092915050565b7f7b0000000000000000000000000000000000000000000000000000000000000081527f226e616d65223a2022486f6d6965732047656e657369732023000000000000006001820152600085516146ac81601a850160208a01613e11565b80830190507f222c00000000000000000000000000000000000000000000000000000000000080601a8301527f226465736372697074696f6e223a202200000000000000000000000000000000601c83015261470b602c8301886145db565b91508082527f22696d616765223a2022000000000000000000000000000000000000000000006002830152614743600c8301876145db565b9081527f22616e696d6174696f6e5f75726c223a202200000000000000000000000000006002820152905061477b60148201856145db565b7f220000000000000000000000000000000000000000000000000000000000000081527f7d000000000000000000000000000000000000000000000000000000000000006001820152600201979650505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161480a81601d850160208701613e11565b91909101601d0192915050565b634e487b7160e01b600052603160045260246000fd5b60006001600160a01b0380871683528086166020840152508360408301526080606083015261485f6080830184613e35565b9695505050505050565b60006020828403121561487b57600080fd5b8151610e2c81613dde565b60006001820161489857614898614402565b506001019056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220ed328c08ff18b159f7e3d70e6781cd2a14eded050466f4014276ca6751db6b2c64736f6c6343000811003300000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000004ce69fd760ad0c07490178f9a47863dc0358cccd0000000000000000000000004ce69fd760ad0c07490178f9a47863dc0358cccd000000000000000000000000e318cde62513f8c21e91e5211ff33a7eedf78a2f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000e486f6d696573206f6620576562330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004486f573300000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106104185760003560e01c806376d7fc0711610228578063b88d4fde11610128578063dcd4ab77116100bb578063e8a3d4851161008a578063ec1ffdd81161006f578063ec1ffdd814610c1a578063f2fde38b14610c44578063f950233314610c6457610455565b8063e8a3d48514610be5578063e985e9c514610bfa57610455565b8063dcd4ab7714610b7b578063de02cde714610b90578063e33b7de314610bb0578063e7b7544014610bc557610455565b8063ca4b208b116100f7578063ca4b208b14610b0a578063ce7c2ac214610b28578063d39ce77c14610b48578063d601f1dc14610b6857610455565b8063b88d4fde14610a8a578063bb5027f714610aaa578063c3b8e34514610aca578063c87b56dd14610aea57610455565b806396d32915116101bb578063a22cb4651161018a578063a6b6cb371161016f578063a6b6cb3714610a4a578063a86ff96014610a60578063ad6d9c1714610a7557610455565b8063a22cb46514610a0a578063a3f8eace14610a2a57610455565b806396d329151461098f5780639852595c146109af5780639bce3944146109cf578063a0355eca146109ea57610455565b80638bb2b65a116101f75780638bb2b65a1461091c5780638da5cb5b1461093c578063938e3d7b1461095a57806395d89b411461097a57610455565b806376d7fc07146108bc57806379ba5097146108d15780638159324c146108e65780638693da201461090657610455565b80632db11544116103335780634e8086aa116102c65780636352211e1161029557806366278a6c1161027a57806366278a6c1461086757806370a0823114610887578063715018a6146108a757610455565b80636352211e1461082757806364cb4edb1461084757610455565b80634e8086aa1461079e57806350d604e3146107c05780635ba5e9f0146107e05780636149d8711461080757610455565b806342842e0e1161030257806342842e0e1461072957806344faded01461074957806347786d37146107695780634e71d92d1461078957610455565b80632db11544146106cc57806331e26cfd146106df5780633a98ef39146106f45780633ed358551461070957610455565b8063150b7a02116103ab57806323b872dd1161037a57806323b872dd14610643578063266dcbf6146106635780632a55205a146106785780632bfcf0f2146106b757610455565b8063150b7a02146105b557806318160ddd146105ee57806318f9b023146106035780631fcb02f31461062357610455565b80630b78f9c0116103e75780630b78f9c0146105385780630c222ee51461055857806310ab94321461057857806312065fe01461059857610455565b806301ffc9a71461048757806306fdde03146104bc578063081812fc146104de578063095ea7b31461051657610455565b366104555760405134815233907f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be770906020015b60405180910390a2005b60405134815233907f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be7709060200161044b565b34801561049357600080fd5b506104a76104a2366004613df4565b610c84565b60405190151581526020015b60405180910390f35b3480156104c857600080fd5b506104d1610d55565b6040516104b39190613e61565b3480156104ea57600080fd5b506104fe6104f9366004613e74565b610d66565b6040516001600160a01b0390911681526020016104b3565b34801561052257600080fd5b50610536610531366004613ea9565b610d72565b005b34801561054457600080fd5b50610536610553366004613ed3565b610dbb565b34801561056457600080fd5b50610536610573366004613f07565b610df6565b34801561058457600080fd5b506104a7610593366004613f3a565b610e1e565b3480156105a457600080fd5b50475b6040519081526020016104b3565b3480156105c157600080fd5b506105d56105d0366004613f66565b610e33565b6040516001600160e01b031990911681526020016104b3565b3480156105fa57600080fd5b506105a7610e4d565b34801561060f57600080fd5b5061053661061e366004613ea9565b610e59565b34801561062f57600080fd5b5061053661063e366004614001565b610dde565b34801561064f57600080fd5b5061053661065e36600461403d565b610e7d565b34801561066f57600080fd5b50610536610ed1565b34801561068457600080fd5b50610698610693366004613ed3565b610fe6565b604080516001600160a01b0390931683526020830191909152016104b3565b3480156106c357600080fd5b50610536611000565b6105366106da366004613e74565b611066565b3480156106eb57600080fd5b506105366111be565b34801561070057600080fd5b506105a7611203565b34801561071557600080fd5b50610536610724366004614079565b61120e565b34801561073557600080fd5b5061053661074436600461403d565b611231565b34801561075557600080fd5b50610536610764366004613f3a565b6112c5565b34801561077557600080fd5b50610536610784366004613e74565b61134c565b34801561079557600080fd5b50610536611369565b3480156107aa57600080fd5b506107b361149a565b6040516104b39190614094565b3480156107cc57600080fd5b506104a76107db366004613e74565b6114a6565b3480156107ec57600080fd5b506105d56107fb366004613df4565b506303e1469160e61b90565b34801561081357600080fd5b50610536610822366004614079565b6114e7565b34801561083357600080fd5b506104fe610842366004613e74565b61152c565b34801561085357600080fd5b50610536610862366004614079565b611549565b34801561087357600080fd5b50610536610882366004613df4565b6115ac565b34801561089357600080fd5b506105a76108a2366004614079565b6115e3565b3480156108b357600080fd5b50610536611601565b3480156108c857600080fd5b50610536611652565b3480156108dd57600080fd5b50610536611676565b3480156108f257600080fd5b5061053661090136600461412d565b6116d9565b34801561091257600080fd5b506105a760205481565b34801561092857600080fd5b50610536610937366004614238565b61195f565b34801561094857600080fd5b506009546001600160a01b03166104fe565b34801561096657600080fd5b506105366109753660046142c0565b6119a3565b34801561098657600080fd5b506104d16119c7565b34801561099b57600080fd5b506104a76109aa366004613e74565b6119d3565b3480156109bb57600080fd5b506105a76109ca366004614079565b611a14565b3480156109db57600080fd5b5061053661063e366004613e74565b3480156109f657600080fd5b50610536610a05366004613ed3565b611a32565b348015610a1657600080fd5b50610536610a253660046142f5565b611a55565b348015610a3657600080fd5b506105a7610a45366004614079565b611aa8565b348015610a5657600080fd5b506105a7601f5481565b348015610a6c57600080fd5b50610536611c83565b348015610a8157600080fd5b50610536611cc8565b348015610a9657600080fd5b50610536610aa5366004613f66565b611d19565b348015610ab657600080fd5b50610536610ac5366004614331565b611db2565b348015610ad657600080fd5b506104a7610ae5366004613e74565b612024565b348015610af657600080fd5b506104d1610b05366004613e74565b612065565b348015610b1657600080fd5b50600a546001600160a01b03166104fe565b348015610b3457600080fd5b506105a7610b43366004614079565b6120cc565b348015610b5457600080fd5b50610536610b63366004614079565b6120ea565b610536610b76366004614331565b61212f565b348015610b8757600080fd5b506105366123e8565b348015610b9c57600080fd5b50610536610bab366004613f3a565b61240a565b348015610bbc57600080fd5b50600e546105a7565b348015610bd157600080fd5b506105a7610be0366004614079565b61248d565b348015610bf157600080fd5b506104d161249a565b348015610c0657600080fd5b506104a7610c1536600461438b565b61252c565b348015610c2657600080fd5b50610c2f61255c565b604080519283526020830191909152016104b3565b348015610c5057600080fd5b50610536610c5f366004614079565b61257a565b348015610c7057600080fd5b50610536610c7f3660046143a7565b6125dd565b60006001600160e01b031982167f7f5828d0000000000000000000000000000000000000000000000000000000001480610ce757506001600160e01b031982167f80ac58cd00000000000000000000000000000000000000000000000000000000145b80610d1b57506001600160e01b031982167f2a55205a00000000000000000000000000000000000000000000000000000000145b80610d4f57506001600160e01b031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b92915050565b6060610d616000612931565b905090565b6000610d4f81836129c7565b610d7f6000833384612a4c565b60405181906001600160a01b0384169033907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590600090a45050565b610dce600863ca4b208b60e01b33612b45565b15610dde57601f91909155602055565b6040516282b42960e81b815260040160405180910390fd5b610e096008638da5cb5b60e01b33612b45565b15610dde57610e1a600c8383612ba2565b5050565b6000610e2c60088484612b45565b9392505050565b60006040516282b42960e81b815260040160405180910390fd5b6000610d616000612c83565b610e6c600863ca4b208b60e01b33612b45565b15610dde57610e1a600d8383612c90565b610e8b600084843385612e27565b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000610edd600d612fe4565b805190915060005b81811015610fe1576000306001600160a01b031663a3f8eace858481518110610f1057610f106143d3565b60200260200101516040518263ffffffff1660e01b8152600401610f4391906001600160a01b0391909116815260200190565b602060405180830381865afa158015610f60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8491906143e9565b9050610fb5848381518110610f9b57610f9b6143d3565b602002602001015182600d6130499092919063ffffffff16565b610fd8848381518110610fca57610fca6143d3565b6020026020010151826130d0565b50600101610ee5565b505050565b600080610ff5600c85856131e9565b909590945092505050565b636525904560e11b61101460088233612b45565b8061102d575061102d60086303e1469160e61b33612b45565b15610dde57611045600863ca4b208b60e01b336126ba565b611050600833612859565b6110636008636525904560e11b33613226565b50565b6013546012546110769190614418565b4210610dde57600581111561109d576040516282b42960e81b815260040160405180910390fd5b6012546000036110bf576040516282b42960e81b815260040160405180910390fd5b806020546110cd919061442b565b341461112157604051630330dbc960e11b815260206004820152601160248201527f6d73672e76616c756520746f6f206c6f7700000000000000000000000000000060448201526064015b60405180910390fd5b6014548161112f6000612c83565b6111399190614418565b1115611157576040516282b42960e81b815260040160405180910390fd5b60005b81811015610e1a576111783361116f60215490565b600091906132e2565b60215460405133906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a46111b6602180546001019055565b60010161115a565b636525904560e11b6111d260088233612b45565b806111eb57506111eb60086303e1469160e61b33612b45565b15610dde576110636008636525904560e11b33613226565b6000610d61600d5490565b611221600863ca4b208b60e01b33612b45565b15610dde57611063600d82613407565b6040517fb88d4fde0000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604481018290526080606482015260006084820152309063b88d4fde9060a401600060405180830381600087803b1580156112a857600080fd5b505af11580156112bc573d6000803e3d6000fd5b50505050505050565b816112d260088233612b45565b806112eb57506112eb60086303e1469160e61b33612b45565b15610dde576001600160e01b03198316636525904560e11b148061131f57506001600160e01b031983166346d2e5ad60e11b145b1561134057336001600160a01b03831603610dde57610fe160088484613226565b610fe160088484613226565b61135f600863ca4b208b60e01b33612b45565b15610dde57601455565b60405163673e156160e11b8152336004820152309063ce7c2ac290602401602060405180830381865afa1580156113a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c891906143e9565b6000036113e7576040516282b42960e81b815260040160405180910390fd5b6040517fa3f8eace000000000000000000000000000000000000000000000000000000008152336004820152600090309063a3f8eace90602401602060405180830381865afa15801561143e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146291906143e9565b905080600003611484576040516282b42960e81b815260040160405180910390fd5b611490600d3383613049565b61106333826130d0565b6060610d61600d612fe4565b6000806114b561010084614458565b905060006114c56101008561446c565b60009283526016602052604090922054600190921b9182169091149392505050565b63ca4b208b60e01b6114fb60088233612b45565b80611514575061151460086303e1469160e61b33612b45565b15610dde57610e1a6008636525904560e11b846126ba565b6000818152602081905260408120546001600160a01b0316610d4f565b63ca4b208b60e01b61155d60088233612b45565b80611576575061157660086303e1469160e61b33612b45565b15610dde5761158e600863ca4b208b60e01b846126ba565b611599600883612859565b610e1a600863ca4b208b60e01b33613226565b806115b960088233612b45565b806115d257506115d260086303e1469160e61b33612b45565b15610dde57610e1a60088333613226565b6001600160a01b038116600090815260016020526040812054610d4f565b638da5cb5b60e01b61161560088233612b45565b8061162e575061162e60086303e1469160e61b33612b45565b15610dde5761163f600860006128c5565b6110636008638da5cb5b60e01b33613226565b611665600863ca4b208b60e01b33612b45565b15610dde57611674600d613587565b565b6346d2e5ad60e11b61168a60088233612b45565b806116a357506116a360086303e1469160e61b33612b45565b15610dde576116bb6008638da5cb5b60e01b336126ba565b6116c66008336128c5565b61106360086346d2e5ad60e11b33613226565b6013546012546116e99190614418565b421080156116f957506012544210155b15610dde57601254600003611720576040516282b42960e81b815260040160405180910390fd5b611729856114a6565b1561176957604051630330dbc960e11b815260206004820152600f60248201526e105b1c9958591e4810db185a5b5959608a1b6044820152606401611118565b60408051602081018790526bffffffffffffffffffffffff19606087901b1691810191909152605481018490526000906074016040516020818303038152906040528051906020012090506117f583838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050601554915084905061361c565b61183257604051630330dbc960e11b815260206004820152600d60248201526c24b73b30b634b210283937b7b360991b6044820152606401611118565b61183b86613632565b601454846118496000612c83565b6118539190614418565b1115611871576040516282b42960e81b815260040160405180910390fd5b60005b848110156118d8576118898661116f60215490565b6021546040516001600160a01b038816906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a46118d0602180546001019055565b600101611874565b50604080518781526001600160a01b03871660208201529081018590526080606082018190526005908201527f41646d696e00000000000000000000000000000000000000000000000000000060a08201527fee563d8e532abc293fca2fdeb41c25180305bddcf9206c167dab3e155aaf17139060c00160405180910390a1505050505050565b611972600863ca4b208b60e01b33612b45565b15610dde57601d6119838482614508565b50601c6119908382614508565b50601e61199d8282614508565b50505050565b6119b6600863ca4b208b60e01b33612b45565b15610dde57601b610e1a8282614508565b6060610d616000613670565b6000806119e261010084614458565b905060006119f26101008561446c565b6000928352601a602052604090922054600190921b9182169091149392505050565b6001600160a01b038116600090815260106020526040812054610d4f565b611a45600863ca4b208b60e01b33612b45565b15610dde57601291909155601355565b611a626000833384613681565b60405181151581526001600160a01b0383169033907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319060200160405180910390a35050565b600080306001600160a01b031663e33b7de36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0d91906143e9565b611b179047614418565b6040517f9852595c0000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201529091503090639852595c90602401602060405180830381865afa158015611b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9b91906143e9565b306001600160a01b0316633a98ef396040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bfd91906143e9565b60405163673e156160e11b81526001600160a01b0386166004820152309063ce7c2ac290602401602060405180830381865afa158015611c41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6591906143e9565b611c6f908461442b565b611c799190614458565b610e2c91906145c8565b6346d2e5ad60e11b611c9760088233612b45565b80611cb05750611cb060086303e1469160e61b33612b45565b15610dde5761106360086346d2e5ad60e11b33613226565b63ca4b208b60e01b611cdc60088233612b45565b80611cf55750611cf560086303e1469160e61b33612b45565b15610dde57611d0660086000612859565b611063600863ca4b208b60e01b33613226565b611d27600086863387612e27565b611d6985858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061372192505050565b5082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050565b601354601254611dc29190614418565b42108015611dd257506012544210155b15610dde57601254600003611df9576040516282b42960e81b815260040160405180910390fd5b611e0284612024565b15611e4257604051630330dbc960e11b815260206004820152600f60248201526e105b1c9958591e4810db185a5b5959608a1b6044820152606401611118565b60008484604051602001611e7292919091825260601b6bffffffffffffffffffffffff1916602082015260340190565b604051602081830303815290604052805190602001209050611ecb83838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050601754915084905061361c565b611f0857604051630330dbc960e11b815260206004820152600d60248201526c24b73b30b634b210283937b7b360991b6044820152606401611118565b611f1185613823565b601454611f1e6000612c83565b611f29906001614418565b1115611f47576040516282b42960e81b815260040160405180910390fd5b611f548461116f60215490565b6021546040516001600160a01b038616906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4611f9b602180546001019055565b604080518681526001600160a01b03861660208201526001918101919091526080606082018190526006908201527f486f6d696573000000000000000000000000000000000000000000000000000060a08201527fee563d8e532abc293fca2fdeb41c25180305bddcf9206c167dab3e155aaf17139060c0015b60405180910390a15050505050565b60008061203361010084614458565b905060006120436101008561446c565b60009283526018602052604090922054600190921b9182169091149392505050565b6060600061207283613861565b601d601c601e60405160200161208b949392919061464e565b60405160208183030381529060405290506120a581613996565b6040516020016120b591906147d2565b604051602081830303815290604052915050919050565b6001600160a01b0381166000908152600f6020526040812054610d4f565b638da5cb5b60e01b6120fe60088233612b45565b80612117575061211760086303e1469160e61b33612b45565b15610dde57610e1a60086346d2e5ad60e11b846126ba565b60135460125461213f9190614418565b4210801561214f57506012544210155b15610dde57601254600003612176576040516282b42960e81b815260040160405180910390fd5b601f5434146121c857604051630330dbc960e11b815260206004820152601160248201527f6d73672e76616c756520746f6f206c6f770000000000000000000000000000006044820152606401611118565b6121d1846119d3565b1561221157604051630330dbc960e11b815260206004820152600f60248201526e105b1c9958591e4810db185a5b5959608a1b6044820152606401611118565b6000848460405160200161224192919091825260601b6bffffffffffffffffffffffff1916602082015260340190565b60405160208183030381529060405280519060200120905061229a83838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050601954915084905061361c565b6122d757604051630330dbc960e11b815260206004820152600d60248201526c24b73b30b634b210283937b7b360991b6044820152606401611118565b6122e085613ae9565b6014546122ed6000612c83565b6122f8906001614418565b1115612316576040516282b42960e81b815260040160405180910390fd5b6123238461116f60215490565b6021546040516001600160a01b038616906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a461236a602180546001019055565b604080518681526001600160a01b03861660208201526001918101919091526080606082018190526007908201527f4e6f726d6965730000000000000000000000000000000000000000000000000060a08201527fee563d8e532abc293fca2fdeb41c25180305bddcf9206c167dab3e155aaf17139060c001612015565b6123fb6008638da5cb5b60e01b33612b45565b15610dde57611674600c613b27565b8161241760088233612b45565b80612430575061243060086303e1469160e61b33612b45565b15610dde576001600160e01b03198316636525904560e11b148061246457506001600160e01b031983166346d2e5ad60e11b145b15612481576040516282b42960e81b815260040160405180910390fd5b610fe1600884846126ba565b6000610d4f600d83613b8c565b6060601b80546124a990614480565b80601f01602080910402602001604051908101604052809291908181526020018280546124d590614480565b80156125225780601f106124f757610100808354040283529160200191612522565b820191906000526020600020905b81548152906001019060200180831161250557829003601f168201915b5050505050905090565b6001600160a01b03808316600090815260036020908152604080832093851683529290529081205460ff16610e2c565b6000806012546013546012546125729190614418565b915091509091565b638da5cb5b60e01b61258e60088233612b45565b806125a757506125a760086303e1469160e61b33612b45565b15610dde576125bf6008638da5cb5b60e01b846126ba565b6125ca6008836128c5565b610e1a6008638da5cb5b60e01b33613226565b6125f0600863ca4b208b60e01b33612b45565b15610dde57601592909255601755601955565b8082556040518181527f83b179bd5cb3a111f82ac98510d3c66f48f77679e657302f4f253d4c32d6d672906020015b60405180910390a15050565b6004820161264c8282614508565b507f13c98778b0c1a086bb98d7f1986e15788b5d3a1ad4c492e1d78f1c4cc51c20cf816040516126329190613e61565b6005820161268a8282614508565b507f3e46ff90086ee29856e77591e82c82ff8ed513379b0fd82e84fc5290dd633c99816040516126329190613e61565b6001600160a01b0381166126e0576040516282b42960e81b815260040160405180910390fd5b6126eb838383612b45565b15612708576040516282b42960e81b815260040160405180910390fd5b6001600160a01b0381166000818152602085815260408083206001600160e01b0319871680855290835292819020805460ff19166001908117909155815193845291830193909352918101919091527fc8bed56f8e046b5a3f2c2b2be85045ea5c972dc18ad669157957897b4d26e9f7906060015b60405180910390a1505050565b61279c826303e1469160e61b83612b45565b156127f6576003820180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec690600090a3505050565b6001600160a01b038116610dde576003820180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec690600090a3505050565b61286b8263ca4b208b60e01b83612b45565b156127f6576002820180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f2cfca82ac51c2fc6b6db547820d28d526a505e12d230afb8bf112a5aeefa9a4c90600090a3505050565b6128d782638da5cb5b60e01b83612b45565b156127f6576001820180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b606081600401805461294290614480565b80601f016020809104026020016040519081016040528092919081815260200182805461296e90614480565b80156129bb5780601f10612990576101008083540402835291602001916129bb565b820191906000526020600020905b81548152906001019060200180831161299e57829003601f168201915b50505050509050919050565b6000818152602083905260408120546001600160a01b0316612a2c57604051630330dbc960e11b815260206004820152600360248201527f4c3a3100000000000000000000000000000000000000000000000000000000006044820152606401611118565b50600090815260029190910160205260409020546001600160a01b031690565b6000818152602085905260409020546001600160a01b03908116908416819003612ab957604051630330dbc960e11b815260206004820152600360248201527f4c3a3200000000000000000000000000000000000000000000000000000000006044820152606401611118565b612ac4858484613c55565b612b1157604051630330dbc960e11b815260206004820152600360248201527f4c3a3300000000000000000000000000000000000000000000000000000000006044820152606401611118565b50600090815260029390930160205250604090912080546001600160a01b0319166001600160a01b03909216919091179055565b60006001600160a01b038216612b6d576040516282b42960e81b815260040160405180910390fd5b506001600160a01b03166000908152602092835260408082206001600160e01b03199390931682529190925290205460ff1690565b6103e88161ffff16101580612bb9575061ffff8116155b15612c0757604051630330dbc960e11b815260206004820152600360248201527f523a3100000000000000000000000000000000000000000000000000000000006044820152606401611118565b82546001600160a01b0383811675ffffffffffffffffffffffffffffffffffffffffffff1990921691909117600160a01b61ffff84811682029290921780875560408051948216855291900490911660208301527f712ca2ffb17da9e3b90d98d54938dee8be84b528cbdec691d680c1df8b78538a910161277d565b6000610d4f826007015490565b6001600160a01b038216612cd057604051630330dbc960e11b81526004016111189060208082526004908201526350533a3360e01b604082015260600190565b80600003612d2357604051630330dbc960e11b81526004016111189060208082526004908201527f50533a3400000000000000000000000000000000000000000000000000000000604082015260600190565b6001600160a01b038216600090815260028401602052604090205415612d8e57604051630330dbc960e11b81526004016111189060208082526004908201527f50533a3500000000000000000000000000000000000000000000000000000000604082015260600190565b6004830180546001810182556000918252602080832090910180546001600160a01b0319166001600160a01b038616908117909155825260028501905260408120829055835482918591612de3908490614418565b9091555050604080516001600160a01b0384168152602081018390527f40c340f65e17194d14ddddb073d3c9f888e3cb52b5aae0c6c7706b4fbc905fac910161277d565b612e32858383613c55565b612e7f57604051630330dbc960e11b815260206004820152600360248201527f4c3a3500000000000000000000000000000000000000000000000000000000006044820152606401611118565b6000818152602086905260409020546001600160a01b039081169085168114612eeb57604051630330dbc960e11b815260206004820152600360248201527f4c3a3600000000000000000000000000000000000000000000000000000000006044820152606401611118565b6001600160a01b038416612f4257604051630330dbc960e11b815260206004820152600360248201527f4c3a3700000000000000000000000000000000000000000000000000000000006044820152606401611118565b612f4f8660008585612a4c565b6001600160a01b0385166000908152600187810160205260408220805491929091612f7b9084906145c8565b90915550506001600160a01b0384166000908152600187810160205260408220805491929091612fac908490614418565b909155505050600090815260209490945250604090922080546001600160a01b0319166001600160a01b039093169290921790915550565b6060816004018054806020026020016040519081016040528092919081815260200182805480156129bb57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116130205750505050509050919050565b8083600101600082825461305d9190614418565b90915550506001600160a01b03821660009081526003840160205260408120805483929061308c908490614418565b9091555050604080516001600160a01b0384168152602081018390527fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b056910161277d565b804710156131205760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401611118565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461316d576040519150601f19603f3d011682016040523d82523d6000602084013e613172565b606091505b5050905080610fe15760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401611118565b82546001600160a01b038116906000906103e89061321290600160a01b900461ffff168561442b565b61321c9190614458565b9050935093915050565b6001600160a01b03811661324c576040516282b42960e81b815260040160405180910390fd5b613257838383612b45565b613273576040516282b42960e81b815260040160405180910390fd5b6001600160a01b0381166000818152602085815260408083206001600160e01b03198716808552908352818420805460ff19169055815190815291820193909352918201527fc8bed56f8e046b5a3f2c2b2be85045ea5c972dc18ad669157957897b4d26e9f79060600161277d565b6001600160a01b03821661333957604051630330dbc960e11b815260206004820152600360248201527f4c3a3800000000000000000000000000000000000000000000000000000000006044820152606401611118565b6000818152602084905260409020546001600160a01b03161561339f57604051630330dbc960e11b815260206004820152600360248201527f4c3a3900000000000000000000000000000000000000000000000000000000006044820152606401611118565b6001600160a01b03821660009081526001848101602052604082208054919290916133cb908490614418565b9091555050600081815260208490526040902080546001600160a01b0319166001600160a01b0384161790556007830180546001019055505050565b6001600160a01b03811661344757604051630330dbc960e11b81526004016111189060208082526004908201526350533a3360e01b604082015260600190565b60006134538383613b8c565b60048401805491925060009161346b906001906145c8565b8154811061347b5761347b6143d3565b6000918252602090912001546004850180546001600160a01b0390921692508291849081106134ac576134ac6143d3565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550836004018054806134ed576134ed614817565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0385168252600286019052604081208054908290558554909182918791906135439084906145c8565b9091555050604080516001600160a01b0386168152602081018390527f104b8837ec12e86f303ac7ce5e3bf20c6790f843fabd7451943f3390fc8376cb9101612015565b600481015460005b818110156135db5760008360040182815481106135ae576135ae6143d3565b60009182526020808320909101546001600160a01b0316825260028601905260408120555060010161358f565b5060008083556135ef906004840190613dac565b6040517f3407fd525bf6581e0ae8e3a3636bd90d02112bea34d66802743c28ced73f910e90600090a15050565b6000826136298584613cd4565b14949350505050565b600061364061010083614458565b905060006136506101008461446c565b6000928352601660205260409092208054600190931b9092179091555050565b606081600501805461294290614480565b826001600160a01b0316826001600160a01b0316036136e357604051630330dbc960e11b815260206004820152600360248201527f4c3a3400000000000000000000000000000000000000000000000000000000006044820152606401611118565b6001600160a01b0391821660009081526003949094016020908152604080862094909316855292909252909120805460ff1916911515919091179055565b60006001600160a01b0384163b1561381757604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061376590339089908890889060040161482d565b6020604051808303816000875af19250505080156137a0575060408051601f3d908101601f1916820190925261379d91810190614869565b60015b6137fd573d8080156137ce576040519150601f19603f3d011682016040523d82523d6000602084013e6137d3565b606091505b5080516000036137f5576040516282b42960e81b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061381b565b5060015b949350505050565b600061383161010083614458565b905060006138416101008461446c565b6000928352601860205260409092208054600190931b9092179091555050565b6060816000036138a457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156138ce57806138b881614886565b91506138c79050600a83614458565b91506138a8565b60008167ffffffffffffffff8111156138e9576138e9614195565b6040519080825280601f01601f191660200182016040528015613913576020820181803683370190505b5090505b841561381b576139286001836145c8565b9150613935600a8661446c565b613940906030614418565b60f81b818381518110613955576139556143d3565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061398f600a86614458565b9450613917565b606081516000036139b557505060408051602081019091526000815290565b60006040518060600160405280604081526020016148a060409139905060006003845160026139e49190614418565b6139ee9190614458565b6139f990600461442b565b67ffffffffffffffff811115613a1157613a11614195565b6040519080825280601f01601f191660200182016040528015613a3b576020820181803683370190505b509050600182016020820185865187015b80821015613aa7576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f8116850151845350600183019250613a4c565b5050600386510660018114613ac35760028114613ad657613ade565b603d6001830353603d6002830353613ade565b603d60018303535b509195945050505050565b6000613af761010083614458565b90506000613b076101008461446c565b6000928352601a60205260409092208054600190931b9092179091555050565b805475ffffffffffffffffffffffffffffffffffffffffffff19168082556040805160008152600160a01b90920461ffff1660208301527f712ca2ffb17da9e3b90d98d54938dee8be84b528cbdec691d680c1df8b78538a910160405180910390a150565b6000806000613bf785600401805480602002602001604051908101604052809291908181526020018280548015613bec57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613bce575b505050505085613d21565b915091508115613c0a579150610d4f9050565b604051630330dbc960e11b81526004016111189060208082526004908201527f50533a3600000000000000000000000000000000000000000000000000000000604082015260600190565b6000818152602084905260408120546001600160a01b03908116908416811480613ca657506001600160a01b03808216600090815260038701602090815260408083209388168352929052205460ff165b80613ccb5750836001600160a01b0316613cc086856129c7565b6001600160a01b0316145b95945050505050565b600081815b8451811015613d1957613d0582868381518110613cf857613cf86143d3565b6020026020010151613d7d565b915080613d1181614886565b915050613cd9565b509392505050565b81516000908190815b81811015613d7457846001600160a01b0316868281518110613d4e57613d4e6143d3565b60200260200101516001600160a01b031603613d6c57600193508092505b600101613d2a565b50509250929050565b6000818310613d99576000828152602084905260409020610e2c565b6000838152602083905260409020610e2c565b508054600082559060005260206000209081019061106391905b80821115613dda5760008155600101613dc6565b5090565b6001600160e01b03198116811461106357600080fd5b600060208284031215613e0657600080fd5b8135610e2c81613dde565b60005b83811015613e2c578181015183820152602001613e14565b50506000910152565b60008151808452613e4d816020860160208601613e11565b601f01601f19169290920160200192915050565b602081526000610e2c6020830184613e35565b600060208284031215613e8657600080fd5b5035919050565b80356001600160a01b0381168114613ea457600080fd5b919050565b60008060408385031215613ebc57600080fd5b613ec583613e8d565b946020939093013593505050565b60008060408385031215613ee657600080fd5b50508035926020909101359150565b803561ffff81168114613ea457600080fd5b60008060408385031215613f1a57600080fd5b613f2383613e8d565b9150613f3160208401613ef5565b90509250929050565b60008060408385031215613f4d57600080fd5b8235613f5881613dde565b9150613f3160208401613e8d565b600080600080600060808688031215613f7e57600080fd5b613f8786613e8d565b9450613f9560208701613e8d565b935060408601359250606086013567ffffffffffffffff80821115613fb957600080fd5b818801915088601f830112613fcd57600080fd5b813581811115613fdc57600080fd5b896020828501011115613fee57600080fd5b9699959850939650602001949392505050565b60008060006060848603121561401657600080fd5b8335925061402660208501613e8d565b915061403460408501613ef5565b90509250925092565b60008060006060848603121561405257600080fd5b61405b84613e8d565b925061406960208501613e8d565b9150604084013590509250925092565b60006020828403121561408b57600080fd5b610e2c82613e8d565b6020808252825182820181905260009190848201906040850190845b818110156140d55783516001600160a01b0316835292840192918401916001016140b0565b50909695505050505050565b60008083601f8401126140f357600080fd5b50813567ffffffffffffffff81111561410b57600080fd5b6020830191508360208260051b850101111561412657600080fd5b9250929050565b60008060008060006080868803121561414557600080fd5b8535945061415560208701613e8d565b935060408601359250606086013567ffffffffffffffff81111561417857600080fd5b614184888289016140e1565b969995985093965092949392505050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126141bc57600080fd5b813567ffffffffffffffff808211156141d7576141d7614195565b604051601f8301601f19908116603f011681019082821181831017156141ff576141ff614195565b8160405283815286602085880101111561421857600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561424d57600080fd5b833567ffffffffffffffff8082111561426557600080fd5b614271878388016141ab565b9450602086013591508082111561428757600080fd5b614293878388016141ab565b935060408601359150808211156142a957600080fd5b506142b6868287016141ab565b9150509250925092565b6000602082840312156142d257600080fd5b813567ffffffffffffffff8111156142e957600080fd5b61381b848285016141ab565b6000806040838503121561430857600080fd5b61431183613e8d565b91506020830135801515811461432657600080fd5b809150509250929050565b6000806000806060858703121561434757600080fd5b8435935061435760208601613e8d565b9250604085013567ffffffffffffffff81111561437357600080fd5b61437f878288016140e1565b95989497509550505050565b6000806040838503121561439e57600080fd5b613f5883613e8d565b6000806000606084860312156143bc57600080fd5b505081359360208301359350604090920135919050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156143fb57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610d4f57610d4f614402565b8082028115828204841417610d4f57610d4f614402565b634e487b7160e01b600052601260045260246000fd5b60008261446757614467614442565b500490565b60008261447b5761447b614442565b500690565b600181811c9082168061449457607f821691505b6020821081036144b457634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610fe157600081815260208120601f850160051c810160208610156144e15750805b601f850160051c820191505b81811015614500578281556001016144ed565b505050505050565b815167ffffffffffffffff81111561452257614522614195565b614536816145308454614480565b846144ba565b602080601f83116001811461456b57600084156145535750858301515b600019600386901b1c1916600185901b178555614500565b600085815260208120601f198616915b8281101561459a5788860151825594840194600190910190840161457b565b50858210156145b85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b81810381811115610d4f57610d4f614402565b600081546145e881614480565b60018281168015614600576001811461461557614644565b60ff1984168752821515830287019450614644565b8560005260208060002060005b8581101561463b5781548a820152908401908201614622565b50505082870194505b5050505092915050565b7f7b0000000000000000000000000000000000000000000000000000000000000081527f226e616d65223a2022486f6d6965732047656e657369732023000000000000006001820152600085516146ac81601a850160208a01613e11565b80830190507f222c00000000000000000000000000000000000000000000000000000000000080601a8301527f226465736372697074696f6e223a202200000000000000000000000000000000601c83015261470b602c8301886145db565b91508082527f22696d616765223a2022000000000000000000000000000000000000000000006002830152614743600c8301876145db565b9081527f22616e696d6174696f6e5f75726c223a202200000000000000000000000000006002820152905061477b60148201856145db565b7f220000000000000000000000000000000000000000000000000000000000000081527f7d000000000000000000000000000000000000000000000000000000000000006001820152600201979650505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161480a81601d850160208701613e11565b91909101601d0192915050565b634e487b7160e01b600052603160045260246000fd5b60006001600160a01b0380871683528086166020840152508360408301526080606083015261485f6080830184613e35565b9695505050505050565b60006020828403121561487b57600080fd5b8151610e2c81613dde565b60006001820161489857614898614402565b506001019056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220ed328c08ff18b159f7e3d70e6781cd2a14eded050466f4014276ca6751db6b2c64736f6c63430008110033

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

00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000004ce69fd760ad0c07490178f9a47863dc0358cccd0000000000000000000000004ce69fd760ad0c07490178f9a47863dc0358cccd000000000000000000000000e318cde62513f8c21e91e5211ff33a7eedf78a2f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000e486f6d696573206f6620576562330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004486f573300000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): Homies of Web3
Arg [1] : _symbol (string): HoW3
Arg [2] : _admin (address): 0x4CE69fd760AD0c07490178f9a47863Dc0358cCCD
Arg [3] : _dev (address): 0x4CE69fd760AD0c07490178f9a47863Dc0358cCCD
Arg [4] : _owner (address): 0xE318Cde62513F8C21e91E5211ff33A7eedF78A2F
Arg [5] : _start (uint256): 1

-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [2] : 0000000000000000000000004ce69fd760ad0c07490178f9a47863dc0358cccd
Arg [3] : 0000000000000000000000004ce69fd760ad0c07490178f9a47863dc0358cccd
Arg [4] : 000000000000000000000000e318cde62513f8c21e91e5211ff33a7eedf78a2f
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [6] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [7] : 486f6d696573206f662057656233000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [9] : 486f573300000000000000000000000000000000000000000000000000000000


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.