ETH Price: $2,921.26 (+4.56%)
 

Overview

Max Total Supply

1,000 KLDSCP

Holders

180

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
urtooslow.eth
Balance
20 KLDSCP
0x702f99334E19c045a35Ca22F2274EC49Ca002d94
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
Kaleidoscopes

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 11 : Kaleidoscopes.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.12;

import "erc721a/contracts/ERC721A.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "./Utilities.sol";
import "./Renderer.sol";
import "svgnft/contracts/Base64.sol";

contract Kaleidoscopes is ERC721A, Ownable {
  uint256 public price;
  uint256 public maxSupply;
  uint256 public constant maxMintPerWallet = 20;

  Renderer public renderer;

  bytes32 public merkleRoot;

  uint256 public allowListMintStartBlock;
  uint256 public publicMintOffsetBlocks; // 3 hours

  /**
   * @dev Constructs a new instance of the contract.
   * @param _name Name of the ERC721 token.
   * @param _symbol Symbol of the ERC721 token.
   * @param _price Price of each token in wei.
   * @param _maxSupply Maximum supply of tokens.
   */
  constructor(
    string memory _name,
    string memory _symbol,
    uint256 _price,
    uint256 _maxSupply,
    bytes32 _merkleRoot,
    uint256 _allowListMintStartBlock,
    uint256 _publicMintOffsetBlocks,
    address _renderer
  ) ERC721A(_name, _symbol) {
    price = _price;
    maxSupply = _maxSupply;
    merkleRoot = _merkleRoot;
    allowListMintStartBlock = _allowListMintStartBlock;
    publicMintOffsetBlocks = _publicMintOffsetBlocks;
    renderer = Renderer(_renderer);
  }

  /**
   * @notice Checks if public sale has started.
   */
  function hasPublicSaleStarted() public view returns (bool) {
    return block.number >= allowListMintStartBlock + publicMintOffsetBlocks;
  }

  /**
   * @notice Checks if allow list sale has started.
   */
  function hasAllowlistSaleStarted() public view returns (bool) {
    return block.number >= allowListMintStartBlock;
  }

  /**
   * @notice Sets the block at which the allowlist mint starts.
   * @param _allowListMintStartBlock Block at which the allowlist mint starts.
   */
  function setAllowListMintStartBlock(uint256 _allowListMintStartBlock) external onlyOwner {
    allowListMintStartBlock = _allowListMintStartBlock;
  }

  /**
   * @notice Sets the number of blocks after which the public sale starts.
   * @param _publicMintOffsetBlocks Number of blocks.
   */
  function setPublicMintOffsetBlocks(uint256 _publicMintOffsetBlocks) external onlyOwner {
    publicMintOffsetBlocks = _publicMintOffsetBlocks;
  }

  /**
   * @notice Sets the price of each token in wei.
   * @param _price Price of each token in wei.
   */
  function setPrice(uint256 _price) external onlyOwner {
    price = _price;
  }

  /**
   * @notice Returns the token URI for a given token ID.
   * @param _tokenId ID of the token to get the URI for.
   * @return Token URI.
   */
  function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) {
    if (!_exists(_tokenId)) revert URIQueryForNonexistentToken();

    string memory name = string(abi.encodePacked("Kaleidoscope #", utils.uint2str(_tokenId)));
    string memory description = "Fully on-chain, procedurally generated, animated kaleidoscopes.";
    Renderer.Kaleidoscope memory kaleidoscope = renderer.kaleidoscopeForTokenId(_tokenId);
    kaleidoscope.hasHalo = _tokenId <= 50;

    Renderer.ColorPalette memory palette = renderer.colorPaletteForKaleidescope(kaleidoscope);
    string memory svg = renderer.getKaleidoscopeSVG(kaleidoscope, palette);

    string memory attributes = string.concat(
      '"attributes": [',
      '{"trait_type": "Mirrors", "value": ',
      utils.uint2str(kaleidoscope.repetitions),
      "},",
      '{"trait_type": "Outside Artifacts", "value": ',
      utils.uint2str(kaleidoscope.numOutsideArtifacts),
      "},",
      '{"trait_type": "Inside Artifacts", "value": ',
      utils.uint2str(kaleidoscope.numInsideArtifacts),
      "},",
      '{"trait_type": "Gradient", "value": "',
      kaleidoscope.hasGradient ? "Yes" : "No",
      '"},',
      '{"trait_type": "Primary Color", "value": "',
      utils.getHueName(palette.primaryHue),
      '"}'
    );

    if (kaleidoscope.hasSecondaryColor) {
      attributes = string.concat(
        attributes,
        ',{"trait_type": "Secondary Color", "value": "',
        utils.getHueName(palette.secondaryHue),
        '"}'
      );
    }

    if (kaleidoscope.hasHalo) {
      attributes = string.concat(attributes, ',{"trait_type": "Halo", "value": "Yes"}');
    }

    attributes = string.concat(attributes, "]");

    string memory json = string(
      abi.encodePacked(
        '{"name":"',
        name,
        '","description":"',
        description,
        '",',
        attributes,
        ', "image": "data:image/svg+xml;base64,',
        Base64.encode(bytes(svg)),
        '"}'
      )
    );
    return string(abi.encodePacked("data:application/json;base64,", Base64.encode(bytes(json))));
  }

  /**
   * @notice Mints new tokens for the caller.
   * @param _quantity Quantity of tokens to mint.
   */
  function mint(uint256 _quantity) internal {
    require(msg.value >= price * _quantity, "Insufficient fee");
    require(totalSupply() + _quantity <= maxSupply, "Exceeds max supply");
    require(_numberMinted(msg.sender) + _quantity <= 20, "Exceeds max quantity");
    _mint(msg.sender, _quantity);

    // Refund any extra ETH sent
    if (msg.value > price * _quantity) {
      (bool status, ) = payable(msg.sender).call{value: msg.value - price * _quantity}("");
      require(status, "Refund failed");
    }
  }

  /**
   * @notice  Airdrops tokens to a list of recipients. Only callable by the contract owner.
   * @param _recipients List of recipients to receive the airdrop.
   * @param _quantity Quantity of tokens to airdrop to each recipient.
   */
  function airdrop(address[] memory _recipients, uint256 _quantity) external payable onlyOwner {
    require(totalSupply() + _quantity * _recipients.length <= maxSupply, "Exceeds max supply");
    for (uint256 i = 0; i < _recipients.length; i++) {
      _mint(_recipients[i], _quantity);
    }
  }

  /**
   * @notice Withdraws the contract's balance. Only callable by the contract owner.
   */
  function withdraw() external onlyOwner {
    require(payable(msg.sender).send(address(this).balance));
  }

  /**
   * @notice Checks if a wallet is on the allowlist given a Merkle proof.
   * @param _wallet Wallet to check.
   * @param _proof Merkle proof.
   */
  function allowListed(address _wallet, bytes32[] calldata _proof) public view returns (bool) {
    return MerkleProof.verify(_proof, merkleRoot, keccak256(abi.encodePacked(_wallet)));
  }

  /**
   * @notice Mints tokens for the caller if they are on the allowlist.
   * @param _quantity Quantity of tokens to mint.
   * @param _proof Merkle proof.
   */
  function mintAllowList(uint256 _quantity, bytes32[] calldata _proof) external payable {
    require(allowListed(msg.sender, _proof), "You are not on the allowlist");
    require(hasAllowlistSaleStarted(), "Allowlist sale has not started yet");
    mint(_quantity);
  }

  /**
   * @notice Mints tokens for the caller if public sale has started.
   * @param _quantity Quantity of tokens to mint.
   */
  function mintPublic(uint256 _quantity) external payable {
    require(hasPublicSaleStarted(), "Public sale has not started yet");
    mint(_quantity);
  }

  function mintQuotaRemaining(address _wallet) external view returns (uint256) {
    return maxMintPerWallet - _numberMinted(_wallet);
  }

  function _startTokenId() internal view virtual override returns (uint256) {
    return 1;
  }
}

File 2 of 11 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

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

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

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

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

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

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

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

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

File 3 of 11 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

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

File 4 of 11 : 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 5 of 11 : Renderer.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

import "./Trigonometry.sol";
import "./Utilities.sol";
import "hardhat/console.sol";

contract Renderer {
  uint256 constant SIZE = 500;
  uint256 constant RADIUS = 200;
  uint256 constant PRECISION_DEGREE = 7;
  uint256 constant PRECISION = 10**PRECISION_DEGREE;

  struct ColorPalette {
    uint256 primaryHue;
    uint256 secondaryHue;
    utils.HSL primaryColorHsl;
    utils.HSL secondaryColorHsl;
    utils.HSL backgroundColorHsl;
    utils.HSL darkerSecondaryHsl;
    utils.HSL[] primaryColorsHsl;
    utils.HSL[] secondaryColorsHsl;
  }

  struct Kaleidoscope {
    uint256 tokenId;
    uint256 repetitions;
    uint256 numInsideArtifacts;
    uint256 numOutsideArtifacts;
    uint256 centerX_precise;
    uint256 centerY_precise;
    bool hasGradient;
    bool hasSecondaryColor;
    bool hasHalo;
  }

  struct AnimatedCircle {
    // Start position
    int256 x1;
    int256 y1;
    // End position
    int256 x2;
    int256 y2;
    uint256 radius1;
    uint256 radius2;
    uint256 alternatingClass;
    uint256 duration;
    utils.HSL color;
  }

  struct AnimatedTriangle {
    uint256 x1;
    uint256 y1;
    uint256 centerX;
    uint256 centerY;
    uint256 duration;
    utils.HSL color;
  }

  struct AnimatedRectangle {
    uint256 width;
    uint256 height;
    uint256 x;
    uint256 y;
    uint256 duration;
    utils.HSL color;
  }

  function colorPaletteForKaleidescope(Kaleidoscope memory _kaleidoscope)
    public
    pure
    returns (ColorPalette memory palette)
  {
    palette.primaryHue = utils.randomRange(_kaleidoscope.tokenId, "primaryHue", 0, 360);
    palette.secondaryHue = _kaleidoscope.hasSecondaryColor ? (palette.primaryHue + 240) % 360 : palette.primaryHue;
    palette.primaryColorHsl = utils.HSL(palette.primaryHue, 100, 30);
    palette.secondaryColorHsl = utils.HSL(palette.secondaryHue, 100, 70);
    palette.backgroundColorHsl = utils.HSL(palette.primaryHue, 100, 10);
    palette.darkerSecondaryHsl = utils.HSL((palette.primaryHue + 10) % 360, 100, 10);
    palette.primaryColorsHsl = utils.generateColors(palette.primaryHue, _kaleidoscope.numInsideArtifacts + 1);
    palette.secondaryColorsHsl = utils.generateColors(palette.secondaryHue, _kaleidoscope.numInsideArtifacts + 1);

    return palette;
  }

  function kaleidoscopeForTokenId(uint256 _tokenId) public pure returns (Kaleidoscope memory kaleidoscope) {
    kaleidoscope.tokenId = _tokenId;
    kaleidoscope.repetitions = utils.randomRange(_tokenId, "repetitions", 3, 20);
    kaleidoscope.numInsideArtifacts = utils.randomRange(_tokenId, "numInsideArtifacts", 3, 10);
    kaleidoscope.numOutsideArtifacts = utils.randomRange(_tokenId, "numOutsideArtifacts", 1, 4);
    kaleidoscope.hasGradient = utils.randomRange(_tokenId, "hasGradient", 1, 10) == 5;
    kaleidoscope.hasSecondaryColor = utils.randomRange(_tokenId, "secondaryColor", 1, 8) == 8;

    uint256 angle = (((180 - 360 / kaleidoscope.repetitions) / 2) * Trigonometry.PI) / 180;
    kaleidoscope.centerX_precise = uint256(
      (int256(RADIUS) * Trigonometry.cos(angle)) / int256(10**(18 - PRECISION_DEGREE))
    );
    kaleidoscope.centerY_precise = uint256(
      (int256(RADIUS) * Trigonometry.sin(angle)) / int256(10**(18 - PRECISION_DEGREE))
    );

    return kaleidoscope;
  }

  function circleAtIndexForKaleidescope(
    Kaleidoscope memory _kaleidoscope,
    ColorPalette memory _palette,
    uint256 _index
  ) public pure returns (AnimatedCircle memory circle) {
    uint256 yUpperBound = (_kaleidoscope.centerY_precise / PRECISION) + RADIUS / 8;

    circle.y1 = int256(
      utils.randomRange(_kaleidoscope.tokenId, string.concat("y1", utils.uint2str(_index)), 20, yUpperBound)
    );
    circle.y2 = int256(
      utils.randomRange(_kaleidoscope.tokenId, string.concat("y2", utils.uint2str(_index)), 20, yUpperBound)
    );

    circle.alternatingClass = utils.randomRange(
      _kaleidoscope.tokenId,
      string.concat("alternatingClass", utils.uint2str(_index)),
      0,
      3
    );

    if (circle.y1 > circle.y2 && circle.alternatingClass % 2 == 0) {
      int256 temp = circle.y1;
      circle.y1 = circle.y2;
      circle.y2 = temp;
    }

    int256 gradient_1000 = int256((_kaleidoscope.centerY_precise * 1000) / _kaleidoscope.centerX_precise);

    uint256 radiusUB = (_kaleidoscope.centerX_precise / PRECISION) * 2;
    circle.radius1 = uint256(
      utils.min((radiusUB * (1000 - (uint256(circle.y1) * 1000) / yUpperBound)) / 1000, radiusUB)
    );
    circle.radius2 = uint256(
      utils.min((radiusUB * (1000 - (uint256(circle.y2) * 1000) / yUpperBound)) / 1000, radiusUB)
    );

    // x1 should be within bounds of triangular path
    int256 lb1 = (circle.y1 * 1000) / gradient_1000;
    circle.x1 = int256(lb1 - int256(circle.radius1) * 2);

    // x2 should be within bounds of triangular path
    int256 lb2 = (circle.y2 * 1000) / gradient_1000;
    circle.x2 = int256(2 * int256(_kaleidoscope.centerX_precise / PRECISION) - lb2 + int256(circle.radius2) * 2);

    circle.duration = utils.randomRange(_kaleidoscope.tokenId, string.concat("duration", utils.uint2str(_index)), 3, 7);

    circle.color = _index % 2 == 0 ? _palette.primaryColorsHsl[_index + 1] : _palette.secondaryColorsHsl[_index + 1];

    return circle;
  }

  function rectangleAtIndexForKaleidescope(
    Kaleidoscope memory _kaleidoscope,
    ColorPalette memory _palette,
    uint256 _index
  ) public pure returns (AnimatedRectangle memory rectangle) {
    rectangle.width = utils.randomRange(
      _kaleidoscope.tokenId,
      string.concat("rectwidth", utils.uint2str(_index)),
      (_kaleidoscope.centerY_precise / PRECISION) / 2,
      (_kaleidoscope.centerY_precise / PRECISION)
    );
    rectangle.height = utils.randomRange(
      _kaleidoscope.tokenId,
      string.concat("rectheight", utils.uint2str(_index)),
      (_kaleidoscope.centerY_precise / PRECISION),
      _kaleidoscope.centerY_precise * 2 + RADIUS / 8
    );
    rectangle.x = 0;
    rectangle.y = _kaleidoscope.centerY_precise / PRECISION;
    rectangle.duration = utils.randomRange(
      _kaleidoscope.tokenId,
      string.concat("rectduration", utils.uint2str(_index)),
      5,
      10
    );
    rectangle.color = _index % 2 == 0 ? _palette.primaryColorsHsl[0] : _palette.secondaryColorsHsl[0];

    return rectangle;
  }

  function getCircleSVG(AnimatedCircle memory _circle) public pure returns (string memory) {
    string memory animations = string.concat(
      '<animate attributeName="r" values="',
      utils.uint2str(_circle.radius1),
      ";",
      utils.uint2str(_circle.radius2),
      ";",
      utils.uint2str(_circle.radius1),
      ";",
      utils.uint2str(_circle.radius2),
      '" calcMode="linear" dur="',
      utils.uint2str(_circle.duration * 2),
      's" repeatCount="indefinite"/>'
    );

    animations = string.concat(
      animations,
      '<animate attributeName="cy" values="',
      utils.int2str(_circle.y1),
      ";",
      utils.int2str(_circle.y2),
      ";",
      utils.int2str(_circle.y1),
      ";",
      utils.int2str(_circle.y2),
      '" calcMode="linear" dur="',
      utils.uint2str(_circle.duration * 2),
      's" repeatCount="indefinite"/>'
    );

    animations = string.concat(
      animations,
      '<animate attributeName="cx" values="',
      utils.int2str(_circle.x1),
      ";",
      utils.int2str(_circle.x2),
      ";",
      utils.int2str(_circle.x1),
      ";",
      utils.int2str(_circle.x2),
      '" calcMode="linear" dur="',
      utils.uint2str(_circle.duration * 2),
      's" repeatCount="indefinite"/>'
    );

    return
      string.concat(
        '<circle cx="',
        utils.int2str((_circle.x1 + _circle.x2) / 2),
        '" cy="',
        utils.int2str((_circle.y1 + _circle.y2) / 2),
        '" r="',
        utils.uint2str((_circle.radius1 + _circle.radius2) / 2),
        '" fill="',
        utils.getHslString(_circle.color),
        '">',
        animations,
        "</circle>"
      );
  }

  function getRectangleSVG(AnimatedRectangle memory _rectangle) public pure returns (string memory) {
    string memory animations = string.concat(
      '<animateTransform attributeName="transform" type="rotate" from="0 0 -',
      utils.uint2str(_rectangle.y),
      '" to="-360 0 -',
      utils.uint2str(_rectangle.y),
      '" begin="0s" dur="',
      utils.uint2str(_rectangle.duration),
      's" repeatCount="indefinite" />'
    );

    return
      string.concat(
        '<rect rx="3" ry="3" x="0" y="-',
        utils.uint2str(_rectangle.y),
        '" width="',
        utils.uint2str(_rectangle.width),
        '" height="',
        utils.uint2str(_rectangle.height),
        '" fill="',
        utils.getHslString(_rectangle.color),
        '">',
        animations,
        "</rect>"
      );
  }

  function linearGradient(string memory _stop1Color, string memory _stop2Color) internal pure returns (string memory) {
    return
      string.concat(
        '<linearGradient id="gradient">',
        '<stop offset="0%" stop-color="',
        _stop1Color,
        '"/>',
        '<stop offset="100%" stop-color="',
        _stop2Color,
        '"/>',
        "</linearGradient>"
      );
  }

  function getKaleidoscopeSVG(Kaleidoscope memory _kaleidoscope, ColorPalette memory _palette)
    public
    pure
    returns (string memory)
  {
    // Get outer artifacts
    string memory outerArtifacts = "";
    for (uint256 i = 0; i < _kaleidoscope.numOutsideArtifacts; i++) {
      // Rectangle
      AnimatedRectangle memory rectangle = rectangleAtIndexForKaleidescope(_kaleidoscope, _palette, i);
      outerArtifacts = string.concat(outerArtifacts, getRectangleSVG(rectangle));
    }

    string memory innerArtifacts = "";
    for (uint256 i = 0; i < _kaleidoscope.numInsideArtifacts; i++) {
      AnimatedCircle memory circle = circleAtIndexForKaleidescope(_kaleidoscope, _palette, i);
      innerArtifacts = string.concat(innerArtifacts, getCircleSVG(circle));
    }

    string memory paths = "";
    uint256 angleInterval = (360 * 10**7) / _kaleidoscope.repetitions;
    for (uint256 i = 0; i < _kaleidoscope.repetitions; i++) {
      paths = string.concat(
        paths,
        '<use href="#tile" transform="rotate(',
        utils.uint2floatstr(angleInterval * i, PRECISION_DEGREE),
        ",",
        utils.uint2floatstr(_kaleidoscope.centerX_precise, PRECISION_DEGREE),
        ",",
        utils.uint2floatstr(_kaleidoscope.centerY_precise, PRECISION_DEGREE),
        ')" />'
      );
    }

    string memory clipPath = string.concat(
      '<clipPath id="clip">',
      '<path d="M0,0L',
      utils.uint2floatstr(_kaleidoscope.centerX_precise, PRECISION_DEGREE),
      ",",
      utils.uint2floatstr(_kaleidoscope.centerY_precise, PRECISION_DEGREE),
      "L",
      utils.uint2floatstr(_kaleidoscope.centerX_precise * 2, PRECISION_DEGREE),
      ",0A",
      utils.uint2str(RADIUS),
      ",",
      utils.uint2str(RADIUS),
      ',0,0,0,0,0Z" />',
      "</clipPath>"
    );

    string memory svg = string.concat(
      '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ',
      utils.uint2str(SIZE),
      " ",
      utils.uint2str(SIZE),
      '" width="',
      utils.uint2str(SIZE),
      '" height="',
      utils.uint2str(SIZE),
      '"><defs>',
      linearGradient(utils.getHslString(_palette.primaryColorHsl), utils.getHslString(_palette.darkerSecondaryHsl)),
      clipPath,
      '<g id="tile" clip-path="url(#clip)">',
      '<rect x="0" y="-',
      utils.uint2str(RADIUS),
      '" width="',
      utils.uint2str(RADIUS * 2),
      '" height="',
      utils.uint2str(RADIUS * 2),
      '" fill="'
    );

    svg = string.concat(
      svg,
      _kaleidoscope.hasGradient ? "url(#gradient)" : utils.getHslString(_palette.primaryColorHsl),
      '"></rect>',
      outerArtifacts,
      innerArtifacts,
      "</g>"
    );

    svg = string.concat(
      svg,
      "</defs>",
      '<rect width="',
      utils.uint2str(SIZE),
      '" height="',
      utils.uint2str(SIZE),
      '" fill="',
      utils.getHslString(_palette.backgroundColorHsl),
      '"></rect>',
      '<g id="kaleidoscopeTile" transform="translate(',
      utils.uint2str(SIZE / 2 - _kaleidoscope.centerX_precise / PRECISION)
      // "0"
    );

    string memory backgroundCircleBase = string.concat(
      '<circle cx="',
      utils.uint2floatstr(_kaleidoscope.centerX_precise, PRECISION_DEGREE),
      '" cy="',
      utils.uint2floatstr(_kaleidoscope.centerY_precise, PRECISION_DEGREE),
      '" r="'
    );

    string memory haloTrait = string.concat(
      backgroundCircleBase,
      utils.uint2str(RADIUS + 8),
      '" fill="none"',
      _kaleidoscope.hasHalo ? ' stroke="#EBA947" stroke-width="4"' : "",
      "/>"
    );

    svg = string.concat(
      svg,
      ",",
      utils.uint2str(SIZE / 2 - _kaleidoscope.centerY_precise / PRECISION),
      // "0",
      ')">',
      backgroundCircleBase,
      utils.uint2str(RADIUS),
      '" fill="',
      utils.getHslString(_palette.primaryColorHsl),
      '" />',
      _kaleidoscope.hasHalo ? haloTrait : ""
    );

    svg = string.concat(svg, paths, "</g>", "</svg>");

    return svg;
  }

  function render(uint256 _tokenId) public pure returns (string memory) {
    Kaleidoscope memory kaleidoscope = kaleidoscopeForTokenId(_tokenId);
    ColorPalette memory palette = colorPaletteForKaleidescope(kaleidoscope);
    string memory svg = getKaleidoscopeSVG(kaleidoscope, palette);

    return svg;
  }

  function metadata(uint256 _tokenId) public pure returns (Kaleidoscope memory) {
    Kaleidoscope memory kaleidoscope = kaleidoscopeForTokenId(_tokenId);
    return kaleidoscope;
  }
}

File 6 of 11 : Trigonometry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

/**
 * @notice Solidity library offering basic trigonometry functions where inputs and outputs are
 * integers. Inputs are specified in radians scaled by 1e18, and similarly outputs are scaled by 1e18.
 *
 * This implementation is based off the Solidity trigonometry library written by Lefteris Karapetsas
 * which can be found here: https://github.com/Sikorkaio/sikorka/blob/e75c91925c914beaedf4841c0336a806f2b5f66d/contracts/trigonometry.sol
 *
 * Compared to Lefteris' implementation, this version makes the following changes:
 *   - Uses a 32 bits instead of 16 bits for improved accuracy
 *   - Updated for Solidity 0.8.x
 *   - Various gas optimizations
 *   - Change inputs/outputs to standard trig format (scaled by 1e18) instead of requiring the
 *     integer format used by the algorithm
 *
 * Lefertis' implementation is based off Dave Dribin's trigint C library
 *     http://www.dribin.org/dave/trigint/
 *
 * Which in turn is based from a now deleted article which can be found in the Wayback Machine:
 *     http://web.archive.org/web/20120301144605/http://www.dattalo.com/technical/software/pic/picsine.html
 */
library Trigonometry {
  // Table index into the trigonometric table
  uint256 constant INDEX_WIDTH = 8;
  // Interpolation between successive entries in the table
  uint256 constant INTERP_WIDTH = 16;
  uint256 constant INDEX_OFFSET = 28 - INDEX_WIDTH;
  uint256 constant INTERP_OFFSET = INDEX_OFFSET - INTERP_WIDTH;
  uint32 constant ANGLES_IN_CYCLE = 1073741824;
  uint32 constant QUADRANT_HIGH_MASK = 536870912;
  uint32 constant QUADRANT_LOW_MASK = 268435456;
  uint256 constant SINE_TABLE_SIZE = 256;

  // Pi as an 18 decimal value, which is plenty of accuracy: "For JPL's highest accuracy calculations, which are for
  // interplanetary navigation, we use 3.141592653589793: https://www.jpl.nasa.gov/edu/news/2016/3/16/how-many-decimals-of-pi-do-we-really-need/
  uint256 constant PI = 3141592653589793238;
  uint256 constant TWO_PI = 2 * PI;
  uint256 constant PI_OVER_TWO = PI / 2;

  // The constant sine lookup table was generated by generate_trigonometry.py. We must use a constant
  // bytes array because constant arrays are not supported in Solidity. Each entry in the lookup
  // table is 4 bytes. Since we're using 32-bit parameters for the lookup table, we get a table size
  // of 2^(32/4) + 1 = 257, where the first and last entries are equivalent (hence the table size of
  // 256 defined above)
  uint8 constant entry_bytes = 4; // each entry in the lookup table is 4 bytes
  uint256 constant entry_mask = ((1 << (8 * entry_bytes)) - 1); // mask used to cast bytes32 -> lookup table entry
  bytes constant sin_table =
    hex"00_00_00_00_00_c9_0f_88_01_92_1d_20_02_5b_26_d7_03_24_2a_bf_03_ed_26_e6_04_b6_19_5d_05_7f_00_35_06_47_d9_7c_07_10_a3_45_07_d9_5b_9e_08_a2_00_9a_09_6a_90_49_0a_33_08_bc_0a_fb_68_05_0b_c3_ac_35_0c_8b_d3_5e_0d_53_db_92_0e_1b_c2_e4_0e_e3_87_66_0f_ab_27_2b_10_72_a0_48_11_39_f0_cf_12_01_16_d5_12_c8_10_6e_13_8e_db_b1_14_55_76_b1_15_1b_df_85_15_e2_14_44_16_a8_13_05_17_6d_d9_de_18_33_66_e8_18_f8_b8_3c_19_bd_cb_f3_1a_82_a0_25_1b_47_32_ef_1c_0b_82_6a_1c_cf_8c_b3_1d_93_4f_e5_1e_56_ca_1e_1f_19_f9_7b_1f_dc_dc_1b_20_9f_70_1c_21_61_b3_9f_22_23_a4_c5_22_e5_41_af_23_a6_88_7e_24_67_77_57_25_28_0c_5d_25_e8_45_b6_26_a8_21_85_27_67_9d_f4_28_26_b9_28_28_e5_71_4a_29_a3_c4_85_2a_61_b1_01_2b_1f_34_eb_2b_dc_4e_6f_2c_98_fb_ba_2d_55_3a_fb_2e_11_0a_62_2e_cc_68_1e_2f_87_52_62_30_41_c7_60_30_fb_c5_4d_31_b5_4a_5d_32_6e_54_c7_33_26_e2_c2_33_de_f2_87_34_96_82_4f_35_4d_90_56_36_04_1a_d9_36_ba_20_13_37_6f_9e_46_38_24_93_b0_38_d8_fe_93_39_8c_dd_32_3a_40_2d_d1_3a_f2_ee_b7_3b_a5_1e_29_3c_56_ba_70_3d_07_c1_d5_3d_b8_32_a5_3e_68_0b_2c_3f_17_49_b7_3f_c5_ec_97_40_73_f2_1d_41_21_58_9a_41_ce_1e_64_42_7a_41_d0_43_25_c1_35_43_d0_9a_ec_44_7a_cd_50_45_24_56_bc_45_cd_35_8f_46_75_68_27_47_1c_ec_e6_47_c3_c2_2e_48_69_e6_64_49_0f_57_ee_49_b4_15_33_4a_58_1c_9d_4a_fb_6c_97_4b_9e_03_8f_4c_3f_df_f3_4c_e1_00_34_4d_81_62_c3_4e_21_06_17_4e_bf_e8_a4_4f_5e_08_e2_4f_fb_65_4c_50_97_fc_5e_51_33_cc_94_51_ce_d4_6e_52_69_12_6e_53_02_85_17_53_9b_2a_ef_54_33_02_7d_54_ca_0a_4a_55_60_40_e2_55_f5_a4_d2_56_8a_34_a9_57_1d_ee_f9_57_b0_d2_55_58_42_dd_54_58_d4_0e_8c_59_64_64_97_59_f3_de_12_5a_82_79_99_5b_10_35_ce_5b_9d_11_53_5c_29_0a_cc_5c_b4_20_df_5d_3e_52_36_5d_c7_9d_7b_5e_50_01_5d_5e_d7_7c_89_5f_5e_0d_b2_5f_e3_b3_8d_60_68_6c_ce_60_ec_38_2f_61_6f_14_6b_61_f1_00_3e_62_71_fa_68_62_f2_01_ac_63_71_14_cc_63_ef_32_8f_64_6c_59_bf_64_e8_89_25_65_63_bf_91_65_dd_fb_d2_66_57_3c_bb_66_cf_81_1f_67_46_c7_d7_67_bd_0f_bc_68_32_57_aa_68_a6_9e_80_69_19_e3_1f_69_8c_24_6b_69_fd_61_4a_6a_6d_98_a3_6a_dc_c9_64_6b_4a_f2_78_6b_b8_12_d0_6c_24_29_5f_6c_8f_35_1b_6c_f9_34_fb_6d_62_27_f9_6d_ca_0d_14_6e_30_e3_49_6e_96_a9_9c_6e_fb_5f_11_6f_5f_02_b1_6f_c1_93_84_70_23_10_99_70_83_78_fe_70_e2_cb_c5_71_41_08_04_71_9e_2c_d1_71_fa_39_48_72_55_2c_84_72_af_05_a6_73_07_c3_cf_73_5f_66_25_73_b5_eb_d0_74_0b_53_fa_74_5f_9d_d0_74_b2_c8_83_75_04_d3_44_75_55_bd_4b_75_a5_85_ce_75_f4_2c_0a_76_41_af_3c_76_8e_0e_a5_76_d9_49_88_77_23_5f_2c_77_6c_4e_da_77_b4_17_df_77_fa_b9_88_78_40_33_28_78_84_84_13_78_c7_ab_a1_79_09_a9_2c_79_4a_7c_11_79_8a_23_b0_79_c8_9f_6d_7a_05_ee_ac_7a_42_10_d8_7a_7d_05_5a_7a_b6_cb_a3_7a_ef_63_23_7b_26_cb_4e_7b_5d_03_9d_7b_92_0b_88_7b_c5_e2_8f_7b_f8_88_2f_7c_29_fb_ed_7c_5a_3d_4f_7c_89_4b_dd_7c_b7_27_23_7c_e3_ce_b1_7d_0f_42_17_7d_39_80_eb_7d_62_8a_c5_7d_8a_5f_3f_7d_b0_fd_f7_7d_d6_66_8e_7d_fa_98_a7_7e_1d_93_e9_7e_3f_57_fe_7e_5f_e4_92_7e_7f_39_56_7e_9d_55_fb_7e_ba_3a_38_7e_d5_e5_c5_7e_f0_58_5f_7f_09_91_c3_7f_21_91_b3_7f_38_57_f5_7f_4d_e4_50_7f_62_36_8e_7f_75_4e_7f_7f_87_2b_f2_7f_97_ce_bc_7f_a7_36_b3_7f_b5_63_b2_7f_c2_55_95_7f_ce_0c_3d_7f_d8_87_8d_7f_e1_c7_6a_7f_e9_cb_bf_7f_f0_94_77_7f_f6_21_81_7f_fa_72_d0_7f_fd_88_59_7f_ff_62_15_7f_ff_ff_ff";

  /**
   * @notice Return the sine of a value, specified in radians scaled by 1e18
   * @dev This algorithm for converting sine only uses integer values, and it works by dividing the
   * circle into 30 bit angles, i.e. there are 1,073,741,824 (2^30) angle units, instead of the
   * standard 360 degrees (2pi radians). From there, we get an output in range -2,147,483,647 to
   * 2,147,483,647, (which is the max value of an int32) which is then converted back to the standard
   * range of -1 to 1, again scaled by 1e18
   * @param _angle Angle to convert
   * @return Result scaled by 1e18
   */
  function sin(uint256 _angle) internal pure returns (int256) {
    unchecked {
      // Convert angle from from arbitrary radian value (range of 0 to 2pi) to the algorithm's range
      // of 0 to 1,073,741,824
      _angle = (ANGLES_IN_CYCLE * (_angle % TWO_PI)) / TWO_PI;

      // Apply a mask on an integer to extract a certain number of bits, where angle is the integer
      // whose bits we want to get, the width is the width of the bits (in bits) we want to extract,
      // and the offset is the offset of the bits (in bits) we want to extract. The result is an
      // integer containing _width bits of _value starting at the offset bit
      uint256 interp = (_angle >> INTERP_OFFSET) & ((1 << INTERP_WIDTH) - 1);
      uint256 index = (_angle >> INDEX_OFFSET) & ((1 << INDEX_WIDTH) - 1);

      // The lookup table only contains data for one quadrant (since sin is symmetric around both
      // axes), so here we figure out which quadrant we're in, then we lookup the values in the
      // table then modify values accordingly
      bool is_odd_quadrant = (_angle & QUADRANT_LOW_MASK) == 0;
      bool is_negative_quadrant = (_angle & QUADRANT_HIGH_MASK) != 0;

      if (!is_odd_quadrant) {
        index = SINE_TABLE_SIZE - 1 - index;
      }

      bytes memory table = sin_table;
      // We are looking for two consecutive indices in our lookup table
      // Since EVM is left aligned, to read n bytes of data from idx i, we must read from `i * data_len` + `n`
      // therefore, to read two entries of size entry_bytes `index * entry_bytes` + `entry_bytes * 2`
      uint256 offset1_2 = (index + 2) * entry_bytes;

      // This following snippet will function for any entry_bytes <= 15
      uint256 x1_2;
      assembly {
        // mload will grab one word worth of bytes (32), as that is the minimum size in EVM
        x1_2 := mload(add(table, offset1_2))
      }

      // We now read the last two numbers of size entry_bytes from x1_2
      // in example: entry_bytes = 4; x1_2 = 0x00...12345678abcdefgh
      // therefore: entry_mask = 0xFFFFFFFF

      // 0x00...12345678abcdefgh >> 8*4 = 0x00...12345678
      // 0x00...12345678 & 0xFFFFFFFF = 0x12345678
      uint256 x1 = (x1_2 >> (8 * entry_bytes)) & entry_mask;
      // 0x00...12345678abcdefgh & 0xFFFFFFFF = 0xabcdefgh
      uint256 x2 = x1_2 & entry_mask;

      // Approximate angle by interpolating in the table, accounting for the quadrant
      uint256 approximation = ((x2 - x1) * interp) >> INTERP_WIDTH;
      int256 sine = is_odd_quadrant ? int256(x1) + int256(approximation) : int256(x2) - int256(approximation);
      if (is_negative_quadrant) {
        sine *= -1;
      }

      // Bring result from the range of -2,147,483,647 through 2,147,483,647 to -1e18 through 1e18.
      // This can never overflow because sine is bounded by the above values
      return (sine * 1e18) / 2_147_483_647;
    }
  }

  /**
   * @notice Return the cosine of a value, specified in radians scaled by 1e18
   * @dev This is identical to the sin() method, and just computes the value by delegating to the
   * sin() method using the identity cos(x) = sin(x + pi/2)
   * @dev Overflow when `angle + PI_OVER_TWO > type(uint256).max` is ok, results are still accurate
   * @param _angle Angle to convert
   * @return Result scaled by 1e18
   */
  function cos(uint256 _angle) internal pure returns (int256) {
    unchecked {
      return sin(_angle + PI_OVER_TWO);
    }
  }
}

File 7 of 11 : Utilities.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

// Core utils used extensively to format CSS and numbers.
library utils {
  struct HSL {
    uint256 h;
    uint256 s;
    uint256 l;
  }

  function random(string memory input) internal pure returns (uint256) {
    return uint256(keccak256(abi.encodePacked(input)));
  }

  function randomRange(
    uint256 tokenId,
    string memory keyPrefix,
    uint256 lower,
    uint256 upper
  ) internal pure returns (uint256) {
    uint256 rand = random(string(abi.encodePacked(keyPrefix, uint2str(tokenId))));
    return (rand % (upper - lower + 1)) + lower;
  }

  function min(int256 a, int256 b) internal pure returns (int256) {
    return a < b ? a : b;
  }

  function min(uint256 a, uint256 b) internal pure returns (uint256) {
    return a < b ? a : b;
  }

  function max(int256 a, int256 b) internal pure returns (int256) {
    return a > b ? a : b;
  }

  function generateColors(uint256 _hue, uint256 _numColors) public pure returns (HSL[] memory) {
    HSL[] memory colors = new HSL[](_numColors);

    for (uint256 i = 0; i < _numColors; i++) {
      colors[i] = HSL(_hue, 100 - ((i * 50) / _numColors), 70 - ((i * 30) / _numColors));
    }

    return colors;
  }

  function getHueName(uint256 _hue) public pure returns (string memory) {
    _hue = _hue % 360;

    string[12] memory colors = [
      "Red",
      "Orange",
      "Yellow",
      "Chartreuse",
      "Green",
      "Spring green",
      "Turquoise",
      "Teal",
      "Blue",
      "Violet",
      "Magenta",
      "Rose"
    ];

    uint256 colorIndex = (_hue / 30) % colors.length;
    return colors[colorIndex];
  }

  function getHslString(HSL memory _hsl) public pure returns (string memory) {
    return string(abi.encodePacked("hsl(", uint2str(_hsl.h), ",", uint2str(_hsl.s), "%,", uint2str(_hsl.l), "%)"));
  }

  function uint2floatstr(uint256 _i_scaled, uint256 _decimals) internal pure returns (string memory) {
    return string.concat(uint2str(_i_scaled / (10**_decimals)), ".", uint2str(_i_scaled % (10**_decimals)));
  }

  function int2str(int256 _i) internal pure returns (string memory _uintAsString) {
    if (_i < 0) {
      return string.concat("-", uint2str(uint256(-_i)));
    } else {
      return uint2str(uint256(_i));
    }
  }

  // converts an unsigned integer to a string
  function uint2str(uint256 _i) internal pure returns (string memory _uintAsString) {
    if (_i == 0) {
      return "0";
    }
    uint256 j = _i;
    uint256 len;
    while (j != 0) {
      len++;
      j /= 10;
    }
    bytes memory bstr = new bytes(len);
    uint256 k = len;
    while (_i != 0) {
      k = k - 1;
      uint8 temp = (48 + uint8(_i - (_i / 10) * 10));
      bytes1 b1 = bytes1(temp);
      bstr[k] = b1;
      _i /= 10;
    }
    return string(bstr);
  }
}

File 8 of 11 : ERC721A.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

import './IERC721A.sol';

/**
 * @dev Interface of ERC721 token receiver.
 */
interface ERC721A__IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

/**
 * @title ERC721A
 *
 * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721)
 * Non-Fungible Token Standard, including the Metadata extension.
 * Optimized for lower gas during batch mints.
 *
 * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...)
 * starting from `_startTokenId()`.
 *
 * Assumptions:
 *
 * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
 * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256).
 */
contract ERC721A is IERC721A {
    // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364).
    struct TokenApprovalRef {
        address value;
    }

    // =============================================================
    //                           CONSTANTS
    // =============================================================

    // Mask of an entry in packed address data.
    uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1;

    // The bit position of `numberMinted` in packed address data.
    uint256 private constant _BITPOS_NUMBER_MINTED = 64;

    // The bit position of `numberBurned` in packed address data.
    uint256 private constant _BITPOS_NUMBER_BURNED = 128;

    // The bit position of `aux` in packed address data.
    uint256 private constant _BITPOS_AUX = 192;

    // Mask of all 256 bits in packed address data except the 64 bits for `aux`.
    uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1;

    // The bit position of `startTimestamp` in packed ownership.
    uint256 private constant _BITPOS_START_TIMESTAMP = 160;

    // The bit mask of the `burned` bit in packed ownership.
    uint256 private constant _BITMASK_BURNED = 1 << 224;

    // The bit position of the `nextInitialized` bit in packed ownership.
    uint256 private constant _BITPOS_NEXT_INITIALIZED = 225;

    // The bit mask of the `nextInitialized` bit in packed ownership.
    uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225;

    // The bit position of `extraData` in packed ownership.
    uint256 private constant _BITPOS_EXTRA_DATA = 232;

    // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`.
    uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1;

    // The mask of the lower 160 bits for addresses.
    uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;

    // The maximum `quantity` that can be minted with {_mintERC2309}.
    // This limit is to prevent overflows on the address data entries.
    // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309}
    // is required to cause an overflow, which is unrealistic.
    uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000;

    // The `Transfer` event signature is given by:
    // `keccak256(bytes("Transfer(address,address,uint256)"))`.
    bytes32 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    // =============================================================
    //                            STORAGE
    // =============================================================

    // The next token ID to be minted.
    uint256 private _currentIndex;

    // The number of tokens burned.
    uint256 private _burnCounter;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned.
    // See {_packedOwnershipOf} implementation for details.
    //
    // Bits Layout:
    // - [0..159]   `addr`
    // - [160..223] `startTimestamp`
    // - [224]      `burned`
    // - [225]      `nextInitialized`
    // - [232..255] `extraData`
    mapping(uint256 => uint256) private _packedOwnerships;

    // Mapping owner address to address data.
    //
    // Bits Layout:
    // - [0..63]    `balance`
    // - [64..127]  `numberMinted`
    // - [128..191] `numberBurned`
    // - [192..255] `aux`
    mapping(address => uint256) private _packedAddressData;

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

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

    // =============================================================
    //                          CONSTRUCTOR
    // =============================================================

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
        _currentIndex = _startTokenId();
    }

    // =============================================================
    //                   TOKEN COUNTING OPERATIONS
    // =============================================================

    /**
     * @dev Returns the starting token ID.
     * To change the starting token ID, please override this function.
     */
    function _startTokenId() internal view virtual returns (uint256) {
        return 0;
    }

    /**
     * @dev Returns the next token ID to be minted.
     */
    function _nextTokenId() internal view virtual returns (uint256) {
        return _currentIndex;
    }

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        // Counter underflow is impossible as _burnCounter cannot be incremented
        // more than `_currentIndex - _startTokenId()` times.
        unchecked {
            return _currentIndex - _burnCounter - _startTokenId();
        }
    }

    /**
     * @dev Returns the total amount of tokens minted in the contract.
     */
    function _totalMinted() internal view virtual returns (uint256) {
        // Counter underflow is impossible as `_currentIndex` does not decrement,
        // and it is initialized to `_startTokenId()`.
        unchecked {
            return _currentIndex - _startTokenId();
        }
    }

    /**
     * @dev Returns the total number of tokens burned.
     */
    function _totalBurned() internal view virtual returns (uint256) {
        return _burnCounter;
    }

    // =============================================================
    //                    ADDRESS DATA OPERATIONS
    // =============================================================

    /**
     * @dev Returns the number of tokens in `owner`'s account.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        if (owner == address(0)) revert BalanceQueryForZeroAddress();
        return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens minted by `owner`.
     */
    function _numberMinted(address owner) internal view returns (uint256) {
        return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens burned by or on behalf of `owner`.
     */
    function _numberBurned(address owner) internal view returns (uint256) {
        return (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
     */
    function _getAux(address owner) internal view returns (uint64) {
        return uint64(_packedAddressData[owner] >> _BITPOS_AUX);
    }

    /**
     * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
     * If there are multiple variables, please pack them into a uint64.
     */
    function _setAux(address owner, uint64 aux) internal virtual {
        uint256 packed = _packedAddressData[owner];
        uint256 auxCasted;
        // Cast `aux` with assembly to avoid redundant masking.
        assembly {
            auxCasted := aux
        }
        packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX);
        _packedAddressData[owner] = packed;
    }

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        // The interface IDs are constants representing the first 4 bytes
        // of the XOR of all function selectors in the interface.
        // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165)
        // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`)
        return
            interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165.
            interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721.
            interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata.
    }

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

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

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();

        string memory baseURI = _baseURI();
        return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : '';
    }

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

    // =============================================================
    //                     OWNERSHIPS OPERATIONS
    // =============================================================

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        return address(uint160(_packedOwnershipOf(tokenId)));
    }

    /**
     * @dev Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around over time.
     */
    function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) {
        return _unpackedOwnership(_packedOwnershipOf(tokenId));
    }

    /**
     * @dev Returns the unpacked `TokenOwnership` struct at `index`.
     */
    function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) {
        return _unpackedOwnership(_packedOwnerships[index]);
    }

    /**
     * @dev Initializes the ownership slot minted at `index` for efficiency purposes.
     */
    function _initializeOwnershipAt(uint256 index) internal virtual {
        if (_packedOwnerships[index] == 0) {
            _packedOwnerships[index] = _packedOwnershipOf(index);
        }
    }

    /**
     * Returns the packed ownership data of `tokenId`.
     */
    function _packedOwnershipOf(uint256 tokenId) private view returns (uint256) {
        uint256 curr = tokenId;

        unchecked {
            if (_startTokenId() <= curr)
                if (curr < _currentIndex) {
                    uint256 packed = _packedOwnerships[curr];
                    // If not burned.
                    if (packed & _BITMASK_BURNED == 0) {
                        // Invariant:
                        // There will always be an initialized ownership slot
                        // (i.e. `ownership.addr != address(0) && ownership.burned == false`)
                        // before an unintialized ownership slot
                        // (i.e. `ownership.addr == address(0) && ownership.burned == false`)
                        // Hence, `curr` will not underflow.
                        //
                        // We can directly compare the packed value.
                        // If the address is zero, packed will be zero.
                        while (packed == 0) {
                            packed = _packedOwnerships[--curr];
                        }
                        return packed;
                    }
                }
        }
        revert OwnerQueryForNonexistentToken();
    }

    /**
     * @dev Returns the unpacked `TokenOwnership` struct from `packed`.
     */
    function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) {
        ownership.addr = address(uint160(packed));
        ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP);
        ownership.burned = packed & _BITMASK_BURNED != 0;
        ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA);
    }

    /**
     * @dev Packs ownership data into a single uint256.
     */
    function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) {
        assembly {
            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
            owner := and(owner, _BITMASK_ADDRESS)
            // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`.
            result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags))
        }
    }

    /**
     * @dev Returns the `nextInitialized` flag set if `quantity` equals 1.
     */
    function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) {
        // For branchless setting of the `nextInitialized` flag.
        assembly {
            // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`.
            result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1))
        }
    }

    // =============================================================
    //                      APPROVAL OPERATIONS
    // =============================================================

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

        if (_msgSenderERC721A() != owner)
            if (!isApprovedForAll(owner, _msgSenderERC721A())) {
                revert ApprovalCallerNotOwnerNorApproved();
            }

        _tokenApprovals[tokenId].value = to;
        emit Approval(owner, to, tokenId);
    }

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();

        return _tokenApprovals[tokenId].value;
    }

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

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

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted. See {_mint}.
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return
            _startTokenId() <= tokenId &&
            tokenId < _currentIndex && // If within bounds,
            _packedOwnerships[tokenId] & _BITMASK_BURNED == 0; // and not burned.
    }

    /**
     * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`.
     */
    function _isSenderApprovedOrOwner(
        address approvedAddress,
        address owner,
        address msgSender
    ) private pure returns (bool result) {
        assembly {
            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
            owner := and(owner, _BITMASK_ADDRESS)
            // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean.
            msgSender := and(msgSender, _BITMASK_ADDRESS)
            // `msgSender == owner || msgSender == approvedAddress`.
            result := or(eq(msgSender, owner), eq(msgSender, approvedAddress))
        }
    }

    /**
     * @dev Returns the storage slot and value for the approved address of `tokenId`.
     */
    function _getApprovedSlotAndAddress(uint256 tokenId)
        private
        view
        returns (uint256 approvedAddressSlot, address approvedAddress)
    {
        TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId];
        // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`.
        assembly {
            approvedAddressSlot := tokenApproval.slot
            approvedAddress := sload(approvedAddressSlot)
        }
    }

    // =============================================================
    //                      TRANSFER OPERATIONS
    // =============================================================

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable virtual override {
        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);

        if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner();

        (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);

        // The nested ifs save around 20+ gas over a compound boolean condition.
        if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
            if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved();

        if (to == address(0)) revert TransferToZeroAddress();

        _beforeTokenTransfers(from, to, tokenId, 1);

        // Clear approvals from the previous owner.
        assembly {
            if approvedAddress {
                // This is equivalent to `delete _tokenApprovals[tokenId]`.
                sstore(approvedAddressSlot, 0)
            }
        }

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
        unchecked {
            // We can directly increment and decrement the balances.
            --_packedAddressData[from]; // Updates: `balance -= 1`.
            ++_packedAddressData[to]; // Updates: `balance += 1`.

            // Updates:
            // - `address` to the next owner.
            // - `startTimestamp` to the timestamp of transfering.
            // - `burned` to `false`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] = _packOwnershipData(
                to,
                _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked)
            );

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

        emit Transfer(from, to, tokenId);
        _afterTokenTransfers(from, to, tokenId, 1);
    }

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable virtual override {
        safeTransferFrom(from, to, tokenId, '');
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement
     * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public payable virtual override {
        transferFrom(from, to, tokenId);
        if (to.code.length != 0)
            if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
                revert TransferToNonERC721ReceiverImplementer();
            }
    }

    /**
     * @dev Hook that is called before a set of serially-ordered token IDs
     * are about to be transferred. This includes minting.
     * And also called before burning one token.
     *
     * `startTokenId` - the first token ID to be transferred.
     * `quantity` - the amount to be transferred.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Hook that is called after a set of serially-ordered token IDs
     * have been transferred. This includes minting.
     * And also called after one token has been burned.
     *
     * `startTokenId` - the first token ID to be transferred.
     * `quantity` - the amount to be transferred.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
     * transferred to `to`.
     * - When `from` is zero, `tokenId` has been minted for `to`.
     * - When `to` is zero, `tokenId` has been burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract.
     *
     * `from` - Previous owner of the given token ID.
     * `to` - Target address that will receive the token.
     * `tokenId` - Token ID to be transferred.
     * `_data` - Optional data to send along with the call.
     *
     * Returns whether the call correctly returned the expected magic value.
     */
    function _checkContractOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns (
            bytes4 retval
        ) {
            return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector;
        } catch (bytes memory reason) {
            if (reason.length == 0) {
                revert TransferToNonERC721ReceiverImplementer();
            } else {
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
    }

    // =============================================================
    //                        MINT OPERATIONS
    // =============================================================

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _mint(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (quantity == 0) revert MintZeroQuantity();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are incredibly unrealistic.
        // `balance` and `numberMinted` have a maximum limit of 2**64.
        // `tokenId` has a maximum limit of 2**256.
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
            );

            uint256 toMasked;
            uint256 end = startTokenId + quantity;

            // Use assembly to loop and emit the `Transfer` event for gas savings.
            // The duplicated `log4` removes an extra check and reduces stack juggling.
            // The assembly, together with the surrounding Solidity code, have been
            // delicately arranged to nudge the compiler into producing optimized opcodes.
            assembly {
                // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
                toMasked := and(to, _BITMASK_ADDRESS)
                // Emit the `Transfer` event.
                log4(
                    0, // Start of data (0, since no data).
                    0, // End of data (0, since no data).
                    _TRANSFER_EVENT_SIGNATURE, // Signature.
                    0, // `address(0)`.
                    toMasked, // `to`.
                    startTokenId // `tokenId`.
                )

                // The `iszero(eq(,))` check ensures that large values of `quantity`
                // that overflows uint256 will make the loop run out of gas.
                // The compiler will optimize the `iszero` away for performance.
                for {
                    let tokenId := add(startTokenId, 1)
                } iszero(eq(tokenId, end)) {
                    tokenId := add(tokenId, 1)
                } {
                    // Emit the `Transfer` event. Similar to above.
                    log4(0, 0, _TRANSFER_EVENT_SIGNATURE, 0, toMasked, tokenId)
                }
            }
            if (toMasked == 0) revert MintToZeroAddress();

            _currentIndex = end;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * This function is intended for efficient minting only during contract creation.
     *
     * It emits only one {ConsecutiveTransfer} as defined in
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309),
     * instead of a sequence of {Transfer} event(s).
     *
     * Calling this function outside of contract creation WILL make your contract
     * non-compliant with the ERC721 standard.
     * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309
     * {ConsecutiveTransfer} event is only permissible during contract creation.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {ConsecutiveTransfer} event.
     */
    function _mintERC2309(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (to == address(0)) revert MintToZeroAddress();
        if (quantity == 0) revert MintZeroQuantity();
        if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) revert MintERC2309QuantityExceedsLimit();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are unrealistic due to the above check for `quantity` to be below the limit.
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
            );

            emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to);

            _currentIndex = startTokenId + quantity;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Safely mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement
     * {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
     * - `quantity` must be greater than 0.
     *
     * See {_mint}.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal virtual {
        _mint(to, quantity);

        unchecked {
            if (to.code.length != 0) {
                uint256 end = _currentIndex;
                uint256 index = end - quantity;
                do {
                    if (!_checkContractOnERC721Received(address(0), to, index++, _data)) {
                        revert TransferToNonERC721ReceiverImplementer();
                    }
                } while (index < end);
                // Reentrancy protection.
                if (_currentIndex != end) revert();
            }
        }
    }

    /**
     * @dev Equivalent to `_safeMint(to, quantity, '')`.
     */
    function _safeMint(address to, uint256 quantity) internal virtual {
        _safeMint(to, quantity, '');
    }

    // =============================================================
    //                        BURN OPERATIONS
    // =============================================================

    /**
     * @dev Equivalent to `_burn(tokenId, false)`.
     */
    function _burn(uint256 tokenId) internal virtual {
        _burn(tokenId, false);
    }

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

        address from = address(uint160(prevOwnershipPacked));

        (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);

        if (approvalCheck) {
            // The nested ifs save around 20+ gas over a compound boolean condition.
            if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
                if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved();
        }

        _beforeTokenTransfers(from, address(0), tokenId, 1);

        // Clear approvals from the previous owner.
        assembly {
            if approvedAddress {
                // This is equivalent to `delete _tokenApprovals[tokenId]`.
                sstore(approvedAddressSlot, 0)
            }
        }

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
        unchecked {
            // Updates:
            // - `balance -= 1`.
            // - `numberBurned += 1`.
            //
            // We can directly decrement the balance, and increment the number burned.
            // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`.
            _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1;

            // Updates:
            // - `address` to the last owner.
            // - `startTimestamp` to the timestamp of burning.
            // - `burned` to `true`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] = _packOwnershipData(
                from,
                (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked)
            );

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

        emit Transfer(from, address(0), tokenId);
        _afterTokenTransfers(from, address(0), tokenId, 1);

        // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times.
        unchecked {
            _burnCounter++;
        }
    }

    // =============================================================
    //                     EXTRA DATA OPERATIONS
    // =============================================================

    /**
     * @dev Directly sets the extra data for the ownership data `index`.
     */
    function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual {
        uint256 packed = _packedOwnerships[index];
        if (packed == 0) revert OwnershipNotInitializedForExtraData();
        uint256 extraDataCasted;
        // Cast `extraData` with assembly to avoid redundant masking.
        assembly {
            extraDataCasted := extraData
        }
        packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA);
        _packedOwnerships[index] = packed;
    }

    /**
     * @dev Called during each token transfer to set the 24bit `extraData` field.
     * Intended to be overridden by the cosumer contract.
     *
     * `previousExtraData` - the value of `extraData` before transfer.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _extraData(
        address from,
        address to,
        uint24 previousExtraData
    ) internal view virtual returns (uint24) {}

    /**
     * @dev Returns the next extra data for the packed ownership data.
     * The returned result is shifted into position.
     */
    function _nextExtraData(
        address from,
        address to,
        uint256 prevOwnershipPacked
    ) private view returns (uint256) {
        uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA);
        return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA;
    }

    // =============================================================
    //                       OTHER OPERATIONS
    // =============================================================

    /**
     * @dev Returns the message sender (defaults to `msg.sender`).
     *
     * If you are writing GSN compatible contracts, you need to override this function.
     */
    function _msgSenderERC721A() internal view virtual returns (address) {
        return msg.sender;
    }

    /**
     * @dev Converts a uint256 to its ASCII string decimal representation.
     */
    function _toString(uint256 value) internal pure virtual returns (string memory str) {
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but
            // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
            // We will need 1 word for the trailing zeros padding, 1 word for the length,
            // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.
            let m := add(mload(0x40), 0xa0)
            // Update the free memory pointer to allocate.
            mstore(0x40, m)
            // Assign the `str` to the end.
            str := sub(m, 0x20)
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end of the memory to calculate the length later.
            let end := str

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            // prettier-ignore
            for { let temp := value } 1 {} {
                str := sub(str, 1)
                // Write the character to the pointer.
                // The ASCII index of the '0' character is 48.
                mstore8(str, add(48, mod(temp, 10)))
                // Keep dividing `temp` until zero.
                temp := div(temp, 10)
                // prettier-ignore
                if iszero(temp) { break }
            }

            let length := sub(end, str)
            // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 0x20)
            // Store the length.
            mstore(str, length)
        }
    }
}

File 9 of 11 : IERC721A.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

/**
 * @dev Interface of ERC721A.
 */
interface IERC721A {
    /**
     * The caller must own the token or be an approved operator.
     */
    error ApprovalCallerNotOwnerNorApproved();

    /**
     * The token does not exist.
     */
    error ApprovalQueryForNonexistentToken();

    /**
     * Cannot query the balance for the zero address.
     */
    error BalanceQueryForZeroAddress();

    /**
     * Cannot mint to the zero address.
     */
    error MintToZeroAddress();

    /**
     * The quantity of tokens minted must be more than zero.
     */
    error MintZeroQuantity();

    /**
     * The token does not exist.
     */
    error OwnerQueryForNonexistentToken();

    /**
     * The caller must own the token or be an approved operator.
     */
    error TransferCallerNotOwnerNorApproved();

    /**
     * The token must be owned by `from`.
     */
    error TransferFromIncorrectOwner();

    /**
     * Cannot safely transfer to a contract that does not implement the
     * ERC721Receiver interface.
     */
    error TransferToNonERC721ReceiverImplementer();

    /**
     * Cannot transfer to the zero address.
     */
    error TransferToZeroAddress();

    /**
     * The token does not exist.
     */
    error URIQueryForNonexistentToken();

    /**
     * The `quantity` minted with ERC2309 exceeds the safety limit.
     */
    error MintERC2309QuantityExceedsLimit();

    /**
     * The `extraData` cannot be set on an unintialized ownership slot.
     */
    error OwnershipNotInitializedForExtraData();

    // =============================================================
    //                            STRUCTS
    // =============================================================

    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Stores the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
        // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
        uint24 extraData;
    }

    // =============================================================
    //                         TOKEN COUNTERS
    // =============================================================

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() external view returns (uint256);

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);

    // =============================================================
    //                            IERC721
    // =============================================================

    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

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

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

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

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

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

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

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

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

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

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

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

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

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

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

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

    // =============================================================
    //                           IERC2309
    // =============================================================

    /**
     * @dev Emitted when tokens in `fromTokenId` to `toTokenId`
     * (inclusive) is transferred from `from` to `to`, as defined in the
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
     *
     * See {_mintERC2309} for more details.
     */
    event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}

File 10 of 11 : console.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 <0.9.0;

library console {
	address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);

	function _sendLogPayload(bytes memory payload) private view {
		uint256 payloadLength = payload.length;
		address consoleAddress = CONSOLE_ADDRESS;
		assembly {
			let payloadStart := add(payload, 32)
			let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
		}
	}

	function log() internal view {
		_sendLogPayload(abi.encodeWithSignature("log()"));
	}

	function logInt(int256 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
	}

	function logUint(uint256 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
	}

	function logString(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function logBool(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function logAddress(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function logBytes(bytes memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
	}

	function logBytes1(bytes1 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
	}

	function logBytes2(bytes2 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
	}

	function logBytes3(bytes3 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
	}

	function logBytes4(bytes4 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
	}

	function logBytes5(bytes5 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
	}

	function logBytes6(bytes6 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
	}

	function logBytes7(bytes7 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
	}

	function logBytes8(bytes8 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
	}

	function logBytes9(bytes9 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
	}

	function logBytes10(bytes10 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
	}

	function logBytes11(bytes11 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
	}

	function logBytes12(bytes12 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
	}

	function logBytes13(bytes13 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
	}

	function logBytes14(bytes14 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
	}

	function logBytes15(bytes15 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
	}

	function logBytes16(bytes16 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
	}

	function logBytes17(bytes17 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
	}

	function logBytes18(bytes18 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
	}

	function logBytes19(bytes19 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
	}

	function logBytes20(bytes20 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
	}

	function logBytes21(bytes21 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
	}

	function logBytes22(bytes22 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
	}

	function logBytes23(bytes23 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
	}

	function logBytes24(bytes24 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
	}

	function logBytes25(bytes25 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
	}

	function logBytes26(bytes26 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
	}

	function logBytes27(bytes27 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
	}

	function logBytes28(bytes28 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
	}

	function logBytes29(bytes29 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
	}

	function logBytes30(bytes30 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
	}

	function logBytes31(bytes31 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
	}

	function logBytes32(bytes32 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
	}

	function log(uint256 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
	}

	function log(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function log(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function log(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function log(uint256 p0, uint256 p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
	}

	function log(uint256 p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
	}

	function log(uint256 p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
	}

	function log(uint256 p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
	}

	function log(string memory p0, uint256 p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
	}

	function log(string memory p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
	}

	function log(string memory p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
	}

	function log(string memory p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
	}

	function log(bool p0, uint256 p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
	}

	function log(bool p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
	}

	function log(bool p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
	}

	function log(bool p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
	}

	function log(address p0, uint256 p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
	}

	function log(address p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
	}

	function log(address p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
	}

	function log(address p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
	}

	function log(uint256 p0, uint256 p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
	}

	function log(uint256 p0, uint256 p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
	}

	function log(uint256 p0, uint256 p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
	}

	function log(uint256 p0, uint256 p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
	}

	function log(uint256 p0, string memory p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
	}

	function log(uint256 p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
	}

	function log(uint256 p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
	}

	function log(uint256 p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
	}

	function log(uint256 p0, bool p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
	}

	function log(uint256 p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
	}

	function log(uint256 p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
	}

	function log(uint256 p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
	}

	function log(uint256 p0, address p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
	}

	function log(uint256 p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
	}

	function log(uint256 p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
	}

	function log(uint256 p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
	}

	function log(string memory p0, uint256 p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
	}

	function log(string memory p0, uint256 p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
	}

	function log(string memory p0, uint256 p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
	}

	function log(string memory p0, uint256 p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
	}

	function log(string memory p0, address p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
	}

	function log(string memory p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
	}

	function log(string memory p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
	}

	function log(string memory p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
	}

	function log(bool p0, uint256 p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
	}

	function log(bool p0, uint256 p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
	}

	function log(bool p0, uint256 p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
	}

	function log(bool p0, uint256 p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
	}

	function log(bool p0, bool p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
	}

	function log(bool p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
	}

	function log(bool p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
	}

	function log(bool p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
	}

	function log(bool p0, address p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
	}

	function log(bool p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
	}

	function log(bool p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
	}

	function log(bool p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
	}

	function log(address p0, uint256 p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
	}

	function log(address p0, uint256 p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
	}

	function log(address p0, uint256 p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
	}

	function log(address p0, uint256 p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
	}

	function log(address p0, string memory p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
	}

	function log(address p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
	}

	function log(address p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
	}

	function log(address p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
	}

	function log(address p0, bool p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
	}

	function log(address p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
	}

	function log(address p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
	}

	function log(address p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
	}

	function log(address p0, address p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
	}

	function log(address p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
	}

	function log(address p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
	}

	function log(address p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
	}

	function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, uint256 p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
	}

	function log(uint256 p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint256 p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint256 p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint256 p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint256 p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint256 p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint256 p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
	}

}

File 11 of 11 : Base64.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

/// [MIT License]
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Brecht Devos <[email protected]>
library Base64 {
  bytes internal constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

  /// @notice Encodes some bytes to the base64 representation
  function encode(bytes memory data) internal pure returns (string memory) {
    uint256 len = data.length;
    if (len == 0) return "";

    // multiply by 4/3 rounded up
    uint256 encodedLen = 4 * ((len + 2) / 3);

    // Add some extra buffer at the end
    bytes memory result = new bytes(encodedLen + 32);

    bytes memory table = TABLE;

    assembly {
      let tablePtr := add(table, 1)
      let resultPtr := add(result, 32)

      for {
        let i := 0
      } lt(i, len) {

      } {
        i := add(i, 3)
        let input := and(mload(add(data, i)), 0xffffff)

        let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
        out := shl(8, out)
        out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))
        out := shl(8, out)
        out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))
        out := shl(8, out)
        out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))
        out := shl(224, out)

        mstore(resultPtr, out)

        resultPtr := add(resultPtr, 4)
      }

      switch mod(len, 3)
      case 1 {
        mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
      }
      case 2 {
        mstore(sub(resultPtr, 1), shl(248, 0x3d))
      }

      mstore(result, encodedLen)
    }

    return string(result);
  }
}

Settings
{
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {
    "contracts/Utilities.sol": {
      "utils": "0x01e833cf8c115bb859a8e16a72d5ff298f834413"
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_maxSupply","type":"uint256"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"_allowListMintStartBlock","type":"uint256"},{"internalType":"uint256","name":"_publicMintOffsetBlocks","type":"uint256"},{"internalType":"address","name":"_renderer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","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":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","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":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address[]","name":"_recipients","type":"address[]"},{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"allowListMintStartBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"allowListed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasAllowlistSaleStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasPublicSaleStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintPerWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"mintAllowList","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"mintPublic","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"}],"name":"mintQuotaRemaining","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","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":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicMintOffsetBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renderer","outputs":[{"internalType":"contract Renderer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","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":"safeTransferFrom","outputs":[],"stateMutability":"payable","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":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_allowListMintStartBlock","type":"uint256"}],"name":"setAllowListMintStartBlock","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":"_price","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_publicMintOffsetBlocks","type":"uint256"}],"name":"setPublicMintOffsetBlocks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","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":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b50604051620051393803806200513983398181016040528101906200003791906200044c565b878781600290816200004a919062000794565b5080600390816200005c919062000794565b506200006d6200010760201b60201c565b600081905550505062000095620000896200011060201b60201c565b6200011860201b60201c565b8560098190555084600a8190555083600c8190555082600d8190555081600e8190555080600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050505050506200087b565b60006001905090565b600033905090565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200024782620001fc565b810181811067ffffffffffffffff821117156200026957620002686200020d565b5b80604052505050565b60006200027e620001de565b90506200028c82826200023c565b919050565b600067ffffffffffffffff821115620002af57620002ae6200020d565b5b620002ba82620001fc565b9050602081019050919050565b60005b83811015620002e7578082015181840152602081019050620002ca565b60008484015250505050565b60006200030a620003048462000291565b62000272565b905082815260208101848484011115620003295762000328620001f7565b5b62000336848285620002c7565b509392505050565b600082601f830112620003565762000355620001f2565b5b815162000368848260208601620002f3565b91505092915050565b6000819050919050565b620003868162000371565b81146200039257600080fd5b50565b600081519050620003a6816200037b565b92915050565b6000819050919050565b620003c181620003ac565b8114620003cd57600080fd5b50565b600081519050620003e181620003b6565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200041482620003e7565b9050919050565b620004268162000407565b81146200043257600080fd5b50565b60008151905062000446816200041b565b92915050565b600080600080600080600080610100898b03121562000470576200046f620001e8565b5b600089015167ffffffffffffffff811115620004915762000490620001ed565b5b6200049f8b828c016200033e565b985050602089015167ffffffffffffffff811115620004c357620004c2620001ed565b5b620004d18b828c016200033e565b9750506040620004e48b828c0162000395565b9650506060620004f78b828c0162000395565b95505060806200050a8b828c01620003d0565b94505060a06200051d8b828c0162000395565b93505060c0620005308b828c0162000395565b92505060e0620005438b828c0162000435565b9150509295985092959890939650565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620005a657607f821691505b602082108103620005bc57620005bb6200055e565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620006267fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620005e7565b620006328683620005e7565b95508019841693508086168417925050509392505050565b6000819050919050565b6000620006756200066f620006698462000371565b6200064a565b62000371565b9050919050565b6000819050919050565b620006918362000654565b620006a9620006a0826200067c565b848454620005f4565b825550505050565b600090565b620006c0620006b1565b620006cd81848462000686565b505050565b5b81811015620006f557620006e9600082620006b6565b600181019050620006d3565b5050565b601f82111562000744576200070e81620005c2565b6200071984620005d7565b8101602085101562000729578190505b620007416200073885620005d7565b830182620006d2565b50505b505050565b600082821c905092915050565b6000620007696000198460080262000749565b1980831691505092915050565b600062000784838362000756565b9150826002028217905092915050565b6200079f8262000553565b67ffffffffffffffff811115620007bb57620007ba6200020d565b5b620007c782546200058d565b620007d4828285620006f9565b600060209050601f8311600181146200080c5760008415620007f7578287015190505b62000803858262000776565b86555062000873565b601f1984166200081c86620005c2565b60005b8281101562000846578489015182556001820191506020850194506020810190506200081f565b8683101562000866578489015162000862601f89168262000756565b8355505b6001600288020188555050505b505050505050565b6148ae806200088b6000396000f3fe6080604052600436106102045760003560e01c80638da5cb5b11610118578063c87b56dd116100a0578063efd0cbf91161006f578063efd0cbf91461072a578063f2fde38b14610746578063f764561d1461076f578063fa05a65714610798578063fdd4b0f0146107b457610204565b8063c87b56dd1461065a578063d0e59d5a14610697578063d5abeb01146106c2578063e985e9c5146106ed57610204565b8063a22cb465116100e7578063a22cb465146105a3578063afc1cad3146105cc578063b228d925146105f7578063b88d4fde14610622578063c204642c1461063e57610204565b80638da5cb5b146104f957806391b7f5ed1461052457806395d89b411461054d578063a035b1fe1461057857610204565b806323b872dd1161019b57806342842e0e1161016a57806342842e0e146104215780636352211e1461043d57806370a082311461047a578063715018a6146104b75780638ada6b0f146104ce57610204565b806323b872dd14610386578063247155ff146103a25780632eb4a7ab146103df5780633ccfd60b1461040a57610204565b80630bf02d87116101d75780630bf02d87146102ca5780630e2a1448146102f5578063170a78cc1461033257806318160ddd1461035b57610204565b806301ffc9a71461020957806306fdde0314610246578063081812fc14610271578063095ea7b3146102ae575b600080fd5b34801561021557600080fd5b50610230600480360381019061022b91906127a8565b6107df565b60405161023d91906127f0565b60405180910390f35b34801561025257600080fd5b5061025b610871565b604051610268919061289b565b60405180910390f35b34801561027d57600080fd5b50610298600480360381019061029391906128f3565b610903565b6040516102a59190612961565b60405180910390f35b6102c860048036038101906102c391906129a8565b610982565b005b3480156102d657600080fd5b506102df610ac6565b6040516102ec91906127f0565b60405180910390f35b34801561030157600080fd5b5061031c600480360381019061031791906129e8565b610ad3565b6040516103299190612a24565b60405180910390f35b34801561033e57600080fd5b50610359600480360381019061035491906128f3565b610af1565b005b34801561036757600080fd5b50610370610b03565b60405161037d9190612a24565b60405180910390f35b6103a0600480360381019061039b9190612a3f565b610b1a565b005b3480156103ae57600080fd5b506103c960048036038101906103c49190612af7565b610e3c565b6040516103d691906127f0565b60405180910390f35b3480156103eb57600080fd5b506103f4610ebb565b6040516104019190612b70565b60405180910390f35b34801561041657600080fd5b5061041f610ec1565b005b61043b60048036038101906104369190612a3f565b610f09565b005b34801561044957600080fd5b50610464600480360381019061045f91906128f3565b610f29565b6040516104719190612961565b60405180910390f35b34801561048657600080fd5b506104a1600480360381019061049c91906129e8565b610f3b565b6040516104ae9190612a24565b60405180910390f35b3480156104c357600080fd5b506104cc610ff3565b005b3480156104da57600080fd5b506104e3611007565b6040516104f09190612bea565b60405180910390f35b34801561050557600080fd5b5061050e61102d565b60405161051b9190612961565b60405180910390f35b34801561053057600080fd5b5061054b600480360381019061054691906128f3565b611057565b005b34801561055957600080fd5b50610562611069565b60405161056f919061289b565b60405180910390f35b34801561058457600080fd5b5061058d6110fb565b60405161059a9190612a24565b60405180910390f35b3480156105af57600080fd5b506105ca60048036038101906105c59190612c31565b611101565b005b3480156105d857600080fd5b506105e161120c565b6040516105ee9190612a24565b60405180910390f35b34801561060357600080fd5b5061060c611212565b6040516106199190612a24565b60405180910390f35b61063c60048036038101906106379190612da1565b611217565b005b61065860048036038101906106539190612ee7565b61128a565b005b34801561066657600080fd5b50610681600480360381019061067c91906128f3565b61133d565b60405161068e919061289b565b60405180910390f35b3480156106a357600080fd5b506106ac61187a565b6040516106b99190612a24565b60405180910390f35b3480156106ce57600080fd5b506106d7611880565b6040516106e49190612a24565b60405180910390f35b3480156106f957600080fd5b50610714600480360381019061070f9190612f43565b611886565b60405161072191906127f0565b60405180910390f35b610744600480360381019061073f91906128f3565b61191a565b005b34801561075257600080fd5b5061076d600480360381019061076891906129e8565b61196d565b005b34801561077b57600080fd5b50610796600480360381019061079191906128f3565b6119f0565b005b6107b260048036038101906107ad9190612f83565b611a02565b005b3480156107c057600080fd5b506107c9611aa1565b6040516107d691906127f0565b60405180910390f35b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061083a57506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061086a5750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60606002805461088090613012565b80601f01602080910402602001604051908101604052809291908181526020018280546108ac90613012565b80156108f95780601f106108ce576101008083540402835291602001916108f9565b820191906000526020600020905b8154815290600101906020018083116108dc57829003601f168201915b5050505050905090565b600061090e82611abb565b610944576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600061098d82610f29565b90508073ffffffffffffffffffffffffffffffffffffffff166109ae611b1a565b73ffffffffffffffffffffffffffffffffffffffff1614610a11576109da816109d5611b1a565b611886565b610a10576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b826006600084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b6000600d54431015905090565b6000610ade82611b22565b6014610aea9190613072565b9050919050565b610af9611b79565b80600e8190555050565b6000610b0d611bf7565b6001546000540303905090565b6000610b2582611c00565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610b8c576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610b9884611ccc565b91509150610bae8187610ba9611b1a565b611cf3565b610bfa57610bc386610bbe611b1a565b611886565b610bf9576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610c60576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c6d8686866001611d37565b8015610c7857600082555b600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001900391905081905550600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815460010191905081905550610d4685610d22888887611d3d565b7c020000000000000000000000000000000000000000000000000000000017611d65565b600460008681526020019081526020016000208190555060007c0200000000000000000000000000000000000000000000000000000000841603610dcc5760006001850190506000600460008381526020019081526020016000205403610dca576000548114610dc9578360046000838152602001908152602001600020819055505b5b505b838573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4610e348686866001611d90565b505050505050565b6000610eb2838380806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050600c5486604051602001610e9791906130ee565b60405160208183030381529060405280519060200120611d96565b90509392505050565b600c5481565b610ec9611b79565b3373ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050610f0757600080fd5b565b610f2483838360405180602001604052806000815250611217565b505050565b6000610f3482611c00565b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610fa2576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054169050919050565b610ffb611b79565b6110056000611dad565b565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61105f611b79565b8060098190555050565b60606003805461107890613012565b80601f01602080910402602001604051908101604052809291908181526020018280546110a490613012565b80156110f15780601f106110c6576101008083540402835291602001916110f1565b820191906000526020600020905b8154815290600101906020018083116110d457829003601f168201915b5050505050905090565b60095481565b806007600061110e611b1a565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff166111bb611b1a565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161120091906127f0565b60405180910390a35050565b600e5481565b601481565b611222848484610b1a565b60008373ffffffffffffffffffffffffffffffffffffffff163b146112845761124d84848484611e73565b611283576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b611292611b79565b600a548251826112a29190613109565b6112aa610b03565b6112b49190613163565b11156112f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ec906131e3565b60405180910390fd5b60005b82518110156113385761132583828151811061131757611316613203565b5b602002602001015183611fc3565b808061133090613232565b9150506112f8565b505050565b606061134882611abb565b61137e576040517fa14c4b5000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006113898361217e565b6040516020016113999190613302565b604051602081830303815290604052905060006040518060600160405280603f815260200161483a603f913990506000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d6cf5f55866040518263ffffffff1660e01b81526004016114249190612a24565b61012060405180830381865afa158015611442573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114669190613438565b90506032851115816101000190151590811515815250506000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166391b078a4836040518263ffffffff1660e01b81526004016114da919061353b565b600060405180830381865afa1580156114f7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906115209190613784565b90506000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637d11e69c84846040518363ffffffff1660e01b8152600401611581929190613979565b600060405180830381865afa15801561159e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906115c79190613a4c565b905060006115d8846020015161217e565b6115e5856060015161217e565b6115f2866040015161217e565b8660c00151611636576040518060400160405280600281526020017f4e6f00000000000000000000000000000000000000000000000000000000000081525061166d565b6040518060400160405280600381526020017f59657300000000000000000000000000000000000000000000000000000000008152505b7301e833cf8c115bb859a8e16a72d5ff298f8344136375f5696d88600001516040518263ffffffff1660e01b81526004016116a89190613aa4565b600060405180830381865af41580156116c5573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906116ee9190613a4c565b604051602001611702959493929190613d91565b60405160208183030381529060405290508360e00151156117c257807301e833cf8c115bb859a8e16a72d5ff298f8344136375f5696d85602001516040518263ffffffff1660e01b81526004016117599190613aa4565b600060405180830381865af4158015611776573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061179f9190613a4c565b6040516020016117b0929190613edf565b60405160208183030381529060405290505b836101000151156117f057806040516020016117de9190613f8f565b60405160208183030381529060405290505b806040516020016118019190613fd7565b6040516020818303038152906040529050600086868361182086612306565b604051602001611833949392919061419f565b604051602081830303815290604052905061184d81612306565b60405160200161185d9190614260565b604051602081830303815290604052975050505050505050919050565b600d5481565b600a5481565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b611922611aa1565b611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611958906142ce565b60405180910390fd5b61196a8161249d565b50565b611975611b79565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036119e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119db90614360565b60405180910390fd5b6119ed81611dad565b50565b6119f8611b79565b80600d8190555050565b611a0d338383610e3c565b611a4c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a43906143cc565b60405180910390fd5b611a54610ac6565b611a93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8a9061445e565b60405180910390fd5b611a9c8361249d565b505050565b6000600e54600d54611ab39190613163565b431015905090565b600081611ac6611bf7565b11158015611ad5575060005482105b8015611b13575060007c0100000000000000000000000000000000000000000000000000000000600460008581526020019081526020016000205416145b9050919050565b600033905090565b600067ffffffffffffffff6040600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054901c169050919050565b611b81612683565b73ffffffffffffffffffffffffffffffffffffffff16611b9f61102d565b73ffffffffffffffffffffffffffffffffffffffff1614611bf5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bec906144ca565b60405180910390fd5b565b60006001905090565b60008082905080611c0f611bf7565b11611c9557600054811015611c945760006004600083815260200190815260200160002054905060007c0100000000000000000000000000000000000000000000000000000000821603611c92575b60008103611c88576004600083600190039350838152602001908152602001600020549050611c5e565b8092505050611cc7565b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60008060006006600085815260200190815260200160002090508092508254915050915091565b600073ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b50505050565b60008060e883901c905060e8611d5486868461268b565b62ffffff16901b9150509392505050565b600073ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b600082611da38584612694565b1490509392505050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02611e99611b1a565b8786866040518563ffffffff1660e01b8152600401611ebb949392919061453f565b6020604051808303816000875af1925050508015611ef757506040513d601f19601f82011682018060405250810190611ef491906145a0565b60015b611f70573d8060008114611f27576040519150601f19603f3d011682016040523d82523d6000602084013e611f2c565b606091505b506000815103611f68576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b60008054905060008203612003576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120106000848385611d37565b600160406001901b178202600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550612087836120786000866000611d3d565b612081856126ea565b17611d65565b6004600083815260200190815260200160002081905550600080838301905073ffffffffffffffffffffffffffffffffffffffff85169150828260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600183015b81811461212857808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a46001810190506120ed565b5060008203612163576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060008190555050506121796000848385611d90565b505050565b6060600082036121c5576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612301565b600082905060005b600082146121f75780806121e090613232565b915050600a826121f091906145fc565b91506121cd565b60008167ffffffffffffffff81111561221357612212612c76565b5b6040519080825280601f01601f1916602001820160405280156122455781602001600182028036833780820191505090505b50905060008290505b600086146122f9576001816122639190613072565b90506000600a808861227591906145fc565b61227f9190613109565b8761228a9190613072565b6030612296919061463a565b905060008160f81b9050808484815181106122b4576122b3613203565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a886122f091906145fc565b9750505061224e565b819450505050505b919050565b60606000825190506000810361232e5760405180602001604052806000815250915050612498565b6000600360028361233f9190613163565b61234991906145fc565b60046123559190613109565b905060006020826123669190613163565b67ffffffffffffffff81111561237f5761237e612c76565b5b6040519080825280601f01601f1916602001820160405280156123b15781602001600182028036833780820191505090505b50905060006040518060600160405280604081526020016147fa604091399050600181016020830160005b868110156124555760038101905062ffffff818a015116603f8160121c168401518060081b905060ff603f83600c1c1686015116810190508060081b905060ff603f8360061c1686015116810190508060081b905060ff603f831686015116810190508060e01b905080845260048401935050506123dc565b50600386066001811461246f576002811461247f5761248a565b613d3d60f01b600283035261248a565b603d60f81b60018303525b508484525050819450505050505b919050565b806009546124ab9190613109565b3410156124ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124e4906146bb565b60405180910390fd5b600a54816124f9610b03565b6125039190613163565b1115612544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253b906131e3565b60405180910390fd5b60148161255033611b22565b61255a9190613163565b111561259b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161259290614727565b60405180910390fd5b6125a53382611fc3565b806009546125b39190613109565b3411156126805760003373ffffffffffffffffffffffffffffffffffffffff16826009546125e19190613109565b346125ec9190613072565b6040516125f890614778565b60006040518083038185875af1925050503d8060008114612635576040519150601f19603f3d011682016040523d82523d6000602084013e61263a565b606091505b505090508061267e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612675906147d9565b60405180910390fd5b505b50565b600033905090565b60009392505050565b60008082905060005b84518110156126df576126ca828683815181106126bd576126bc613203565b5b60200260200101516126fa565b915080806126d790613232565b91505061269d565b508091505092915050565b60006001821460e11b9050919050565b60008183106127125761270d8284612725565b61271d565b61271c8383612725565b5b905092915050565b600082600052816020526040600020905092915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61278581612750565b811461279057600080fd5b50565b6000813590506127a28161277c565b92915050565b6000602082840312156127be576127bd612746565b5b60006127cc84828501612793565b91505092915050565b60008115159050919050565b6127ea816127d5565b82525050565b600060208201905061280560008301846127e1565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561284557808201518184015260208101905061282a565b60008484015250505050565b6000601f19601f8301169050919050565b600061286d8261280b565b6128778185612816565b9350612887818560208601612827565b61289081612851565b840191505092915050565b600060208201905081810360008301526128b58184612862565b905092915050565b6000819050919050565b6128d0816128bd565b81146128db57600080fd5b50565b6000813590506128ed816128c7565b92915050565b60006020828403121561290957612908612746565b5b6000612917848285016128de565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061294b82612920565b9050919050565b61295b81612940565b82525050565b60006020820190506129766000830184612952565b92915050565b61298581612940565b811461299057600080fd5b50565b6000813590506129a28161297c565b92915050565b600080604083850312156129bf576129be612746565b5b60006129cd85828601612993565b92505060206129de858286016128de565b9150509250929050565b6000602082840312156129fe576129fd612746565b5b6000612a0c84828501612993565b91505092915050565b612a1e816128bd565b82525050565b6000602082019050612a396000830184612a15565b92915050565b600080600060608486031215612a5857612a57612746565b5b6000612a6686828701612993565b9350506020612a7786828701612993565b9250506040612a88868287016128de565b9150509250925092565b600080fd5b600080fd5b600080fd5b60008083601f840112612ab757612ab6612a92565b5b8235905067ffffffffffffffff811115612ad457612ad3612a97565b5b602083019150836020820283011115612af057612aef612a9c565b5b9250929050565b600080600060408486031215612b1057612b0f612746565b5b6000612b1e86828701612993565b935050602084013567ffffffffffffffff811115612b3f57612b3e61274b565b5b612b4b86828701612aa1565b92509250509250925092565b6000819050919050565b612b6a81612b57565b82525050565b6000602082019050612b856000830184612b61565b92915050565b6000819050919050565b6000612bb0612bab612ba684612920565b612b8b565b612920565b9050919050565b6000612bc282612b95565b9050919050565b6000612bd482612bb7565b9050919050565b612be481612bc9565b82525050565b6000602082019050612bff6000830184612bdb565b92915050565b612c0e816127d5565b8114612c1957600080fd5b50565b600081359050612c2b81612c05565b92915050565b60008060408385031215612c4857612c47612746565b5b6000612c5685828601612993565b9250506020612c6785828601612c1c565b9150509250929050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612cae82612851565b810181811067ffffffffffffffff82111715612ccd57612ccc612c76565b5b80604052505050565b6000612ce061273c565b9050612cec8282612ca5565b919050565b600067ffffffffffffffff821115612d0c57612d0b612c76565b5b612d1582612851565b9050602081019050919050565b82818337600083830152505050565b6000612d44612d3f84612cf1565b612cd6565b905082815260208101848484011115612d6057612d5f612c71565b5b612d6b848285612d22565b509392505050565b600082601f830112612d8857612d87612a92565b5b8135612d98848260208601612d31565b91505092915050565b60008060008060808587031215612dbb57612dba612746565b5b6000612dc987828801612993565b9450506020612dda87828801612993565b9350506040612deb878288016128de565b925050606085013567ffffffffffffffff811115612e0c57612e0b61274b565b5b612e1887828801612d73565b91505092959194509250565b600067ffffffffffffffff821115612e3f57612e3e612c76565b5b602082029050602081019050919050565b6000612e63612e5e84612e24565b612cd6565b90508083825260208201905060208402830185811115612e8657612e85612a9c565b5b835b81811015612eaf5780612e9b8882612993565b845260208401935050602081019050612e88565b5050509392505050565b600082601f830112612ece57612ecd612a92565b5b8135612ede848260208601612e50565b91505092915050565b60008060408385031215612efe57612efd612746565b5b600083013567ffffffffffffffff811115612f1c57612f1b61274b565b5b612f2885828601612eb9565b9250506020612f39858286016128de565b9150509250929050565b60008060408385031215612f5a57612f59612746565b5b6000612f6885828601612993565b9250506020612f7985828601612993565b9150509250929050565b600080600060408486031215612f9c57612f9b612746565b5b6000612faa868287016128de565b935050602084013567ffffffffffffffff811115612fcb57612fca61274b565b5b612fd786828701612aa1565b92509250509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061302a57607f821691505b60208210810361303d5761303c612fe3565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061307d826128bd565b9150613088836128bd565b92508282039050818111156130a05761309f613043565b5b92915050565b60008160601b9050919050565b60006130be826130a6565b9050919050565b60006130d0826130b3565b9050919050565b6130e86130e382612940565b6130c5565b82525050565b60006130fa82846130d7565b60148201915081905092915050565b6000613114826128bd565b915061311f836128bd565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561315857613157613043565b5b828202905092915050565b600061316e826128bd565b9150613179836128bd565b925082820190508082111561319157613190613043565b5b92915050565b7f45786365656473206d617820737570706c790000000000000000000000000000600082015250565b60006131cd601283612816565b91506131d882613197565b602082019050919050565b600060208201905081810360008301526131fc816131c0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061323d826128bd565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361326f5761326e613043565b5b600182019050919050565b600081905092915050565b7f4b616c6569646f73636f70652023000000000000000000000000000000000000600082015250565b60006132bb600e8361327a565b91506132c682613285565b600e82019050919050565b60006132dc8261280b565b6132e6818561327a565b93506132f6818560208601612827565b80840191505092915050565b600061330d826132ae565b915061331982846132d1565b915081905092915050565b600080fd5b600080fd5b60008151905061333d816128c7565b92915050565b60008151905061335281612c05565b92915050565b6000610120828403121561336f5761336e613324565b5b61337a610120612cd6565b9050600061338a8482850161332e565b600083015250602061339e8482850161332e565b60208301525060406133b28482850161332e565b60408301525060606133c68482850161332e565b60608301525060806133da8482850161332e565b60808301525060a06133ee8482850161332e565b60a08301525060c061340284828501613343565b60c08301525060e061341684828501613343565b60e08301525061010061342b84828501613343565b6101008301525092915050565b6000610120828403121561344f5761344e612746565b5b600061345d84828501613358565b91505092915050565b61346f816128bd565b82525050565b61347e816127d5565b82525050565b6101208201600082015161349b6000850182613466565b5060208201516134ae6020850182613466565b5060408201516134c16040850182613466565b5060608201516134d46060850182613466565b5060808201516134e76080850182613466565b5060a08201516134fa60a0850182613466565b5060c082015161350d60c0850182613475565b5060e082015161352060e0850182613475565b50610100820151613535610100850182613475565b50505050565b6000610120820190506135516000830184613484565b92915050565b60006060828403121561356d5761356c613324565b5b6135776060612cd6565b905060006135878482850161332e565b600083015250602061359b8482850161332e565b60208301525060406135af8482850161332e565b60408301525092915050565b600067ffffffffffffffff8211156135d6576135d5612c76565b5b602082029050602081019050919050565b60006135fa6135f5846135bb565b612cd6565b9050808382526020820190506060840283018581111561361d5761361c612a9c565b5b835b8181101561364657806136328882613557565b84526020840193505060608101905061361f565b5050509392505050565b600082601f83011261366557613664612a92565b5b81516136758482602086016135e7565b91505092915050565b6000610200828403121561369557613694613324565b5b6136a0610100612cd6565b905060006136b08482850161332e565b60008301525060206136c48482850161332e565b60208301525060406136d884828501613557565b60408301525060a06136ec84828501613557565b60608301525061010061370184828501613557565b60808301525061016061371684828501613557565b60a0830152506101c082015167ffffffffffffffff81111561373b5761373a613329565b5b61374784828501613650565b60c0830152506101e082015167ffffffffffffffff81111561376c5761376b613329565b5b61377884828501613650565b60e08301525092915050565b60006020828403121561379a57613799612746565b5b600082015167ffffffffffffffff8111156137b8576137b761274b565b5b6137c48482850161367e565b91505092915050565b6060820160008201516137e36000850182613466565b5060208201516137f66020850182613466565b5060408201516138096040850182613466565b50505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061384783836137cd565b60608301905092915050565b6000602082019050919050565b600061386b8261380f565b613875818561381a565b93506138808361382b565b8060005b838110156138b1578151613898888261383b565b97506138a383613853565b925050600181019050613884565b5085935050505092915050565b6000610200830160008301516138d76000860182613466565b5060208301516138ea6020860182613466565b5060408301516138fd60408601826137cd565b50606083015161391060a08601826137cd565b5060808301516139246101008601826137cd565b5060a08301516139386101608601826137cd565b5060c08301518482036101c08601526139518282613860565b91505060e08301518482036101e086015261396c8282613860565b9150508091505092915050565b60006101408201905061398f6000830185613484565b8181036101208301526139a281846138be565b90509392505050565b600067ffffffffffffffff8211156139c6576139c5612c76565b5b6139cf82612851565b9050602081019050919050565b60006139ef6139ea846139ab565b612cd6565b905082815260208101848484011115613a0b57613a0a612c71565b5b613a16848285612827565b509392505050565b600082601f830112613a3357613a32612a92565b5b8151613a438482602086016139dc565b91505092915050565b600060208284031215613a6257613a61612746565b5b600082015167ffffffffffffffff811115613a8057613a7f61274b565b5b613a8c84828501613a1e565b91505092915050565b613a9e816128bd565b82525050565b6000602082019050613ab96000830184613a95565b92915050565b7f2261747472696275746573223a205b0000000000000000000000000000000000815250565b7f7b2274726169745f74797065223a20224d6972726f7273222c202276616c756560008201527f223a200000000000000000000000000000000000000000000000000000000000602082015250565b6000613b4160238361327a565b9150613b4c82613ae5565b602382019050919050565b7f7d2c000000000000000000000000000000000000000000000000000000000000815250565b7f7b2274726169745f74797065223a20224f75747369646520417274696661637460008201527f73222c202276616c7565223a2000000000000000000000000000000000000000602082015250565b6000613bd9602d8361327a565b9150613be482613b7d565b602d82019050919050565b7f7b2274726169745f74797065223a2022496e736964652041727469666163747360008201527f222c202276616c7565223a200000000000000000000000000000000000000000602082015250565b6000613c4b602c8361327a565b9150613c5682613bef565b602c82019050919050565b7f7b2274726169745f74797065223a20224772616469656e74222c202276616c7560008201527f65223a2022000000000000000000000000000000000000000000000000000000602082015250565b6000613cbd60258361327a565b9150613cc882613c61565b602582019050919050565b7f227d2c0000000000000000000000000000000000000000000000000000000000815250565b7f7b2274726169745f74797065223a20225072696d61727920436f6c6f72222c2060008201527f2276616c7565223a202200000000000000000000000000000000000000000000602082015250565b6000613d55602a8361327a565b9150613d6082613cf9565b602a82019050919050565b7f227d000000000000000000000000000000000000000000000000000000000000815250565b6000613d9c82613abf565b600f82019150613dab82613b34565b9150613db782886132d1565b9150613dc282613b57565b600282019150613dd182613bcc565b9150613ddd82876132d1565b9150613de882613b57565b600282019150613df782613c3e565b9150613e0382866132d1565b9150613e0e82613b57565b600282019150613e1d82613cb0565b9150613e2982856132d1565b9150613e3482613cd3565b600382019150613e4382613d48565b9150613e4f82846132d1565b9150613e5a82613d6b565b6002820191508190509695505050505050565b7f2c7b2274726169745f74797065223a20225365636f6e6461727920436f6c6f7260008201527f222c202276616c7565223a202200000000000000000000000000000000000000602082015250565b6000613ec9602d8361327a565b9150613ed482613e6d565b602d82019050919050565b6000613eeb82856132d1565b9150613ef682613ebc565b9150613f0282846132d1565b9150613f0d82613d6b565b6002820191508190509392505050565b7f2c7b2274726169745f74797065223a202248616c6f222c202276616c7565223a60008201527f2022596573227d00000000000000000000000000000000000000000000000000602082015250565b6000613f7960278361327a565b9150613f8482613f1d565b602782019050919050565b6000613f9b82846132d1565b9150613fa682613f6c565b915081905092915050565b7f5d00000000000000000000000000000000000000000000000000000000000000815250565b6000613fe382846132d1565b9150613fee82613fb1565b60018201915081905092915050565b7f7b226e616d65223a220000000000000000000000000000000000000000000000600082015250565b600061403360098361327a565b915061403e82613ffd565b600982019050919050565b7f222c226465736372697074696f6e223a22000000000000000000000000000000600082015250565b600061407f60118361327a565b915061408a82614049565b601182019050919050565b7f222c000000000000000000000000000000000000000000000000000000000000600082015250565b60006140cb60028361327a565b91506140d682614095565b600282019050919050565b7f2c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b6260008201527f61736536342c0000000000000000000000000000000000000000000000000000602082015250565b600061413d60268361327a565b9150614148826140e1565b602682019050919050565b7f227d000000000000000000000000000000000000000000000000000000000000600082015250565b600061418960028361327a565b915061419482614153565b600282019050919050565b60006141aa82614026565b91506141b682876132d1565b91506141c182614072565b91506141cd82866132d1565b91506141d8826140be565b91506141e482856132d1565b91506141ef82614130565b91506141fb82846132d1565b91506142068261417c565b915081905095945050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b600061424a601d8361327a565b915061425582614214565b601d82019050919050565b600061426b8261423d565b915061427782846132d1565b915081905092915050565b7f5075626c69632073616c6520686173206e6f7420737461727465642079657400600082015250565b60006142b8601f83612816565b91506142c382614282565b602082019050919050565b600060208201905081810360008301526142e7816142ab565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061434a602683612816565b9150614355826142ee565b604082019050919050565b600060208201905081810360008301526143798161433d565b9050919050565b7f596f7520617265206e6f74206f6e2074686520616c6c6f776c69737400000000600082015250565b60006143b6601c83612816565b91506143c182614380565b602082019050919050565b600060208201905081810360008301526143e5816143a9565b9050919050565b7f416c6c6f776c6973742073616c6520686173206e6f742073746172746564207960008201527f6574000000000000000000000000000000000000000000000000000000000000602082015250565b6000614448602283612816565b9150614453826143ec565b604082019050919050565b600060208201905081810360008301526144778161443b565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006144b4602083612816565b91506144bf8261447e565b602082019050919050565b600060208201905081810360008301526144e3816144a7565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000614511826144ea565b61451b81856144f5565b935061452b818560208601612827565b61453481612851565b840191505092915050565b60006080820190506145546000830187612952565b6145616020830186612952565b61456e6040830185612a15565b81810360608301526145808184614506565b905095945050505050565b60008151905061459a8161277c565b92915050565b6000602082840312156145b6576145b5612746565b5b60006145c48482850161458b565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614607826128bd565b9150614612836128bd565b925082614622576146216145cd565b5b828204905092915050565b600060ff82169050919050565b60006146458261462d565b91506146508361462d565b9250828201905060ff81111561466957614668613043565b5b92915050565b7f496e73756666696369656e742066656500000000000000000000000000000000600082015250565b60006146a5601083612816565b91506146b08261466f565b602082019050919050565b600060208201905081810360008301526146d481614698565b9050919050565b7f45786365656473206d6178207175616e74697479000000000000000000000000600082015250565b6000614711601483612816565b915061471c826146db565b602082019050919050565b6000602082019050818103600083015261474081614704565b9050919050565b600081905092915050565b50565b6000614762600083614747565b915061476d82614752565b600082019050919050565b600061478382614755565b9150819050919050565b7f526566756e64206661696c656400000000000000000000000000000000000000600082015250565b60006147c3600d83612816565b91506147ce8261478d565b602082019050919050565b600060208201905081810360008301526147f2816147b6565b905091905056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f46756c6c79206f6e2d636861696e2c2070726f6365647572616c6c792067656e6572617465642c20616e696d61746564206b616c6569646f73636f7065732ea264697066735822122052abef236944e932101b30fe89aa13017f608c9ba9c850189986d5776b62cea064736f6c6343000810003300000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000003e81a803dbdfb3d0c0c775bc03f7e858f42eac3ccf7aae62a18b498e8dcced2b2240000000000000000000000000000000000000000000000000000000000fa3afc000000000000000000000000000000000000000000000000000000000000012c000000000000000000000000834a227ec86776292601d298de4a767677950a55000000000000000000000000000000000000000000000000000000000000000d4b616c6569646f73636f7065730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064b4c445343500000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106102045760003560e01c80638da5cb5b11610118578063c87b56dd116100a0578063efd0cbf91161006f578063efd0cbf91461072a578063f2fde38b14610746578063f764561d1461076f578063fa05a65714610798578063fdd4b0f0146107b457610204565b8063c87b56dd1461065a578063d0e59d5a14610697578063d5abeb01146106c2578063e985e9c5146106ed57610204565b8063a22cb465116100e7578063a22cb465146105a3578063afc1cad3146105cc578063b228d925146105f7578063b88d4fde14610622578063c204642c1461063e57610204565b80638da5cb5b146104f957806391b7f5ed1461052457806395d89b411461054d578063a035b1fe1461057857610204565b806323b872dd1161019b57806342842e0e1161016a57806342842e0e146104215780636352211e1461043d57806370a082311461047a578063715018a6146104b75780638ada6b0f146104ce57610204565b806323b872dd14610386578063247155ff146103a25780632eb4a7ab146103df5780633ccfd60b1461040a57610204565b80630bf02d87116101d75780630bf02d87146102ca5780630e2a1448146102f5578063170a78cc1461033257806318160ddd1461035b57610204565b806301ffc9a71461020957806306fdde0314610246578063081812fc14610271578063095ea7b3146102ae575b600080fd5b34801561021557600080fd5b50610230600480360381019061022b91906127a8565b6107df565b60405161023d91906127f0565b60405180910390f35b34801561025257600080fd5b5061025b610871565b604051610268919061289b565b60405180910390f35b34801561027d57600080fd5b50610298600480360381019061029391906128f3565b610903565b6040516102a59190612961565b60405180910390f35b6102c860048036038101906102c391906129a8565b610982565b005b3480156102d657600080fd5b506102df610ac6565b6040516102ec91906127f0565b60405180910390f35b34801561030157600080fd5b5061031c600480360381019061031791906129e8565b610ad3565b6040516103299190612a24565b60405180910390f35b34801561033e57600080fd5b50610359600480360381019061035491906128f3565b610af1565b005b34801561036757600080fd5b50610370610b03565b60405161037d9190612a24565b60405180910390f35b6103a0600480360381019061039b9190612a3f565b610b1a565b005b3480156103ae57600080fd5b506103c960048036038101906103c49190612af7565b610e3c565b6040516103d691906127f0565b60405180910390f35b3480156103eb57600080fd5b506103f4610ebb565b6040516104019190612b70565b60405180910390f35b34801561041657600080fd5b5061041f610ec1565b005b61043b60048036038101906104369190612a3f565b610f09565b005b34801561044957600080fd5b50610464600480360381019061045f91906128f3565b610f29565b6040516104719190612961565b60405180910390f35b34801561048657600080fd5b506104a1600480360381019061049c91906129e8565b610f3b565b6040516104ae9190612a24565b60405180910390f35b3480156104c357600080fd5b506104cc610ff3565b005b3480156104da57600080fd5b506104e3611007565b6040516104f09190612bea565b60405180910390f35b34801561050557600080fd5b5061050e61102d565b60405161051b9190612961565b60405180910390f35b34801561053057600080fd5b5061054b600480360381019061054691906128f3565b611057565b005b34801561055957600080fd5b50610562611069565b60405161056f919061289b565b60405180910390f35b34801561058457600080fd5b5061058d6110fb565b60405161059a9190612a24565b60405180910390f35b3480156105af57600080fd5b506105ca60048036038101906105c59190612c31565b611101565b005b3480156105d857600080fd5b506105e161120c565b6040516105ee9190612a24565b60405180910390f35b34801561060357600080fd5b5061060c611212565b6040516106199190612a24565b60405180910390f35b61063c60048036038101906106379190612da1565b611217565b005b61065860048036038101906106539190612ee7565b61128a565b005b34801561066657600080fd5b50610681600480360381019061067c91906128f3565b61133d565b60405161068e919061289b565b60405180910390f35b3480156106a357600080fd5b506106ac61187a565b6040516106b99190612a24565b60405180910390f35b3480156106ce57600080fd5b506106d7611880565b6040516106e49190612a24565b60405180910390f35b3480156106f957600080fd5b50610714600480360381019061070f9190612f43565b611886565b60405161072191906127f0565b60405180910390f35b610744600480360381019061073f91906128f3565b61191a565b005b34801561075257600080fd5b5061076d600480360381019061076891906129e8565b61196d565b005b34801561077b57600080fd5b50610796600480360381019061079191906128f3565b6119f0565b005b6107b260048036038101906107ad9190612f83565b611a02565b005b3480156107c057600080fd5b506107c9611aa1565b6040516107d691906127f0565b60405180910390f35b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061083a57506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061086a5750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60606002805461088090613012565b80601f01602080910402602001604051908101604052809291908181526020018280546108ac90613012565b80156108f95780601f106108ce576101008083540402835291602001916108f9565b820191906000526020600020905b8154815290600101906020018083116108dc57829003601f168201915b5050505050905090565b600061090e82611abb565b610944576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600061098d82610f29565b90508073ffffffffffffffffffffffffffffffffffffffff166109ae611b1a565b73ffffffffffffffffffffffffffffffffffffffff1614610a11576109da816109d5611b1a565b611886565b610a10576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b826006600084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b6000600d54431015905090565b6000610ade82611b22565b6014610aea9190613072565b9050919050565b610af9611b79565b80600e8190555050565b6000610b0d611bf7565b6001546000540303905090565b6000610b2582611c00565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610b8c576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610b9884611ccc565b91509150610bae8187610ba9611b1a565b611cf3565b610bfa57610bc386610bbe611b1a565b611886565b610bf9576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610c60576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c6d8686866001611d37565b8015610c7857600082555b600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001900391905081905550600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815460010191905081905550610d4685610d22888887611d3d565b7c020000000000000000000000000000000000000000000000000000000017611d65565b600460008681526020019081526020016000208190555060007c0200000000000000000000000000000000000000000000000000000000841603610dcc5760006001850190506000600460008381526020019081526020016000205403610dca576000548114610dc9578360046000838152602001908152602001600020819055505b5b505b838573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4610e348686866001611d90565b505050505050565b6000610eb2838380806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050600c5486604051602001610e9791906130ee565b60405160208183030381529060405280519060200120611d96565b90509392505050565b600c5481565b610ec9611b79565b3373ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050610f0757600080fd5b565b610f2483838360405180602001604052806000815250611217565b505050565b6000610f3482611c00565b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610fa2576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054169050919050565b610ffb611b79565b6110056000611dad565b565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61105f611b79565b8060098190555050565b60606003805461107890613012565b80601f01602080910402602001604051908101604052809291908181526020018280546110a490613012565b80156110f15780601f106110c6576101008083540402835291602001916110f1565b820191906000526020600020905b8154815290600101906020018083116110d457829003601f168201915b5050505050905090565b60095481565b806007600061110e611b1a565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff166111bb611b1a565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161120091906127f0565b60405180910390a35050565b600e5481565b601481565b611222848484610b1a565b60008373ffffffffffffffffffffffffffffffffffffffff163b146112845761124d84848484611e73565b611283576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b611292611b79565b600a548251826112a29190613109565b6112aa610b03565b6112b49190613163565b11156112f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ec906131e3565b60405180910390fd5b60005b82518110156113385761132583828151811061131757611316613203565b5b602002602001015183611fc3565b808061133090613232565b9150506112f8565b505050565b606061134882611abb565b61137e576040517fa14c4b5000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006113898361217e565b6040516020016113999190613302565b604051602081830303815290604052905060006040518060600160405280603f815260200161483a603f913990506000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d6cf5f55866040518263ffffffff1660e01b81526004016114249190612a24565b61012060405180830381865afa158015611442573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114669190613438565b90506032851115816101000190151590811515815250506000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166391b078a4836040518263ffffffff1660e01b81526004016114da919061353b565b600060405180830381865afa1580156114f7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906115209190613784565b90506000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637d11e69c84846040518363ffffffff1660e01b8152600401611581929190613979565b600060405180830381865afa15801561159e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906115c79190613a4c565b905060006115d8846020015161217e565b6115e5856060015161217e565b6115f2866040015161217e565b8660c00151611636576040518060400160405280600281526020017f4e6f00000000000000000000000000000000000000000000000000000000000081525061166d565b6040518060400160405280600381526020017f59657300000000000000000000000000000000000000000000000000000000008152505b7301e833cf8c115bb859a8e16a72d5ff298f8344136375f5696d88600001516040518263ffffffff1660e01b81526004016116a89190613aa4565b600060405180830381865af41580156116c5573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906116ee9190613a4c565b604051602001611702959493929190613d91565b60405160208183030381529060405290508360e00151156117c257807301e833cf8c115bb859a8e16a72d5ff298f8344136375f5696d85602001516040518263ffffffff1660e01b81526004016117599190613aa4565b600060405180830381865af4158015611776573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061179f9190613a4c565b6040516020016117b0929190613edf565b60405160208183030381529060405290505b836101000151156117f057806040516020016117de9190613f8f565b60405160208183030381529060405290505b806040516020016118019190613fd7565b6040516020818303038152906040529050600086868361182086612306565b604051602001611833949392919061419f565b604051602081830303815290604052905061184d81612306565b60405160200161185d9190614260565b604051602081830303815290604052975050505050505050919050565b600d5481565b600a5481565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b611922611aa1565b611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611958906142ce565b60405180910390fd5b61196a8161249d565b50565b611975611b79565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036119e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119db90614360565b60405180910390fd5b6119ed81611dad565b50565b6119f8611b79565b80600d8190555050565b611a0d338383610e3c565b611a4c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a43906143cc565b60405180910390fd5b611a54610ac6565b611a93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8a9061445e565b60405180910390fd5b611a9c8361249d565b505050565b6000600e54600d54611ab39190613163565b431015905090565b600081611ac6611bf7565b11158015611ad5575060005482105b8015611b13575060007c0100000000000000000000000000000000000000000000000000000000600460008581526020019081526020016000205416145b9050919050565b600033905090565b600067ffffffffffffffff6040600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054901c169050919050565b611b81612683565b73ffffffffffffffffffffffffffffffffffffffff16611b9f61102d565b73ffffffffffffffffffffffffffffffffffffffff1614611bf5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bec906144ca565b60405180910390fd5b565b60006001905090565b60008082905080611c0f611bf7565b11611c9557600054811015611c945760006004600083815260200190815260200160002054905060007c0100000000000000000000000000000000000000000000000000000000821603611c92575b60008103611c88576004600083600190039350838152602001908152602001600020549050611c5e565b8092505050611cc7565b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60008060006006600085815260200190815260200160002090508092508254915050915091565b600073ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b50505050565b60008060e883901c905060e8611d5486868461268b565b62ffffff16901b9150509392505050565b600073ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b600082611da38584612694565b1490509392505050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02611e99611b1a565b8786866040518563ffffffff1660e01b8152600401611ebb949392919061453f565b6020604051808303816000875af1925050508015611ef757506040513d601f19601f82011682018060405250810190611ef491906145a0565b60015b611f70573d8060008114611f27576040519150601f19603f3d011682016040523d82523d6000602084013e611f2c565b606091505b506000815103611f68576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b60008054905060008203612003576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120106000848385611d37565b600160406001901b178202600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550612087836120786000866000611d3d565b612081856126ea565b17611d65565b6004600083815260200190815260200160002081905550600080838301905073ffffffffffffffffffffffffffffffffffffffff85169150828260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600183015b81811461212857808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a46001810190506120ed565b5060008203612163576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060008190555050506121796000848385611d90565b505050565b6060600082036121c5576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612301565b600082905060005b600082146121f75780806121e090613232565b915050600a826121f091906145fc565b91506121cd565b60008167ffffffffffffffff81111561221357612212612c76565b5b6040519080825280601f01601f1916602001820160405280156122455781602001600182028036833780820191505090505b50905060008290505b600086146122f9576001816122639190613072565b90506000600a808861227591906145fc565b61227f9190613109565b8761228a9190613072565b6030612296919061463a565b905060008160f81b9050808484815181106122b4576122b3613203565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a886122f091906145fc565b9750505061224e565b819450505050505b919050565b60606000825190506000810361232e5760405180602001604052806000815250915050612498565b6000600360028361233f9190613163565b61234991906145fc565b60046123559190613109565b905060006020826123669190613163565b67ffffffffffffffff81111561237f5761237e612c76565b5b6040519080825280601f01601f1916602001820160405280156123b15781602001600182028036833780820191505090505b50905060006040518060600160405280604081526020016147fa604091399050600181016020830160005b868110156124555760038101905062ffffff818a015116603f8160121c168401518060081b905060ff603f83600c1c1686015116810190508060081b905060ff603f8360061c1686015116810190508060081b905060ff603f831686015116810190508060e01b905080845260048401935050506123dc565b50600386066001811461246f576002811461247f5761248a565b613d3d60f01b600283035261248a565b603d60f81b60018303525b508484525050819450505050505b919050565b806009546124ab9190613109565b3410156124ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124e4906146bb565b60405180910390fd5b600a54816124f9610b03565b6125039190613163565b1115612544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253b906131e3565b60405180910390fd5b60148161255033611b22565b61255a9190613163565b111561259b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161259290614727565b60405180910390fd5b6125a53382611fc3565b806009546125b39190613109565b3411156126805760003373ffffffffffffffffffffffffffffffffffffffff16826009546125e19190613109565b346125ec9190613072565b6040516125f890614778565b60006040518083038185875af1925050503d8060008114612635576040519150601f19603f3d011682016040523d82523d6000602084013e61263a565b606091505b505090508061267e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612675906147d9565b60405180910390fd5b505b50565b600033905090565b60009392505050565b60008082905060005b84518110156126df576126ca828683815181106126bd576126bc613203565b5b60200260200101516126fa565b915080806126d790613232565b91505061269d565b508091505092915050565b60006001821460e11b9050919050565b60008183106127125761270d8284612725565b61271d565b61271c8383612725565b5b905092915050565b600082600052816020526040600020905092915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61278581612750565b811461279057600080fd5b50565b6000813590506127a28161277c565b92915050565b6000602082840312156127be576127bd612746565b5b60006127cc84828501612793565b91505092915050565b60008115159050919050565b6127ea816127d5565b82525050565b600060208201905061280560008301846127e1565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561284557808201518184015260208101905061282a565b60008484015250505050565b6000601f19601f8301169050919050565b600061286d8261280b565b6128778185612816565b9350612887818560208601612827565b61289081612851565b840191505092915050565b600060208201905081810360008301526128b58184612862565b905092915050565b6000819050919050565b6128d0816128bd565b81146128db57600080fd5b50565b6000813590506128ed816128c7565b92915050565b60006020828403121561290957612908612746565b5b6000612917848285016128de565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061294b82612920565b9050919050565b61295b81612940565b82525050565b60006020820190506129766000830184612952565b92915050565b61298581612940565b811461299057600080fd5b50565b6000813590506129a28161297c565b92915050565b600080604083850312156129bf576129be612746565b5b60006129cd85828601612993565b92505060206129de858286016128de565b9150509250929050565b6000602082840312156129fe576129fd612746565b5b6000612a0c84828501612993565b91505092915050565b612a1e816128bd565b82525050565b6000602082019050612a396000830184612a15565b92915050565b600080600060608486031215612a5857612a57612746565b5b6000612a6686828701612993565b9350506020612a7786828701612993565b9250506040612a88868287016128de565b9150509250925092565b600080fd5b600080fd5b600080fd5b60008083601f840112612ab757612ab6612a92565b5b8235905067ffffffffffffffff811115612ad457612ad3612a97565b5b602083019150836020820283011115612af057612aef612a9c565b5b9250929050565b600080600060408486031215612b1057612b0f612746565b5b6000612b1e86828701612993565b935050602084013567ffffffffffffffff811115612b3f57612b3e61274b565b5b612b4b86828701612aa1565b92509250509250925092565b6000819050919050565b612b6a81612b57565b82525050565b6000602082019050612b856000830184612b61565b92915050565b6000819050919050565b6000612bb0612bab612ba684612920565b612b8b565b612920565b9050919050565b6000612bc282612b95565b9050919050565b6000612bd482612bb7565b9050919050565b612be481612bc9565b82525050565b6000602082019050612bff6000830184612bdb565b92915050565b612c0e816127d5565b8114612c1957600080fd5b50565b600081359050612c2b81612c05565b92915050565b60008060408385031215612c4857612c47612746565b5b6000612c5685828601612993565b9250506020612c6785828601612c1c565b9150509250929050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612cae82612851565b810181811067ffffffffffffffff82111715612ccd57612ccc612c76565b5b80604052505050565b6000612ce061273c565b9050612cec8282612ca5565b919050565b600067ffffffffffffffff821115612d0c57612d0b612c76565b5b612d1582612851565b9050602081019050919050565b82818337600083830152505050565b6000612d44612d3f84612cf1565b612cd6565b905082815260208101848484011115612d6057612d5f612c71565b5b612d6b848285612d22565b509392505050565b600082601f830112612d8857612d87612a92565b5b8135612d98848260208601612d31565b91505092915050565b60008060008060808587031215612dbb57612dba612746565b5b6000612dc987828801612993565b9450506020612dda87828801612993565b9350506040612deb878288016128de565b925050606085013567ffffffffffffffff811115612e0c57612e0b61274b565b5b612e1887828801612d73565b91505092959194509250565b600067ffffffffffffffff821115612e3f57612e3e612c76565b5b602082029050602081019050919050565b6000612e63612e5e84612e24565b612cd6565b90508083825260208201905060208402830185811115612e8657612e85612a9c565b5b835b81811015612eaf5780612e9b8882612993565b845260208401935050602081019050612e88565b5050509392505050565b600082601f830112612ece57612ecd612a92565b5b8135612ede848260208601612e50565b91505092915050565b60008060408385031215612efe57612efd612746565b5b600083013567ffffffffffffffff811115612f1c57612f1b61274b565b5b612f2885828601612eb9565b9250506020612f39858286016128de565b9150509250929050565b60008060408385031215612f5a57612f59612746565b5b6000612f6885828601612993565b9250506020612f7985828601612993565b9150509250929050565b600080600060408486031215612f9c57612f9b612746565b5b6000612faa868287016128de565b935050602084013567ffffffffffffffff811115612fcb57612fca61274b565b5b612fd786828701612aa1565b92509250509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061302a57607f821691505b60208210810361303d5761303c612fe3565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061307d826128bd565b9150613088836128bd565b92508282039050818111156130a05761309f613043565b5b92915050565b60008160601b9050919050565b60006130be826130a6565b9050919050565b60006130d0826130b3565b9050919050565b6130e86130e382612940565b6130c5565b82525050565b60006130fa82846130d7565b60148201915081905092915050565b6000613114826128bd565b915061311f836128bd565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561315857613157613043565b5b828202905092915050565b600061316e826128bd565b9150613179836128bd565b925082820190508082111561319157613190613043565b5b92915050565b7f45786365656473206d617820737570706c790000000000000000000000000000600082015250565b60006131cd601283612816565b91506131d882613197565b602082019050919050565b600060208201905081810360008301526131fc816131c0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061323d826128bd565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361326f5761326e613043565b5b600182019050919050565b600081905092915050565b7f4b616c6569646f73636f70652023000000000000000000000000000000000000600082015250565b60006132bb600e8361327a565b91506132c682613285565b600e82019050919050565b60006132dc8261280b565b6132e6818561327a565b93506132f6818560208601612827565b80840191505092915050565b600061330d826132ae565b915061331982846132d1565b915081905092915050565b600080fd5b600080fd5b60008151905061333d816128c7565b92915050565b60008151905061335281612c05565b92915050565b6000610120828403121561336f5761336e613324565b5b61337a610120612cd6565b9050600061338a8482850161332e565b600083015250602061339e8482850161332e565b60208301525060406133b28482850161332e565b60408301525060606133c68482850161332e565b60608301525060806133da8482850161332e565b60808301525060a06133ee8482850161332e565b60a08301525060c061340284828501613343565b60c08301525060e061341684828501613343565b60e08301525061010061342b84828501613343565b6101008301525092915050565b6000610120828403121561344f5761344e612746565b5b600061345d84828501613358565b91505092915050565b61346f816128bd565b82525050565b61347e816127d5565b82525050565b6101208201600082015161349b6000850182613466565b5060208201516134ae6020850182613466565b5060408201516134c16040850182613466565b5060608201516134d46060850182613466565b5060808201516134e76080850182613466565b5060a08201516134fa60a0850182613466565b5060c082015161350d60c0850182613475565b5060e082015161352060e0850182613475565b50610100820151613535610100850182613475565b50505050565b6000610120820190506135516000830184613484565b92915050565b60006060828403121561356d5761356c613324565b5b6135776060612cd6565b905060006135878482850161332e565b600083015250602061359b8482850161332e565b60208301525060406135af8482850161332e565b60408301525092915050565b600067ffffffffffffffff8211156135d6576135d5612c76565b5b602082029050602081019050919050565b60006135fa6135f5846135bb565b612cd6565b9050808382526020820190506060840283018581111561361d5761361c612a9c565b5b835b8181101561364657806136328882613557565b84526020840193505060608101905061361f565b5050509392505050565b600082601f83011261366557613664612a92565b5b81516136758482602086016135e7565b91505092915050565b6000610200828403121561369557613694613324565b5b6136a0610100612cd6565b905060006136b08482850161332e565b60008301525060206136c48482850161332e565b60208301525060406136d884828501613557565b60408301525060a06136ec84828501613557565b60608301525061010061370184828501613557565b60808301525061016061371684828501613557565b60a0830152506101c082015167ffffffffffffffff81111561373b5761373a613329565b5b61374784828501613650565b60c0830152506101e082015167ffffffffffffffff81111561376c5761376b613329565b5b61377884828501613650565b60e08301525092915050565b60006020828403121561379a57613799612746565b5b600082015167ffffffffffffffff8111156137b8576137b761274b565b5b6137c48482850161367e565b91505092915050565b6060820160008201516137e36000850182613466565b5060208201516137f66020850182613466565b5060408201516138096040850182613466565b50505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061384783836137cd565b60608301905092915050565b6000602082019050919050565b600061386b8261380f565b613875818561381a565b93506138808361382b565b8060005b838110156138b1578151613898888261383b565b97506138a383613853565b925050600181019050613884565b5085935050505092915050565b6000610200830160008301516138d76000860182613466565b5060208301516138ea6020860182613466565b5060408301516138fd60408601826137cd565b50606083015161391060a08601826137cd565b5060808301516139246101008601826137cd565b5060a08301516139386101608601826137cd565b5060c08301518482036101c08601526139518282613860565b91505060e08301518482036101e086015261396c8282613860565b9150508091505092915050565b60006101408201905061398f6000830185613484565b8181036101208301526139a281846138be565b90509392505050565b600067ffffffffffffffff8211156139c6576139c5612c76565b5b6139cf82612851565b9050602081019050919050565b60006139ef6139ea846139ab565b612cd6565b905082815260208101848484011115613a0b57613a0a612c71565b5b613a16848285612827565b509392505050565b600082601f830112613a3357613a32612a92565b5b8151613a438482602086016139dc565b91505092915050565b600060208284031215613a6257613a61612746565b5b600082015167ffffffffffffffff811115613a8057613a7f61274b565b5b613a8c84828501613a1e565b91505092915050565b613a9e816128bd565b82525050565b6000602082019050613ab96000830184613a95565b92915050565b7f2261747472696275746573223a205b0000000000000000000000000000000000815250565b7f7b2274726169745f74797065223a20224d6972726f7273222c202276616c756560008201527f223a200000000000000000000000000000000000000000000000000000000000602082015250565b6000613b4160238361327a565b9150613b4c82613ae5565b602382019050919050565b7f7d2c000000000000000000000000000000000000000000000000000000000000815250565b7f7b2274726169745f74797065223a20224f75747369646520417274696661637460008201527f73222c202276616c7565223a2000000000000000000000000000000000000000602082015250565b6000613bd9602d8361327a565b9150613be482613b7d565b602d82019050919050565b7f7b2274726169745f74797065223a2022496e736964652041727469666163747360008201527f222c202276616c7565223a200000000000000000000000000000000000000000602082015250565b6000613c4b602c8361327a565b9150613c5682613bef565b602c82019050919050565b7f7b2274726169745f74797065223a20224772616469656e74222c202276616c7560008201527f65223a2022000000000000000000000000000000000000000000000000000000602082015250565b6000613cbd60258361327a565b9150613cc882613c61565b602582019050919050565b7f227d2c0000000000000000000000000000000000000000000000000000000000815250565b7f7b2274726169745f74797065223a20225072696d61727920436f6c6f72222c2060008201527f2276616c7565223a202200000000000000000000000000000000000000000000602082015250565b6000613d55602a8361327a565b9150613d6082613cf9565b602a82019050919050565b7f227d000000000000000000000000000000000000000000000000000000000000815250565b6000613d9c82613abf565b600f82019150613dab82613b34565b9150613db782886132d1565b9150613dc282613b57565b600282019150613dd182613bcc565b9150613ddd82876132d1565b9150613de882613b57565b600282019150613df782613c3e565b9150613e0382866132d1565b9150613e0e82613b57565b600282019150613e1d82613cb0565b9150613e2982856132d1565b9150613e3482613cd3565b600382019150613e4382613d48565b9150613e4f82846132d1565b9150613e5a82613d6b565b6002820191508190509695505050505050565b7f2c7b2274726169745f74797065223a20225365636f6e6461727920436f6c6f7260008201527f222c202276616c7565223a202200000000000000000000000000000000000000602082015250565b6000613ec9602d8361327a565b9150613ed482613e6d565b602d82019050919050565b6000613eeb82856132d1565b9150613ef682613ebc565b9150613f0282846132d1565b9150613f0d82613d6b565b6002820191508190509392505050565b7f2c7b2274726169745f74797065223a202248616c6f222c202276616c7565223a60008201527f2022596573227d00000000000000000000000000000000000000000000000000602082015250565b6000613f7960278361327a565b9150613f8482613f1d565b602782019050919050565b6000613f9b82846132d1565b9150613fa682613f6c565b915081905092915050565b7f5d00000000000000000000000000000000000000000000000000000000000000815250565b6000613fe382846132d1565b9150613fee82613fb1565b60018201915081905092915050565b7f7b226e616d65223a220000000000000000000000000000000000000000000000600082015250565b600061403360098361327a565b915061403e82613ffd565b600982019050919050565b7f222c226465736372697074696f6e223a22000000000000000000000000000000600082015250565b600061407f60118361327a565b915061408a82614049565b601182019050919050565b7f222c000000000000000000000000000000000000000000000000000000000000600082015250565b60006140cb60028361327a565b91506140d682614095565b600282019050919050565b7f2c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b6260008201527f61736536342c0000000000000000000000000000000000000000000000000000602082015250565b600061413d60268361327a565b9150614148826140e1565b602682019050919050565b7f227d000000000000000000000000000000000000000000000000000000000000600082015250565b600061418960028361327a565b915061419482614153565b600282019050919050565b60006141aa82614026565b91506141b682876132d1565b91506141c182614072565b91506141cd82866132d1565b91506141d8826140be565b91506141e482856132d1565b91506141ef82614130565b91506141fb82846132d1565b91506142068261417c565b915081905095945050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b600061424a601d8361327a565b915061425582614214565b601d82019050919050565b600061426b8261423d565b915061427782846132d1565b915081905092915050565b7f5075626c69632073616c6520686173206e6f7420737461727465642079657400600082015250565b60006142b8601f83612816565b91506142c382614282565b602082019050919050565b600060208201905081810360008301526142e7816142ab565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061434a602683612816565b9150614355826142ee565b604082019050919050565b600060208201905081810360008301526143798161433d565b9050919050565b7f596f7520617265206e6f74206f6e2074686520616c6c6f776c69737400000000600082015250565b60006143b6601c83612816565b91506143c182614380565b602082019050919050565b600060208201905081810360008301526143e5816143a9565b9050919050565b7f416c6c6f776c6973742073616c6520686173206e6f742073746172746564207960008201527f6574000000000000000000000000000000000000000000000000000000000000602082015250565b6000614448602283612816565b9150614453826143ec565b604082019050919050565b600060208201905081810360008301526144778161443b565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006144b4602083612816565b91506144bf8261447e565b602082019050919050565b600060208201905081810360008301526144e3816144a7565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000614511826144ea565b61451b81856144f5565b935061452b818560208601612827565b61453481612851565b840191505092915050565b60006080820190506145546000830187612952565b6145616020830186612952565b61456e6040830185612a15565b81810360608301526145808184614506565b905095945050505050565b60008151905061459a8161277c565b92915050565b6000602082840312156145b6576145b5612746565b5b60006145c48482850161458b565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614607826128bd565b9150614612836128bd565b925082614622576146216145cd565b5b828204905092915050565b600060ff82169050919050565b60006146458261462d565b91506146508361462d565b9250828201905060ff81111561466957614668613043565b5b92915050565b7f496e73756666696369656e742066656500000000000000000000000000000000600082015250565b60006146a5601083612816565b91506146b08261466f565b602082019050919050565b600060208201905081810360008301526146d481614698565b9050919050565b7f45786365656473206d6178207175616e74697479000000000000000000000000600082015250565b6000614711601483612816565b915061471c826146db565b602082019050919050565b6000602082019050818103600083015261474081614704565b9050919050565b600081905092915050565b50565b6000614762600083614747565b915061476d82614752565b600082019050919050565b600061478382614755565b9150819050919050565b7f526566756e64206661696c656400000000000000000000000000000000000000600082015250565b60006147c3600d83612816565b91506147ce8261478d565b602082019050919050565b600060208201905081810360008301526147f2816147b6565b905091905056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f46756c6c79206f6e2d636861696e2c2070726f6365647572616c6c792067656e6572617465642c20616e696d61746564206b616c6569646f73636f7065732ea264697066735822122052abef236944e932101b30fe89aa13017f608c9ba9c850189986d5776b62cea064736f6c63430008100033

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

00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000003e81a803dbdfb3d0c0c775bc03f7e858f42eac3ccf7aae62a18b498e8dcced2b2240000000000000000000000000000000000000000000000000000000000fa3afc000000000000000000000000000000000000000000000000000000000000012c000000000000000000000000834a227ec86776292601d298de4a767677950a55000000000000000000000000000000000000000000000000000000000000000d4b616c6569646f73636f7065730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064b4c445343500000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): Kaleidoscopes
Arg [1] : _symbol (string): KLDSCP
Arg [2] : _price (uint256): 10000000000000000
Arg [3] : _maxSupply (uint256): 1000
Arg [4] : _merkleRoot (bytes32): 0x1a803dbdfb3d0c0c775bc03f7e858f42eac3ccf7aae62a18b498e8dcced2b224
Arg [5] : _allowListMintStartBlock (uint256): 16399100
Arg [6] : _publicMintOffsetBlocks (uint256): 300
Arg [7] : _renderer (address): 0x834A227Ec86776292601D298DE4a767677950a55

-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [2] : 000000000000000000000000000000000000000000000000002386f26fc10000
Arg [3] : 00000000000000000000000000000000000000000000000000000000000003e8
Arg [4] : 1a803dbdfb3d0c0c775bc03f7e858f42eac3ccf7aae62a18b498e8dcced2b224
Arg [5] : 0000000000000000000000000000000000000000000000000000000000fa3afc
Arg [6] : 000000000000000000000000000000000000000000000000000000000000012c
Arg [7] : 000000000000000000000000834a227ec86776292601d298de4a767677950a55
Arg [8] : 000000000000000000000000000000000000000000000000000000000000000d
Arg [9] : 4b616c6569646f73636f70657300000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [11] : 4b4c445343500000000000000000000000000000000000000000000000000000


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

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