ETH Price: $3,411.42 (+1.69%)

Contract

0x000000000001A36777f9930aAEFf623771b13e70
 

Overview

ETH Balance

0.049395 ETH

Eth Value

$168.51 (@ $3,411.42/ETH)

Multichain Info

Transaction Hash
Method
Block
From
To
Mint To211912762024-11-15 6:22:2342 days ago1731651743IN
0x00000000...771b13e70
0.000777 ETH0.0030201415.53915085
Mint To211912702024-11-15 6:21:1142 days ago1731651671IN
0x00000000...771b13e70
0.000777 ETH0.0032786216.8690748
Mint To211912472024-11-15 6:16:2342 days ago1731651383IN
0x00000000...771b13e70
0.000777 ETH0.0029952315.41097836
Mint To211453172024-11-08 20:29:1148 days ago1731097751IN
0x00000000...771b13e70
0.000777 ETH0.0004915217.75157794
Mint To211451802024-11-08 20:01:3548 days ago1731096095IN
0x00000000...771b13e70
0.000777 ETH0.000495817.90603694
Mint To211053042024-11-03 6:25:1154 days ago1730615111IN
0x00000000...771b13e70
0.020777 ETH0.001074574.99420949
Mint To208481832024-09-28 9:17:3590 days ago1727515055IN
0x00000000...771b13e70
0.000777 ETH0.0018626410.50817612
Mint To208303622024-09-25 21:40:1192 days ago1727300411IN
0x00000000...771b13e70
0.008477 ETH0.0032795618.11893851
Mint To207650162024-09-16 18:38:59101 days ago1726511939IN
0x00000000...771b13e70
0.003108 ETH0.00097854.74373142
Mint To206540622024-09-01 6:54:59117 days ago1725173699IN
0x00000000...771b13e70
0.000777 ETH0.000016340.59043795
Mint To206386072024-08-30 3:08:11119 days ago1724987291IN
0x00000000...771b13e70
0.000777 ETH0.000022750.82179214
Mint To206163152024-08-27 0:22:47122 days ago1724718167IN
0x00000000...771b13e70
0.000777 ETH0.000126610.7143291
Mint To205881532024-08-23 1:53:47126 days ago1724378027IN
0x00000000...771b13e70
0.003777 ETH0.000182461.00810337
Mint To205562592024-08-18 14:57:59130 days ago1723993079IN
0x00000000...771b13e70
0.001554 ETH0.000182581.12345981
Mint To205562482024-08-18 14:55:47130 days ago1723992947IN
0x00000000...771b13e70
0.008477 ETH0.000245221.14020952
Mint To205286532024-08-14 18:26:59134 days ago1723660019IN
0x00000000...771b13e70
0.000777 ETH0.000998525.63319733
Mint To205161242024-08-13 0:28:47136 days ago1723508927IN
0x00000000...771b13e70
0.000777 ETH0.000345041.94658683
Mint To205086852024-08-11 23:34:23137 days ago1723419263IN
0x00000000...771b13e70
0.000777 ETH0.000023210.83839352
Mint To205086772024-08-11 23:32:47137 days ago1723419167IN
0x00000000...771b13e70
0.000777 ETH0.000023930.86436011
Mint To204868852024-08-08 22:33:23140 days ago1723156403IN
0x00000000...771b13e70
0.000777 ETH0.00087884.95781096
Mint To204748762024-08-07 6:22:59142 days ago1723011779IN
0x00000000...771b13e70
0.000777 ETH0.000438012.47108273
Mint To204712142024-08-06 18:07:11142 days ago1722967631IN
0x00000000...771b13e70
0.000777 ETH0.00076193.91405712
Mint To204698232024-08-06 13:26:59142 days ago1722950819IN
0x00000000...771b13e70
0.000777 ETH0.001194216.14445326
Mint To204659002024-08-06 0:18:47143 days ago1722903527IN
0x00000000...771b13e70
0.003777 ETH0.00088434.88561056
Mint To204585942024-08-04 23:51:23144 days ago1722815483IN
0x00000000...771b13e70
0.000777 ETH0.00029851.68403662
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
211912762024-11-15 6:22:2342 days ago1731651743
0x00000000...771b13e70
0.000555 ETH
211912702024-11-15 6:21:1142 days ago1731651671
0x00000000...771b13e70
0.000555 ETH
211912472024-11-15 6:16:2342 days ago1731651383
0x00000000...771b13e70
0.000555 ETH
211053042024-11-03 6:25:1154 days ago1730615111
0x00000000...771b13e70
0.020222 ETH
208481832024-09-28 9:17:3590 days ago1727515055
0x00000000...771b13e70
0.000555 ETH
208303622024-09-25 21:40:1192 days ago1727300411
0x00000000...771b13e70
0.007922 ETH
207650162024-09-16 18:38:59101 days ago1726511939
0x00000000...771b13e70
0.00222 ETH
206163152024-08-27 0:22:47122 days ago1724718167
0x00000000...771b13e70
0.000555 ETH
205881532024-08-23 1:53:47126 days ago1724378027
0x00000000...771b13e70
0.003222 ETH
205562592024-08-18 14:57:59130 days ago1723993079
0x00000000...771b13e70
0.00111 ETH
205562482024-08-18 14:55:47130 days ago1723992947
0x00000000...771b13e70
0.007922 ETH
205286532024-08-14 18:26:59134 days ago1723660019
0x00000000...771b13e70
0.000555 ETH
205161242024-08-13 0:28:47136 days ago1723508927
0x00000000...771b13e70
0.000555 ETH
204868852024-08-08 22:33:23140 days ago1723156403
0x00000000...771b13e70
0.000555 ETH
204799142024-08-07 23:14:23141 days ago1723072463
0x00000000...771b13e70
0.000777 ETH
204748762024-08-07 6:22:59142 days ago1723011779
0x00000000...771b13e70
0.000555 ETH
204712142024-08-06 18:07:11142 days ago1722967631
0x00000000...771b13e70
0.000555 ETH
204698232024-08-06 13:26:59142 days ago1722950819
0x00000000...771b13e70
0.000555 ETH
204659002024-08-06 0:18:47143 days ago1722903527
0x00000000...771b13e70
0.003222 ETH
204585942024-08-04 23:51:23144 days ago1722815483
0x00000000...771b13e70
0.000555 ETH
204577532024-08-04 21:02:47144 days ago1722805367
0x00000000...771b13e70
0.000555 ETH
204413232024-08-02 14:01:35146 days ago1722607295
0x00000000...771b13e70
0.003222 ETH
204363792024-08-01 21:27:23147 days ago1722547643
0x00000000...771b13e70
0.000555 ETH
204363502024-08-01 21:21:35147 days ago1722547295
0x00000000...771b13e70
0.003222 ETH
204363412024-08-01 21:19:47147 days ago1722547187
0x00000000...771b13e70
0.003222 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SuperMinterV2

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion, MIT license
File 1 of 21 : SuperMinterV2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import { Ownable, OwnableRoles } from "solady/auth/OwnableRoles.sol";
import { ISoundEditionV2_1 } from "@core/interfaces/ISoundEditionV2_1.sol";
import { ISuperMinterV2 } from "@modules/interfaces/ISuperMinterV2.sol";
import { IERC165 } from "openzeppelin/utils/introspection/IERC165.sol";
import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol";
import { EIP712 } from "solady/utils/EIP712.sol";
import { MerkleProofLib } from "solady/utils/MerkleProofLib.sol";
import { LibBitmap } from "solady/utils/LibBitmap.sol";
import { SignatureCheckerLib } from "solady/utils/SignatureCheckerLib.sol";
import { LibZip } from "solady/utils/LibZip.sol";
import { LibMap } from "solady/utils/LibMap.sol";
import { DelegateCashLib } from "@modules/utils/DelegateCashLib.sol";
import { LibOps } from "@core/utils/LibOps.sol";
import { LibMulticaller } from "multicaller/LibMulticaller.sol";

/**
 * @title SuperMinterV2
 * @dev The `SuperMinterV2` class is a generalized minter.
 */
contract SuperMinterV2 is ISuperMinterV2, EIP712 {
    using LibBitmap for *;
    using MerkleProofLib for *;
    using LibMap for *;

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

    /**
     * @dev A struct to hold the mint data in storage.
     */
    struct MintData {
        // The platform address.
        address platform;
        // The price per token.
        uint96 price;
        // The start time of the mint.
        uint32 startTime;
        // The end time of the mint.
        uint32 endTime;
        // The maximum number of tokens an account can mint in this mint.
        uint32 maxMintablePerAccount;
        // The maximum tokens mintable.
        uint32 maxMintable;
        // The total number of tokens minted.
        uint32 minted;
        // The affiliate fee BPS.
        uint16 affiliateFeeBPS;
        // The offset to the next mint data in the linked list.
        uint16 next;
        // The head of the mint data linked list.
        // Only stored in the 0-th mint data per edition.
        uint16 head;
        // The total number of mint data.
        // Only stored in the 0-th mint data per edition.
        uint16 numMintData;
        // The total number of mints for the edition-tier.
        // Only stored in the 0-th mint data per edition-tier.
        uint8 nextScheduleNum;
        // The mode of the mint.
        uint8 mode;
        // The packed boolean flags.
        uint8 flags;
        // The affiliate Merkle root, if any.
        bytes32 affiliateMerkleRoot;
        // The Merkle root hash, required if `mode` is `VERIFY_MERKLE`.
        bytes32 merkleRoot;
    }

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

    /**
     * @dev The GA tier. Which is 0.
     */
    uint8 public constant GA_TIER = 0;

    /**
     * @dev For EIP-712 signature digest calculation.
     */
    bytes32 public constant MINT_TO_TYPEHASH =
        // prettier-ignore
        keccak256(
            "MintTo("
                "address edition,"
                "uint8 tier,"
                "uint8 scheduleNum,"
                "address to,"
                "uint32 signedQuantity,"
                "uint32 signedClaimTicket,"
                "uint96 signedPrice,"
                "uint32 signedDeadline,"
                "address affiliate"
            ")"
        );

    /**
     * @dev For EIP-712 platform airdrop signature digest calculation.
     */
    bytes32 public constant PLATFORM_AIRDROP_TYPEHASH =
        // prettier-ignore
        keccak256(
            "PlatformAirdrop("
                "address edition,"
                "uint8 tier,"
                "uint8 scheduleNum,"
                "address[] to,"
                "uint32 signedQuantity,"
                "uint32 signedClaimTicket,"
                "uint32 signedDeadline"
            ")"
        );

    /**
     * @dev For EIP-712 signature digest calculation.
     */
    bytes32 public constant DOMAIN_TYPEHASH = _DOMAIN_TYPEHASH;

    /**
     * @dev The default value for options.
     */
    uint8 public constant DEFAULT = 0;

    /**
     * @dev The Merkle drop mint mode.
     */
    uint8 public constant VERIFY_MERKLE = 1;

    /**
     * @dev The Signature mint mint mode.
     */
    uint8 public constant VERIFY_SIGNATURE = 2;

    /**
     * @dev The platform airdrop mint mode.
     */
    uint8 public constant PLATFORM_AIRDROP = 3;

    /**
     * @dev The denominator of all BPS calculations.
     */
    uint16 public constant BPS_DENOMINATOR = LibOps.BPS_DENOMINATOR;

    /**
     * @dev The maximum affiliate fee BPS.
     */
    uint16 public constant MAX_AFFILIATE_FEE_BPS = 1000;

    /**
     * @dev The maximum platform per-mint fee BPS.
     */
    uint16 public constant MAX_PLATFORM_PER_MINT_FEE_BPS = 1000;

    /**
     * @dev The maximum per-mint reward. Applies to artists, affiliates, platform.
     */
    uint96 public constant MAX_PER_MINT_REWARD = 0.1 ether;

    /**
     * @dev The maximum platform per-transaction flat fee.
     */
    uint96 public constant MAX_PLATFORM_PER_TX_FLAT_FEE = 0.1 ether;

    /**
     * @dev The boolean flag on whether the mint has been created.
     */
    uint8 internal constant _MINT_CREATED_FLAG = 1 << 0;

    /**
     * @dev The boolean flag on whether the mint is paused.
     */
    uint8 internal constant _MINT_PAUSED_FLAG = 1 << 1;

    /**
     * @dev The boolean flag on whether the signer is the platform's signer.
     */
    uint8 internal constant _USE_PLATFORM_SIGNER_FLAG = 1 << 2;

    /**
     * @dev The index for the per-platform default fee config.
     *      We use 256, as the tier is uint8, which ranges from 0 to 255.
     */
    uint16 internal constant _DEFAULT_FEE_CONFIG_INDEX = 256;

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

    /**
     * @dev A mapping of `platform` => `feesAccrued`.
     */
    mapping(address => uint256) public platformFeesAccrued;

    /**
     * @dev A mapping of `platform` => `feeRecipient`.
     */
    mapping(address => address) public platformFeeAddress;

    /**
     * @dev A mapping of `affiliate` => `feesAccrued`.
     */
    mapping(address => uint256) public affiliateFeesAccrued;

    /**
     * @dev A mapping of `platform` => `price`.
     */
    mapping(address => uint96) public gaPrice;

    /**
     * @dev A mapping of `platform` => `platformSigner`.
     */
    mapping(address => address) public platformSigner;

    /**
     * @dev A mapping of `mintId` => `mintData`.
     */
    mapping(uint256 => MintData) internal _mintData;

    /**
     * @dev A mapping of `platformTierId` => `platformFeeConfig`.
     */
    mapping(uint256 => PlatformFeeConfig) internal _platformFeeConfigs;

    /**
     * @dev A mapping of `to` => `mintId` => `numberMinted`.
     */
    mapping(address => LibMap.Uint32Map) internal _numberMinted;

    /**
     * @dev A mapping of `mintId` => `signedClaimedTicket` => `claimed`.
     */
    mapping(uint256 => LibBitmap.Bitmap) internal _claimsBitmaps;

    // =============================================================
    //               PUBLIC / EXTERNAL WRITE FUNCTIONS
    // =============================================================

    /**
     * @inheritdoc ISuperMinterV2
     */
    function createEditionMint(MintCreation memory c) public returns (uint8 scheduleNum) {
        _requireOnlyEditionOwnerOrAdmin(c.edition);

        _validateAffiliateFeeBPS(c.affiliateFeeBPS);

        uint8 mode = c.mode;

        if (mode == DEFAULT) {
            c.merkleRoot = bytes32(0);
        } else if (mode == VERIFY_MERKLE) {
            _validateMerkleRoot(c.merkleRoot);
        } else if (mode == VERIFY_SIGNATURE) {
            c.merkleRoot = bytes32(0);
            c.maxMintablePerAccount = type(uint32).max;
        } else if (mode == PLATFORM_AIRDROP) {
            c.merkleRoot = bytes32(0);
            c.maxMintablePerAccount = type(uint32).max;
            c.price = 0; // Platform airdrop mode doesn't have a price.
        } else {
            revert InvalidMode();
        }

        // If GA, overwrite any immutable variables as required.
        if (c.tier == GA_TIER) {
            c.endTime = type(uint32).max;
            c.maxMintablePerAccount = type(uint32).max;
            // We allow the `price` to be the minimum price if the `mode` is `VERIFY_SIGNATURE`.
            // Otherwise, the actual default price is the live value of `gaPrice[platform]`,
            // and we'll simply set it to zero to avoid a SLOAD.
            if (mode != VERIFY_SIGNATURE) c.price = 0;
            // Set `maxMintable` to the maximum only if `mode` is `DEFAULT`.
            if (mode == DEFAULT) c.maxMintable = type(uint32).max;
        }

        _validateTimeRange(c.startTime, c.endTime);
        _validateMaxMintablePerAccount(c.maxMintablePerAccount);
        _validateMaxMintable(c.maxMintable);

        unchecked {
            MintData storage tierHead = _mintData[LibOps.packId(c.edition, c.tier, 0)];
            MintData storage editionHead = _mintData[LibOps.packId(c.edition, 0)];

            scheduleNum = tierHead.nextScheduleNum;
            uint256 n = scheduleNum;
            if (++n >= 1 << 8) LibOps.revertOverflow();
            tierHead.nextScheduleNum = uint8(n);

            n = editionHead.numMintData;
            if (++n >= 1 << 16) LibOps.revertOverflow();
            editionHead.numMintData = uint16(n);

            uint256 mintId = LibOps.packId(c.edition, c.tier, scheduleNum);

            MintData storage d = _mintData[mintId];
            d.platform = c.platform;
            d.price = c.price;
            d.startTime = c.startTime;
            d.endTime = c.endTime;
            d.maxMintablePerAccount = c.maxMintablePerAccount;
            d.maxMintable = c.maxMintable;
            d.affiliateFeeBPS = c.affiliateFeeBPS;
            d.mode = c.mode;
            d.flags = _MINT_CREATED_FLAG;
            d.next = editionHead.head;
            editionHead.head = uint16((uint256(c.tier) << 8) | uint256(scheduleNum));

            // Skip writing zeros, to avoid cold SSTOREs.
            if (c.affiliateMerkleRoot != bytes32(0)) d.affiliateMerkleRoot = c.affiliateMerkleRoot;
            if (c.merkleRoot != bytes32(0)) d.merkleRoot = c.merkleRoot;

            emit MintCreated(c.edition, c.tier, scheduleNum, c);
        }
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function mintTo(MintTo calldata p) public payable returns (uint256 fromTokenId) {
        MintData storage d = _getMintData(LibOps.packId(p.edition, p.tier, p.scheduleNum));

        /* ------------------- CHECKS AND UPDATES ------------------- */

        _requireMintOpen(d);

        // Perform the sub workflows depending on the mint mode.
        uint8 mode = d.mode;
        if (mode == VERIFY_MERKLE) _verifyMerkle(d, p);
        else if (mode == VERIFY_SIGNATURE) _verifyAndClaimSignature(d, p);
        else if (mode == PLATFORM_AIRDROP) revert InvalidMode();

        _incrementMinted(mode, d, p);

        /* ----------------- COMPUTE AND ACCRUE FEES ---------------- */

        MintedLogData memory l;
        // Blocking same address self referral is left curved, but we do anyway.
        l.affiliate = p.to == p.affiliate ? address(0) : p.affiliate;
        // Affiliate check.
        l.affiliated = _isAffiliatedWithProof(d, l.affiliate, p.affiliateProof);

        TotalPriceAndFees memory f = _totalPriceAndFees(p.tier, d, p.quantity, p.signedPrice, l.affiliated);

        if (msg.value != f.total) revert WrongPayment(msg.value, f.total); // Require exact payment.

        l.finalArtistFee = f.finalArtistFee;
        l.finalPlatformFee = f.finalPlatformFee;
        l.finalAffiliateFee = f.finalAffiliateFee;

        // Platform and affilaite fees are accrued mappings.
        // Artist earnings are directly forwarded to the nft contract in mint call below.
        // Overflow not possible since all fees are uint96s.
        unchecked {
            if (l.finalAffiliateFee != 0) {
                affiliateFeesAccrued[p.affiliate] += l.finalAffiliateFee;
            }
            if (l.finalPlatformFee != 0) {
                platformFeesAccrued[d.platform] += l.finalPlatformFee;
            }
        }

        /* ------------------------- MINT --------------------------- */

        ISoundEditionV2_1 edition = ISoundEditionV2_1(p.edition);
        l.quantity = p.quantity;
        l.fromTokenId = edition.mint{ value: l.finalArtistFee }(p.tier, p.to, p.quantity);
        l.allowlisted = p.allowlisted;
        l.allowlistedQuantity = p.allowlistedQuantity;
        l.signedClaimTicket = p.signedClaimTicket;
        l.requiredEtherValue = f.total;
        l.unitPrice = f.unitPrice;

        emit Minted(p.edition, p.tier, p.scheduleNum, p.to, l, p.attributionId);

        return l.fromTokenId;
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function platformAirdrop(PlatformAirdrop calldata p) public returns (uint256 fromTokenId) {
        MintData storage d = _getMintData(LibOps.packId(p.edition, p.tier, p.scheduleNum));

        /* ------------------- CHECKS AND UPDATES ------------------- */

        _requireMintOpen(d);

        if (d.mode != PLATFORM_AIRDROP) revert InvalidMode();
        _verifyAndClaimPlatfromAidropSignature(d, p);

        _incrementPlatformAirdropMinted(d, p);

        /* ------------------------- MINT --------------------------- */

        ISoundEditionV2_1 edition = ISoundEditionV2_1(p.edition);
        fromTokenId = edition.airdrop(p.tier, p.to, p.signedQuantity);

        emit PlatformAirdropped(p.edition, p.tier, p.scheduleNum, p.to, p.signedQuantity, fromTokenId);
    }

    // Per edition mint parameter setters:
    // -----------------------------------
    // These functions can only be called by the owner or admin of the edition.

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setPrice(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint96 price
    ) public onlyEditionOwnerOrAdmin(edition) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        MintData storage d = _getMintData(mintId);
        // If the tier is GA and the `mode` is `VERIFY_SIGNATURE`, we'll use `gaPrice[platform]`.
        if (tier == GA_TIER && d.mode != VERIFY_SIGNATURE) revert NotConfigurable();
        // Platform airdropped mints will not have a price.
        if (d.mode == PLATFORM_AIRDROP) revert NotConfigurable();
        d.price = price;
        emit PriceSet(edition, tier, scheduleNum, price);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setPaused(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        bool paused
    ) public onlyEditionOwnerOrAdmin(edition) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        MintData storage d = _getMintData(mintId);
        d.flags = LibOps.setFlagTo(d.flags, _MINT_PAUSED_FLAG, paused);
        emit PausedSet(edition, tier, scheduleNum, paused);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setTimeRange(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32 startTime,
        uint32 endTime
    ) public onlyEditionOwnerOrAdmin(edition) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        MintData storage d = _getMintData(mintId);
        // For GA tier, `endTime` will always be `type(uint32).max`.
        if (tier == GA_TIER && endTime != type(uint32).max) revert NotConfigurable();
        _validateTimeRange(startTime, endTime);
        d.startTime = startTime;
        d.endTime = endTime;
        emit TimeRangeSet(edition, tier, scheduleNum, startTime, endTime);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setStartTime(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32 startTime
    ) public {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        setTimeRange(edition, tier, scheduleNum, startTime, _mintData[mintId].endTime);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setAffiliateFee(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint16 bps
    ) public onlyEditionOwnerOrAdmin(edition) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        MintData storage d = _getMintData(mintId);
        _validateAffiliateFeeBPS(bps);
        d.affiliateFeeBPS = bps;
        emit AffiliateFeeSet(edition, tier, scheduleNum, bps);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setAffiliateMerkleRoot(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        bytes32 root
    ) public onlyEditionOwnerOrAdmin(edition) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        MintData storage d = _getMintData(mintId);
        d.affiliateMerkleRoot = root;
        emit AffiliateMerkleRootSet(edition, tier, scheduleNum, root);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setMaxMintablePerAccount(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32 value
    ) public onlyEditionOwnerOrAdmin(edition) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        MintData storage d = _getMintData(mintId);
        // GA tier will have `type(uint32).max`.
        if (tier == GA_TIER) revert NotConfigurable();
        // Signature mints will have `type(uint32).max`.
        if (d.mode == VERIFY_SIGNATURE) revert NotConfigurable();
        // Platform airdrops will have `type(uint32).max`.
        if (d.mode == PLATFORM_AIRDROP) revert NotConfigurable();
        _validateMaxMintablePerAccount(value);
        d.maxMintablePerAccount = value;
        emit MaxMintablePerAccountSet(edition, tier, scheduleNum, value);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setMaxMintable(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32 value
    ) public onlyEditionOwnerOrAdmin(edition) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        MintData storage d = _getMintData(mintId);
        // We allow edits for GA tier, if the `mode` is not `DEFAULT`.
        if (tier == GA_TIER && d.mode == DEFAULT) revert NotConfigurable();
        _validateMaxMintable(value);
        d.maxMintable = value;
        emit MaxMintableSet(edition, tier, scheduleNum, value);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setMerkleRoot(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        bytes32 merkleRoot
    ) public onlyEditionOwnerOrAdmin(edition) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        MintData storage d = _getMintData(mintId);
        if (d.mode != VERIFY_MERKLE) revert NotConfigurable();
        _validateMerkleRoot(merkleRoot);
        d.merkleRoot = merkleRoot;
        emit MerkleRootSet(edition, tier, scheduleNum, merkleRoot);
    }

    // Withdrawal functions:
    // ---------------------
    // These functions can be called by anyone.

    /**
     * @inheritdoc ISuperMinterV2
     */
    function withdrawForAffiliate(address affiliate) public {
        uint256 accrued = affiliateFeesAccrued[affiliate];
        if (accrued != 0) {
            affiliateFeesAccrued[affiliate] = 0;
            SafeTransferLib.forceSafeTransferETH(affiliate, accrued);
            emit AffiliateFeesWithdrawn(affiliate, accrued);
        }
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function withdrawForPlatform(address platform) public {
        address recipient = platformFeeAddress[platform];
        _validatePlatformFeeAddress(recipient);
        uint256 accrued = platformFeesAccrued[platform];
        if (accrued != 0) {
            platformFeesAccrued[platform] = 0;
            SafeTransferLib.forceSafeTransferETH(recipient, accrued);
            emit PlatformFeesWithdrawn(platform, accrued);
        }
    }

    // Platform fee functions:
    // -----------------------
    // These functions enable any caller to set their own platform fees.

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setPlatformFeeAddress(address recipient) public {
        address sender = LibMulticaller.senderOrSigner();
        _validatePlatformFeeAddress(recipient);
        platformFeeAddress[sender] = recipient;
        emit PlatformFeeAddressSet(sender, recipient);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setPlatformFeeConfig(uint8 tier, PlatformFeeConfig memory c) public {
        address sender = LibMulticaller.senderOrSigner();
        _validatePlatformFeeConfig(c);
        _platformFeeConfigs[LibOps.packId(sender, tier)] = c;
        emit PlatformFeeConfigSet(sender, tier, c);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setDefaultPlatformFeeConfig(PlatformFeeConfig memory c) public {
        address sender = LibMulticaller.senderOrSigner();
        _validatePlatformFeeConfig(c);
        _platformFeeConfigs[LibOps.packId(sender, _DEFAULT_FEE_CONFIG_INDEX)] = c;
        emit DefaultPlatformFeeConfigSet(sender, c);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setGAPrice(uint96 price) public {
        address sender = LibMulticaller.senderOrSigner();
        gaPrice[sender] = price;
        emit GAPriceSet(sender, price);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function setPlatformSigner(address signer) public {
        address sender = LibMulticaller.senderOrSigner();
        platformSigner[sender] = signer;
        emit PlatformSignerSet(sender, signer);
    }

    // Misc functions:
    // ---------------

    /**
     * @dev For calldata compression.
     */
    fallback() external payable {
        LibZip.cdFallback();
    }

    /**
     * @dev For calldata compression.
     */
    receive() external payable {
        LibZip.cdFallback();
    }

    // =============================================================
    //               PUBLIC / EXTERNAL VIEW FUNCTIONS
    // =============================================================

    /**
     * @inheritdoc ISuperMinterV2
     */
    function computeMintToDigest(MintTo calldata p) public view returns (bytes32) {
        // prettier-ignore
        return
            _hashTypedData(keccak256(abi.encode(
                MINT_TO_TYPEHASH,
                p.edition,
                p.tier, 
                p.scheduleNum,
                p.to,
                p.signedQuantity,
                p.signedClaimTicket,
                p.signedPrice,
                p.signedDeadline,
                p.affiliate
            )));
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function computePlatformAirdropDigest(PlatformAirdrop calldata p) public view returns (bytes32) {
        // prettier-ignore
        return
            _hashTypedData(keccak256(abi.encode(
                PLATFORM_AIRDROP_TYPEHASH,
                p.edition,
                p.tier, 
                p.scheduleNum,
                keccak256(abi.encodePacked(p.to)),
                p.signedQuantity,
                p.signedClaimTicket,
                p.signedDeadline
            )));
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function totalPriceAndFees(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32 quantity,
        bool hasValidAffiliate
    ) public view returns (TotalPriceAndFees memory) {
        return totalPriceAndFeesWithSignedPrice(edition, tier, scheduleNum, quantity, 0, hasValidAffiliate);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function totalPriceAndFeesWithSignedPrice(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32 quantity,
        uint96 signedPrice,
        bool hasValidAffiliate
    ) public view returns (TotalPriceAndFees memory) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        return _totalPriceAndFees(tier, _getMintData(mintId), quantity, signedPrice, hasValidAffiliate);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function nextScheduleNum(address edition, uint8 tier) public view returns (uint8) {
        return _mintData[LibOps.packId(edition, tier, 0)].nextScheduleNum;
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function numberMinted(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        address collector
    ) external view returns (uint32) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        return _numberMinted[collector].get(mintId);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function isAffiliatedWithProof(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        address affiliate,
        bytes32[] calldata affiliateProof
    ) public view virtual returns (bool) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        return _isAffiliatedWithProof(_getMintData(mintId), affiliate, affiliateProof);
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function isAffiliated(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        address affiliate
    ) public view virtual returns (bool) {
        return isAffiliatedWithProof(edition, tier, scheduleNum, affiliate, MerkleProofLib.emptyProof());
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function checkClaimTickets(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32[] calldata claimTickets
    ) public view returns (bool[] memory claimed) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        LibBitmap.Bitmap storage bitmap = _claimsBitmaps[mintId];
        claimed = new bool[](claimTickets.length);
        unchecked {
            for (uint256 i; i != claimTickets.length; i++) {
                claimed[i] = bitmap.get(claimTickets[i]);
            }
        }
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function platformFeeConfig(address platform, uint8 tier) public view returns (PlatformFeeConfig memory) {
        return _platformFeeConfigs[LibOps.packId(platform, tier)];
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function defaultPlatformFeeConfig(address platform) public view returns (PlatformFeeConfig memory) {
        return _platformFeeConfigs[LibOps.packId(platform, _DEFAULT_FEE_CONFIG_INDEX)];
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function effectivePlatformFeeConfig(address platform, uint8 tier) public view returns (PlatformFeeConfig memory) {
        PlatformFeeConfig memory c = _platformFeeConfigs[LibOps.packId(platform, tier)];
        if (!c.active) c = _platformFeeConfigs[LibOps.packId(platform, _DEFAULT_FEE_CONFIG_INDEX)];
        if (!c.active) delete c; // Set all values to zero.
        return c;
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function mintInfoList(address edition) public view returns (MintInfo[] memory a) {
        unchecked {
            MintData storage editionHead = _mintData[LibOps.packId(edition, 0)];
            uint256 n = editionHead.numMintData; // Linked-list length.
            uint16 p = editionHead.head; // Current linked-list pointer.
            a = new MintInfo[](n);
            // Traverse the linked-list and fill the array in reverse.
            // Front: earliest added mint schedule. Back: latest added mint schedule.
            while (n != 0) {
                MintData storage d = _mintData[LibOps.packId(edition, p)];
                a[--n] = mintInfo(edition, uint8(p >> 8), uint8(p));
                p = d.next;
            }
        }
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function mintInfo(
        address edition,
        uint8 tier,
        uint8 scheduleNum
    ) public view returns (MintInfo memory info) {
        uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
        MintData storage d = _getMintData(mintId);
        info.edition = edition;
        info.tier = tier;
        info.scheduleNum = scheduleNum;
        info.platform = d.platform;
        info.price = tier == GA_TIER && d.mode != VERIFY_SIGNATURE ? gaPrice[d.platform] : d.price;
        info.startTime = d.startTime;
        info.endTime = d.endTime;
        info.maxMintablePerAccount = d.maxMintablePerAccount;
        info.maxMintable = d.maxMintable;
        info.minted = d.minted;
        info.affiliateFeeBPS = d.affiliateFeeBPS;
        info.mode = d.mode;
        info.paused = _isPaused(d);
        info.affiliateMerkleRoot = d.affiliateMerkleRoot;
        info.merkleRoot = d.merkleRoot;
        info.signer = platformSigner[d.platform];
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function name() external pure returns (string memory name_) {
        (name_, ) = _domainNameAndVersion();
    }

    /**
     * @inheritdoc ISuperMinterV2
     */
    function version() external pure returns (string memory version_) {
        (, version_) = _domainNameAndVersion();
    }

    /**
     * @inheritdoc IERC165
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            LibOps.or(interfaceId == type(ISuperMinterV2).interfaceId, interfaceId == this.supportsInterface.selector);
    }

    // =============================================================
    //                  INTERNAL / PRIVATE HELPERS
    // =============================================================

    // Validations:
    // ------------

    /**
     * @dev Guards a function to make it callable only by the edition's owner or admin.
     * @param edition The edition address.
     */
    modifier onlyEditionOwnerOrAdmin(address edition) {
        _requireOnlyEditionOwnerOrAdmin(edition);
        _;
    }

    /**
     * @dev Requires that the caller is the owner or admin of `edition`.
     * @param edition The edition address.
     */
    function _requireOnlyEditionOwnerOrAdmin(address edition) internal view {
        address sender = LibMulticaller.senderOrSigner();
        if (sender != OwnableRoles(edition).owner())
            if (!OwnableRoles(edition).hasAnyRole(sender, LibOps.ADMIN_ROLE)) LibOps.revertUnauthorized();
    }

    /**
     * @dev Validates that `startTime <= endTime`.
     * @param startTime  The start time of the mint.
     * @param endTime    The end time of the mint.
     */
    function _validateTimeRange(uint32 startTime, uint32 endTime) internal pure {
        if (startTime > endTime) revert InvalidTimeRange();
    }

    /**
     * @dev Validates that the max mintable amount per account is not zero.
     * @param value The max mintable amount.
     */
    function _validateMaxMintablePerAccount(uint32 value) internal pure {
        if (value == 0) revert MaxMintablePerAccountIsZero();
    }

    /**
     * @dev Validates that the max mintable per schedule.
     * @param value The max mintable amount.
     */
    function _validateMaxMintable(uint32 value) internal pure {
        if (value == 0) revert MaxMintableIsZero();
    }

    /**
     * @dev Validates that the Merkle root is not empty.
     * @param merkleRoot The Merkle root.
     */
    function _validateMerkleRoot(bytes32 merkleRoot) internal pure {
        if (merkleRoot == bytes32(0)) revert MerkleRootIsEmpty();
    }

    /**
     * @dev Validates that the affiliate fee BPS does not exceed the max threshold.
     * @param bps The affiliate fee BPS.
     */
    function _validateAffiliateFeeBPS(uint16 bps) internal pure {
        if (bps > MAX_AFFILIATE_FEE_BPS) revert InvalidAffiliateFeeBPS();
    }

    /**
     * @dev Validates the platform fee configuration.
     * @param c The platform fee configuration.
     */
    function _validatePlatformFeeConfig(PlatformFeeConfig memory c) internal pure {
        if (
            LibOps.or(
                LibOps.or(
                    c.platformTxFlatFee > MAX_PLATFORM_PER_TX_FLAT_FEE,
                    c.platformMintFeeBPS > MAX_PLATFORM_PER_MINT_FEE_BPS
                ),
                LibOps.or(
                    c.artistMintReward > MAX_PER_MINT_REWARD,
                    c.affiliateMintReward > MAX_PER_MINT_REWARD,
                    c.platformMintReward > MAX_PER_MINT_REWARD
                ),
                LibOps.or(
                    c.thresholdArtistMintReward > MAX_PER_MINT_REWARD,
                    c.thresholdAffiliateMintReward > MAX_PER_MINT_REWARD,
                    c.thresholdPlatformMintReward > MAX_PER_MINT_REWARD
                )
            )
        ) revert InvalidPlatformFeeConfig();
    }

    /**
     * @dev Validates that the platform fee address is not the zero address.
     * @param a The platform fee address.
     */
    function _validatePlatformFeeAddress(address a) internal pure {
        if (a == address(0)) revert PlatformFeeAddressIsZero();
    }

    // EIP-712:
    // --------

    /**
     * @dev Override for EIP-712.
     * @return name_    The EIP-712 name.
     * @return version_ The EIP-712 version.
     */
    function _domainNameAndVersion()
        internal
        pure
        virtual
        override
        returns (string memory name_, string memory version_)
    {
        name_ = "SuperMinter";
        version_ = "1_1";
    }

    // Minting:
    // --------

    /**
     * @dev Increments the number minted in the mint and the number minted by the collector.
     * @param mode The mint mode.
     * @param d    The mint data storage pointer.
     * @param p    The mint-to parameters.
     */
    function _incrementMinted(
        uint8 mode,
        MintData storage d,
        MintTo calldata p
    ) internal {
        unchecked {
            // Increment the number minted in the mint.
            uint256 n = uint256(d.minted) + uint256(p.quantity); // The next `minted`.
            if (n > d.maxMintable) revert ExceedsMintSupply();
            d.minted = uint32(n);

            // Increment the number minted by the collector.
            uint256 mintId = LibOps.packId(p.edition, p.tier, p.scheduleNum);
            if (mode == VERIFY_MERKLE) {
                LibMap.Uint32Map storage m = _numberMinted[p.allowlisted];
                n = uint256(m.get(mintId)) + uint256(p.quantity);
                // Check that `n` does not exceed either the default limit,
                // or the limit in the Merkle leaf if a non-zero value is provided.
                if (LibOps.or(n > d.maxMintablePerAccount, n > p.allowlistedQuantity)) revert ExceedsMaxPerAccount();
                m.set(mintId, uint32(n));
            } else {
                LibMap.Uint32Map storage m = _numberMinted[p.to];
                n = uint256(m.get(mintId)) + uint256(p.quantity);
                if (n > d.maxMintablePerAccount) revert ExceedsMaxPerAccount();
                m.set(mintId, uint32(n));
            }
        }
    }

    /**
     * @dev Increments the number minted in the mint and the number minted by the collector.
     * @param d    The mint data storage pointer.
     * @param p    The platform airdrop parameters.
     */
    function _incrementPlatformAirdropMinted(MintData storage d, PlatformAirdrop calldata p) internal {
        unchecked {
            uint256 mintId = LibOps.packId(p.edition, p.tier, p.scheduleNum);
            uint256 toLength = p.to.length;

            // Increment the number minted in the mint.
            uint256 n = uint256(d.minted) + toLength * uint256(p.signedQuantity); // The next `minted`.
            if (n > d.maxMintable) revert ExceedsMintSupply();
            d.minted = uint32(n);

            // Increment the number minted by the collectors.
            for (uint256 i; i != toLength; ++i) {
                LibMap.Uint32Map storage m = _numberMinted[p.to[i]];
                m.set(mintId, uint32(uint256(m.get(mintId)) + uint256(p.signedQuantity)));
            }
        }
    }

    /**
     * @dev Requires that the mint is open and not paused.
     * @param d    The mint data storage pointer.
     */
    function _requireMintOpen(MintData storage d) internal view {
        if (LibOps.or(block.timestamp < d.startTime, block.timestamp > d.endTime))
            revert MintNotOpen(block.timestamp, d.startTime, d.endTime);
        if (_isPaused(d)) revert MintPaused(); // Check if the mint is not paused.
    }

    /**
     * @dev Verify the signature, and mark the signed claim ticket as claimed.
     * @param d The mint data storage pointer.
     * @param p The mint-to parameters.
     */
    function _verifyAndClaimSignature(MintData storage d, MintTo calldata p) internal {
        if (p.quantity > p.signedQuantity) revert ExceedsSignedQuantity();
        address signer = platformSigner[d.platform];
        if (!SignatureCheckerLib.isValidSignatureNowCalldata(signer, computeMintToDigest(p), p.signature))
            revert InvalidSignature();
        if (block.timestamp > p.signedDeadline) revert SignatureExpired();
        uint256 mintId = LibOps.packId(p.edition, p.tier, p.scheduleNum);
        if (!_claimsBitmaps[mintId].toggle(p.signedClaimTicket)) revert SignatureAlreadyUsed();
    }

    /**
     * @dev Verify the platform airdrop signature, and mark the signed claim ticket as claimed.
     * @param d The mint data storage pointer.
     * @param p The platform airdrop parameters.
     */
    function _verifyAndClaimPlatfromAidropSignature(MintData storage d, PlatformAirdrop calldata p) internal {
        // Unlike regular signature mints, platform airdrops only use `signedQuantity`.
        address signer = platformSigner[d.platform];
        if (!SignatureCheckerLib.isValidSignatureNowCalldata(signer, computePlatformAirdropDigest(p), p.signature))
            revert InvalidSignature();
        if (block.timestamp > p.signedDeadline) revert SignatureExpired();
        uint256 mintId = LibOps.packId(p.edition, p.tier, p.scheduleNum);
        if (!_claimsBitmaps[mintId].toggle(p.signedClaimTicket)) revert SignatureAlreadyUsed();
    }

    /**
     * @dev Verify the Merkle proof.
     * @param d The mint data storage pointer.
     * @param p The mint-to parameters.
     */
    function _verifyMerkle(MintData storage d, MintTo calldata p) internal view {
        uint32 allowlistedQuantity = p.allowlistedQuantity;
        address allowlisted = p.allowlisted;
        // Revert if `allowlisted` is the zero address to prevent libraries
        // that fill up partial Merkle trees with empty leafs from screwing things up.
        if (allowlisted == address(0)) revert InvalidMerkleProof();
        // If `allowlistedQuantity` is the max limit, we've got to check two cases for backwards compatibility.
        if (allowlistedQuantity == type(uint32).max) {
            // Revert if neither `keccak256(abi.encodePacked(allowlisted))` nor
            // `keccak256(abi.encodePacked(allowlisted, uint32(0)))` are in the Merkle tree.
            if (
                !p.allowlistProof.verifyCalldata(d.merkleRoot, _leaf(allowlisted)) &&
                !p.allowlistProof.verifyCalldata(d.merkleRoot, _leaf(allowlisted, type(uint32).max))
            ) revert InvalidMerkleProof();
        } else {
            // Revert if `keccak256(abi.encodePacked(allowlisted, uint32(allowlistedQuantity)))`
            // is not in the Merkle tree.
            if (!p.allowlistProof.verifyCalldata(d.merkleRoot, _leaf(allowlisted, allowlistedQuantity)))
                revert InvalidMerkleProof();
        }
        // To mint, either the sender or `to` must be equal to `allowlisted`,
        address sender = LibMulticaller.senderOrSigner();
        if (!LibOps.or(sender == allowlisted, p.to == allowlisted)) {
            // or the sender must be a delegate of `allowlisted`.
            if (!DelegateCashLib.checkDelegateForAll(sender, allowlisted)) revert CallerNotDelegated();
        }
    }

    /**
     * @dev Returns the total price and fees for the mint.
     * @param tier        The tier.
     * @param d           The mint data storage pointer.
     * @param quantity    How many tokens to mint.
     * @param signedPrice The signed price. Only for `VERIFY_SIGNATURE`.
     * @return f A struct containing the total price and fees.
     */
    function _totalPriceAndFees(
        uint8 tier,
        MintData storage d,
        uint32 quantity,
        uint96 signedPrice,
        bool hasValidAffiliate
    ) internal view returns (TotalPriceAndFees memory f) {
        // All flat prices are stored as uint96s in storage.
        // The quantity is a uint32. Multiplications between a uint96 and uint32 won't overflow.
        unchecked {
            PlatformFeeConfig memory c = effectivePlatformFeeConfig(d.platform, tier);

            // For signature mints, even if it is GA tier, we will use the signed price.
            if (d.mode == VERIFY_SIGNATURE) {
                if (signedPrice < d.price) revert SignedPriceTooLow(); // Enforce the price floor.
                f.unitPrice = signedPrice;
            } else if (tier == GA_TIER) {
                f.unitPrice = gaPrice[d.platform]; // Else if GA tier, use `gaPrice[platform]`.
            } else {
                f.unitPrice = d.price; // Else, use the `price`.
            }

            // The total price before any additive fees.
            f.subTotal = f.unitPrice * uint256(quantity);

            // Artist earns `subTotal` minus any basis points (BPS) split with affiliates and platform
            f.finalArtistFee = f.subTotal;

            // `affiliateBPSFee` is deducted from the `finalArtistFee`.
            if (d.affiliateFeeBPS != 0 && hasValidAffiliate) {
                uint256 affiliateBPSFee = LibOps.rawMulDiv(f.subTotal, d.affiliateFeeBPS, BPS_DENOMINATOR);
                f.finalArtistFee -= affiliateBPSFee;
                f.finalAffiliateFee = affiliateBPSFee;
            }
            // `platformBPSFee` is deducted from the `finalArtistFee`.
            if (c.platformMintFeeBPS != 0) {
                uint256 platformBPSFee = LibOps.rawMulDiv(f.subTotal, c.platformMintFeeBPS, BPS_DENOMINATOR);
                f.finalArtistFee -= platformBPSFee;
                f.finalPlatformFee = platformBPSFee;
            }

            // Protocol rewards are additive to `unitPrice` and paid by the buyer.
            // There are 2 sets of rewards, one for prices below `thresholdPrice` and one for prices above.
            if (f.unitPrice <= c.thresholdPrice) {
                f.finalArtistFee += c.artistMintReward * uint256(quantity);
                f.finalPlatformFee += c.platformMintReward * uint256(quantity);

                // The platform is the affiliate if no affiliate is provided.
                if (hasValidAffiliate) {
                    f.finalAffiliateFee += c.affiliateMintReward * uint256(quantity);
                } else {
                    f.finalPlatformFee += c.affiliateMintReward * uint256(quantity);
                }
            } else {
                f.finalArtistFee += c.thresholdArtistMintReward * uint256(quantity);
                f.finalPlatformFee += c.thresholdPlatformMintReward * uint256(quantity);

                // The platform is the affiliate if no affiliate is provided
                if (hasValidAffiliate) {
                    f.finalAffiliateFee += c.thresholdAffiliateMintReward * uint256(quantity);
                } else {
                    f.finalPlatformFee += c.thresholdAffiliateMintReward * uint256(quantity);
                }
            }

            // Per-transaction flat fee.
            f.finalPlatformFee += c.platformTxFlatFee;

            // The total is the final value which the minter has to pay. It includes all fees.
            f.total = f.finalArtistFee + f.finalAffiliateFee + f.finalPlatformFee;
        }
    }

    /**
     * @dev Returns whether the affiliate is affiliated for the mint
     * @param d              The mint data storage pointer.
     * @param affiliate      The affiliate address.
     * @param affiliateProof The Merkle proof for the affiliate.
     * @return The result.
     */
    function _isAffiliatedWithProof(
        MintData storage d,
        address affiliate,
        bytes32[] calldata affiliateProof
    ) internal view virtual returns (bool) {
        bytes32 root = d.affiliateMerkleRoot;
        // If the root is empty, then use the default logic.
        if (root == bytes32(0)) return affiliate != address(0);
        // Otherwise, check if the affiliate is in the Merkle tree.
        // The check that that affiliate is not a zero address is to prevent libraries
        // that fill up partial Merkle trees with empty leafs from screwing things up.
        return LibOps.and(affiliate != address(0), affiliateProof.verifyCalldata(root, _leaf(affiliate)));
    }

    // Utilities:
    // ----------

    /**
     * @dev Equivalent to `keccak256(abi.encodePacked(allowlisted))`.
     * @param allowlisted The allowlisted address.
     * @return result The leaf in the Merkle tree.
     */
    function _leaf(address allowlisted) internal pure returns (bytes32 result) {
        assembly {
            mstore(0x00, allowlisted)
            result := keccak256(0x0c, 0x14)
        }
    }

    /**
     * @dev Equivalent to `keccak256(abi.encodePacked(allowlisted, allowlistedQuantity))`.
     * @param allowlisted         The allowlisted address.
     * @param allowlistedQuantity Number of mints allowlisted.
     * @return result The leaf in the Merkle tree.
     */
    function _leaf(address allowlisted, uint32 allowlistedQuantity) internal pure returns (bytes32 result) {
        assembly {
            mstore(0x04, allowlistedQuantity)
            mstore(0x00, allowlisted)
            result := keccak256(0x0c, 0x18)
        }
    }

    /**
     * @dev Retrieves the mint data from storage, reverting if the mint does not exist.
     * @param mintId The mint ID.
     * @return d The storage pointer to the mint data.
     */
    function _getMintData(uint256 mintId) internal view returns (MintData storage d) {
        d = _mintData[mintId];
        if (d.flags & _MINT_CREATED_FLAG == 0) revert MintDoesNotExist();
    }

    /**
     * @dev Returns whether the mint is paused.
     * @param d The storage pointer to the mint data.
     * @return Whether the mint is paused.
     */
    function _isPaused(MintData storage d) internal view returns (bool) {
        return d.flags & _MINT_PAUSED_FLAG != 0;
    }
}

File 2 of 21 : OwnableRoles.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

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

/// @notice Simple single owner and multiroles authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
/// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173)
/// for compatibility, the nomenclature for the 2-step ownership handover and roles
/// may be unique to this codebase.
abstract contract OwnableRoles is Ownable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The `user`'s roles is updated to `roles`.
    /// Each bit of `roles` represents whether the role is set.
    event RolesUpdated(address indexed user, uint256 indexed roles);

    /// @dev `keccak256(bytes("RolesUpdated(address,uint256)"))`.
    uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE =
        0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The role slot of `user` is given by:
    /// ```
    ///     mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED))
    ///     let roleSlot := keccak256(0x00, 0x20)
    /// ```
    /// This automatically ignores the upper bits of the `user` in case
    /// they are not clean, as well as keep the `keccak256` under 32-bytes.
    ///
    /// Note: This is equivalent to `uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))`.
    uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Overwrite the roles directly without authorization guard.
    function _setRoles(address user, uint256 roles) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x0c, _ROLE_SLOT_SEED)
            mstore(0x00, user)
            // Store the new value.
            sstore(keccak256(0x0c, 0x20), roles)
            // Emit the {RolesUpdated} event.
            log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles)
        }
    }

    /// @dev Updates the roles directly without authorization guard.
    /// If `on` is true, each set bit of `roles` will be turned on,
    /// otherwise, each set bit of `roles` will be turned off.
    function _updateRoles(address user, uint256 roles, bool on) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x0c, _ROLE_SLOT_SEED)
            mstore(0x00, user)
            let roleSlot := keccak256(0x0c, 0x20)
            // Load the current value.
            let current := sload(roleSlot)
            // Compute the updated roles if `on` is true.
            let updated := or(current, roles)
            // Compute the updated roles if `on` is false.
            // Use `and` to compute the intersection of `current` and `roles`,
            // `xor` it with `current` to flip the bits in the intersection.
            if iszero(on) { updated := xor(current, and(current, roles)) }
            // Then, store the new value.
            sstore(roleSlot, updated)
            // Emit the {RolesUpdated} event.
            log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), updated)
        }
    }

    /// @dev Grants the roles directly without authorization guard.
    /// Each bit of `roles` represents the role to turn on.
    function _grantRoles(address user, uint256 roles) internal virtual {
        _updateRoles(user, roles, true);
    }

    /// @dev Removes the roles directly without authorization guard.
    /// Each bit of `roles` represents the role to turn off.
    function _removeRoles(address user, uint256 roles) internal virtual {
        _updateRoles(user, roles, false);
    }

    /// @dev Throws if the sender does not have any of the `roles`.
    function _checkRoles(uint256 roles) internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the role slot.
            mstore(0x0c, _ROLE_SLOT_SEED)
            mstore(0x00, caller())
            // Load the stored value, and if the `and` intersection
            // of the value and `roles` is zero, revert.
            if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Throws if the sender is not the owner,
    /// and does not have any of the `roles`.
    /// Checks for ownership first, then lazily checks for roles.
    function _checkOwnerOrRoles(uint256 roles) internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // If the caller is not the stored owner.
            // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
            if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
                // Compute the role slot.
                mstore(0x0c, _ROLE_SLOT_SEED)
                mstore(0x00, caller())
                // Load the stored value, and if the `and` intersection
                // of the value and `roles` is zero, revert.
                if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
                    mstore(0x00, 0x82b42900) // `Unauthorized()`.
                    revert(0x1c, 0x04)
                }
            }
        }
    }

    /// @dev Throws if the sender does not have any of the `roles`,
    /// and is not the owner.
    /// Checks for roles first, then lazily checks for ownership.
    function _checkRolesOrOwner(uint256 roles) internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the role slot.
            mstore(0x0c, _ROLE_SLOT_SEED)
            mstore(0x00, caller())
            // Load the stored value, and if the `and` intersection
            // of the value and `roles` is zero, revert.
            if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
                // If the caller is not the stored owner.
                // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
                if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
                    mstore(0x00, 0x82b42900) // `Unauthorized()`.
                    revert(0x1c, 0x04)
                }
            }
        }
    }

    /// @dev Convenience function to return a `roles` bitmap from an array of `ordinals`.
    /// This is meant for frontends like Etherscan, and is therefore not fully optimized.
    /// Not recommended to be called on-chain.
    /// Made internal to conserve bytecode. Wrap it in a public function if needed.
    function _rolesFromOrdinals(uint8[] memory ordinals) internal pure returns (uint256 roles) {
        /// @solidity memory-safe-assembly
        assembly {
            for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } {
                // We don't need to mask the values of `ordinals`, as Solidity
                // cleans dirty upper bits when storing variables into memory.
                roles := or(shl(mload(add(ordinals, i)), 1), roles)
            }
        }
    }

    /// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap.
    /// This is meant for frontends like Etherscan, and is therefore not fully optimized.
    /// Not recommended to be called on-chain.
    /// Made internal to conserve bytecode. Wrap it in a public function if needed.
    function _ordinalsFromRoles(uint256 roles) internal pure returns (uint8[] memory ordinals) {
        /// @solidity memory-safe-assembly
        assembly {
            // Grab the pointer to the free memory.
            ordinals := mload(0x40)
            let ptr := add(ordinals, 0x20)
            let o := 0
            // The absence of lookup tables, De Bruijn, etc., here is intentional for
            // smaller bytecode, as this function is not meant to be called on-chain.
            for { let t := roles } 1 {} {
                mstore(ptr, o)
                // `shr` 5 is equivalent to multiplying by 0x20.
                // Push back into the ordinals array if the bit is set.
                ptr := add(ptr, shl(5, and(t, 1)))
                o := add(o, 1)
                t := shr(o, roles)
                if iszero(t) { break }
            }
            // Store the length of `ordinals`.
            mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20))))
            // Allocate the memory.
            mstore(0x40, ptr)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  PUBLIC UPDATE FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Allows the owner to grant `user` `roles`.
    /// If the `user` already has a role, then it will be an no-op for the role.
    function grantRoles(address user, uint256 roles) public payable virtual onlyOwner {
        _grantRoles(user, roles);
    }

    /// @dev Allows the owner to remove `user` `roles`.
    /// If the `user` does not have a role, then it will be an no-op for the role.
    function revokeRoles(address user, uint256 roles) public payable virtual onlyOwner {
        _removeRoles(user, roles);
    }

    /// @dev Allow the caller to remove their own roles.
    /// If the caller does not have a role, then it will be an no-op for the role.
    function renounceRoles(uint256 roles) public payable virtual {
        _removeRoles(msg.sender, roles);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   PUBLIC READ FUNCTIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the roles of `user`.
    function rolesOf(address user) public view virtual returns (uint256 roles) {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the role slot.
            mstore(0x0c, _ROLE_SLOT_SEED)
            mstore(0x00, user)
            // Load the stored value.
            roles := sload(keccak256(0x0c, 0x20))
        }
    }

    /// @dev Returns whether `user` has any of `roles`.
    function hasAnyRole(address user, uint256 roles) public view virtual returns (bool) {
        return rolesOf(user) & roles != 0;
    }

    /// @dev Returns whether `user` has all of `roles`.
    function hasAllRoles(address user, uint256 roles) public view virtual returns (bool) {
        return rolesOf(user) & roles == roles;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         MODIFIERS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Marks a function as only callable by an account with `roles`.
    modifier onlyRoles(uint256 roles) virtual {
        _checkRoles(roles);
        _;
    }

    /// @dev Marks a function as only callable by the owner or by an account
    /// with `roles`. Checks for ownership first, then lazily checks for roles.
    modifier onlyOwnerOrRoles(uint256 roles) virtual {
        _checkOwnerOrRoles(roles);
        _;
    }

    /// @dev Marks a function as only callable by an account with `roles`
    /// or the owner. Checks for roles first, then lazily checks for ownership.
    modifier onlyRolesOrOwner(uint256 roles) virtual {
        _checkRolesOrOwner(roles);
        _;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ROLE CONSTANTS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // IYKYK

    uint256 internal constant _ROLE_0 = 1 << 0;
    uint256 internal constant _ROLE_1 = 1 << 1;
    uint256 internal constant _ROLE_2 = 1 << 2;
    uint256 internal constant _ROLE_3 = 1 << 3;
    uint256 internal constant _ROLE_4 = 1 << 4;
    uint256 internal constant _ROLE_5 = 1 << 5;
    uint256 internal constant _ROLE_6 = 1 << 6;
    uint256 internal constant _ROLE_7 = 1 << 7;
    uint256 internal constant _ROLE_8 = 1 << 8;
    uint256 internal constant _ROLE_9 = 1 << 9;
    uint256 internal constant _ROLE_10 = 1 << 10;
    uint256 internal constant _ROLE_11 = 1 << 11;
    uint256 internal constant _ROLE_12 = 1 << 12;
    uint256 internal constant _ROLE_13 = 1 << 13;
    uint256 internal constant _ROLE_14 = 1 << 14;
    uint256 internal constant _ROLE_15 = 1 << 15;
    uint256 internal constant _ROLE_16 = 1 << 16;
    uint256 internal constant _ROLE_17 = 1 << 17;
    uint256 internal constant _ROLE_18 = 1 << 18;
    uint256 internal constant _ROLE_19 = 1 << 19;
    uint256 internal constant _ROLE_20 = 1 << 20;
    uint256 internal constant _ROLE_21 = 1 << 21;
    uint256 internal constant _ROLE_22 = 1 << 22;
    uint256 internal constant _ROLE_23 = 1 << 23;
    uint256 internal constant _ROLE_24 = 1 << 24;
    uint256 internal constant _ROLE_25 = 1 << 25;
    uint256 internal constant _ROLE_26 = 1 << 26;
    uint256 internal constant _ROLE_27 = 1 << 27;
    uint256 internal constant _ROLE_28 = 1 << 28;
    uint256 internal constant _ROLE_29 = 1 << 29;
    uint256 internal constant _ROLE_30 = 1 << 30;
    uint256 internal constant _ROLE_31 = 1 << 31;
    uint256 internal constant _ROLE_32 = 1 << 32;
    uint256 internal constant _ROLE_33 = 1 << 33;
    uint256 internal constant _ROLE_34 = 1 << 34;
    uint256 internal constant _ROLE_35 = 1 << 35;
    uint256 internal constant _ROLE_36 = 1 << 36;
    uint256 internal constant _ROLE_37 = 1 << 37;
    uint256 internal constant _ROLE_38 = 1 << 38;
    uint256 internal constant _ROLE_39 = 1 << 39;
    uint256 internal constant _ROLE_40 = 1 << 40;
    uint256 internal constant _ROLE_41 = 1 << 41;
    uint256 internal constant _ROLE_42 = 1 << 42;
    uint256 internal constant _ROLE_43 = 1 << 43;
    uint256 internal constant _ROLE_44 = 1 << 44;
    uint256 internal constant _ROLE_45 = 1 << 45;
    uint256 internal constant _ROLE_46 = 1 << 46;
    uint256 internal constant _ROLE_47 = 1 << 47;
    uint256 internal constant _ROLE_48 = 1 << 48;
    uint256 internal constant _ROLE_49 = 1 << 49;
    uint256 internal constant _ROLE_50 = 1 << 50;
    uint256 internal constant _ROLE_51 = 1 << 51;
    uint256 internal constant _ROLE_52 = 1 << 52;
    uint256 internal constant _ROLE_53 = 1 << 53;
    uint256 internal constant _ROLE_54 = 1 << 54;
    uint256 internal constant _ROLE_55 = 1 << 55;
    uint256 internal constant _ROLE_56 = 1 << 56;
    uint256 internal constant _ROLE_57 = 1 << 57;
    uint256 internal constant _ROLE_58 = 1 << 58;
    uint256 internal constant _ROLE_59 = 1 << 59;
    uint256 internal constant _ROLE_60 = 1 << 60;
    uint256 internal constant _ROLE_61 = 1 << 61;
    uint256 internal constant _ROLE_62 = 1 << 62;
    uint256 internal constant _ROLE_63 = 1 << 63;
    uint256 internal constant _ROLE_64 = 1 << 64;
    uint256 internal constant _ROLE_65 = 1 << 65;
    uint256 internal constant _ROLE_66 = 1 << 66;
    uint256 internal constant _ROLE_67 = 1 << 67;
    uint256 internal constant _ROLE_68 = 1 << 68;
    uint256 internal constant _ROLE_69 = 1 << 69;
    uint256 internal constant _ROLE_70 = 1 << 70;
    uint256 internal constant _ROLE_71 = 1 << 71;
    uint256 internal constant _ROLE_72 = 1 << 72;
    uint256 internal constant _ROLE_73 = 1 << 73;
    uint256 internal constant _ROLE_74 = 1 << 74;
    uint256 internal constant _ROLE_75 = 1 << 75;
    uint256 internal constant _ROLE_76 = 1 << 76;
    uint256 internal constant _ROLE_77 = 1 << 77;
    uint256 internal constant _ROLE_78 = 1 << 78;
    uint256 internal constant _ROLE_79 = 1 << 79;
    uint256 internal constant _ROLE_80 = 1 << 80;
    uint256 internal constant _ROLE_81 = 1 << 81;
    uint256 internal constant _ROLE_82 = 1 << 82;
    uint256 internal constant _ROLE_83 = 1 << 83;
    uint256 internal constant _ROLE_84 = 1 << 84;
    uint256 internal constant _ROLE_85 = 1 << 85;
    uint256 internal constant _ROLE_86 = 1 << 86;
    uint256 internal constant _ROLE_87 = 1 << 87;
    uint256 internal constant _ROLE_88 = 1 << 88;
    uint256 internal constant _ROLE_89 = 1 << 89;
    uint256 internal constant _ROLE_90 = 1 << 90;
    uint256 internal constant _ROLE_91 = 1 << 91;
    uint256 internal constant _ROLE_92 = 1 << 92;
    uint256 internal constant _ROLE_93 = 1 << 93;
    uint256 internal constant _ROLE_94 = 1 << 94;
    uint256 internal constant _ROLE_95 = 1 << 95;
    uint256 internal constant _ROLE_96 = 1 << 96;
    uint256 internal constant _ROLE_97 = 1 << 97;
    uint256 internal constant _ROLE_98 = 1 << 98;
    uint256 internal constant _ROLE_99 = 1 << 99;
    uint256 internal constant _ROLE_100 = 1 << 100;
    uint256 internal constant _ROLE_101 = 1 << 101;
    uint256 internal constant _ROLE_102 = 1 << 102;
    uint256 internal constant _ROLE_103 = 1 << 103;
    uint256 internal constant _ROLE_104 = 1 << 104;
    uint256 internal constant _ROLE_105 = 1 << 105;
    uint256 internal constant _ROLE_106 = 1 << 106;
    uint256 internal constant _ROLE_107 = 1 << 107;
    uint256 internal constant _ROLE_108 = 1 << 108;
    uint256 internal constant _ROLE_109 = 1 << 109;
    uint256 internal constant _ROLE_110 = 1 << 110;
    uint256 internal constant _ROLE_111 = 1 << 111;
    uint256 internal constant _ROLE_112 = 1 << 112;
    uint256 internal constant _ROLE_113 = 1 << 113;
    uint256 internal constant _ROLE_114 = 1 << 114;
    uint256 internal constant _ROLE_115 = 1 << 115;
    uint256 internal constant _ROLE_116 = 1 << 116;
    uint256 internal constant _ROLE_117 = 1 << 117;
    uint256 internal constant _ROLE_118 = 1 << 118;
    uint256 internal constant _ROLE_119 = 1 << 119;
    uint256 internal constant _ROLE_120 = 1 << 120;
    uint256 internal constant _ROLE_121 = 1 << 121;
    uint256 internal constant _ROLE_122 = 1 << 122;
    uint256 internal constant _ROLE_123 = 1 << 123;
    uint256 internal constant _ROLE_124 = 1 << 124;
    uint256 internal constant _ROLE_125 = 1 << 125;
    uint256 internal constant _ROLE_126 = 1 << 126;
    uint256 internal constant _ROLE_127 = 1 << 127;
    uint256 internal constant _ROLE_128 = 1 << 128;
    uint256 internal constant _ROLE_129 = 1 << 129;
    uint256 internal constant _ROLE_130 = 1 << 130;
    uint256 internal constant _ROLE_131 = 1 << 131;
    uint256 internal constant _ROLE_132 = 1 << 132;
    uint256 internal constant _ROLE_133 = 1 << 133;
    uint256 internal constant _ROLE_134 = 1 << 134;
    uint256 internal constant _ROLE_135 = 1 << 135;
    uint256 internal constant _ROLE_136 = 1 << 136;
    uint256 internal constant _ROLE_137 = 1 << 137;
    uint256 internal constant _ROLE_138 = 1 << 138;
    uint256 internal constant _ROLE_139 = 1 << 139;
    uint256 internal constant _ROLE_140 = 1 << 140;
    uint256 internal constant _ROLE_141 = 1 << 141;
    uint256 internal constant _ROLE_142 = 1 << 142;
    uint256 internal constant _ROLE_143 = 1 << 143;
    uint256 internal constant _ROLE_144 = 1 << 144;
    uint256 internal constant _ROLE_145 = 1 << 145;
    uint256 internal constant _ROLE_146 = 1 << 146;
    uint256 internal constant _ROLE_147 = 1 << 147;
    uint256 internal constant _ROLE_148 = 1 << 148;
    uint256 internal constant _ROLE_149 = 1 << 149;
    uint256 internal constant _ROLE_150 = 1 << 150;
    uint256 internal constant _ROLE_151 = 1 << 151;
    uint256 internal constant _ROLE_152 = 1 << 152;
    uint256 internal constant _ROLE_153 = 1 << 153;
    uint256 internal constant _ROLE_154 = 1 << 154;
    uint256 internal constant _ROLE_155 = 1 << 155;
    uint256 internal constant _ROLE_156 = 1 << 156;
    uint256 internal constant _ROLE_157 = 1 << 157;
    uint256 internal constant _ROLE_158 = 1 << 158;
    uint256 internal constant _ROLE_159 = 1 << 159;
    uint256 internal constant _ROLE_160 = 1 << 160;
    uint256 internal constant _ROLE_161 = 1 << 161;
    uint256 internal constant _ROLE_162 = 1 << 162;
    uint256 internal constant _ROLE_163 = 1 << 163;
    uint256 internal constant _ROLE_164 = 1 << 164;
    uint256 internal constant _ROLE_165 = 1 << 165;
    uint256 internal constant _ROLE_166 = 1 << 166;
    uint256 internal constant _ROLE_167 = 1 << 167;
    uint256 internal constant _ROLE_168 = 1 << 168;
    uint256 internal constant _ROLE_169 = 1 << 169;
    uint256 internal constant _ROLE_170 = 1 << 170;
    uint256 internal constant _ROLE_171 = 1 << 171;
    uint256 internal constant _ROLE_172 = 1 << 172;
    uint256 internal constant _ROLE_173 = 1 << 173;
    uint256 internal constant _ROLE_174 = 1 << 174;
    uint256 internal constant _ROLE_175 = 1 << 175;
    uint256 internal constant _ROLE_176 = 1 << 176;
    uint256 internal constant _ROLE_177 = 1 << 177;
    uint256 internal constant _ROLE_178 = 1 << 178;
    uint256 internal constant _ROLE_179 = 1 << 179;
    uint256 internal constant _ROLE_180 = 1 << 180;
    uint256 internal constant _ROLE_181 = 1 << 181;
    uint256 internal constant _ROLE_182 = 1 << 182;
    uint256 internal constant _ROLE_183 = 1 << 183;
    uint256 internal constant _ROLE_184 = 1 << 184;
    uint256 internal constant _ROLE_185 = 1 << 185;
    uint256 internal constant _ROLE_186 = 1 << 186;
    uint256 internal constant _ROLE_187 = 1 << 187;
    uint256 internal constant _ROLE_188 = 1 << 188;
    uint256 internal constant _ROLE_189 = 1 << 189;
    uint256 internal constant _ROLE_190 = 1 << 190;
    uint256 internal constant _ROLE_191 = 1 << 191;
    uint256 internal constant _ROLE_192 = 1 << 192;
    uint256 internal constant _ROLE_193 = 1 << 193;
    uint256 internal constant _ROLE_194 = 1 << 194;
    uint256 internal constant _ROLE_195 = 1 << 195;
    uint256 internal constant _ROLE_196 = 1 << 196;
    uint256 internal constant _ROLE_197 = 1 << 197;
    uint256 internal constant _ROLE_198 = 1 << 198;
    uint256 internal constant _ROLE_199 = 1 << 199;
    uint256 internal constant _ROLE_200 = 1 << 200;
    uint256 internal constant _ROLE_201 = 1 << 201;
    uint256 internal constant _ROLE_202 = 1 << 202;
    uint256 internal constant _ROLE_203 = 1 << 203;
    uint256 internal constant _ROLE_204 = 1 << 204;
    uint256 internal constant _ROLE_205 = 1 << 205;
    uint256 internal constant _ROLE_206 = 1 << 206;
    uint256 internal constant _ROLE_207 = 1 << 207;
    uint256 internal constant _ROLE_208 = 1 << 208;
    uint256 internal constant _ROLE_209 = 1 << 209;
    uint256 internal constant _ROLE_210 = 1 << 210;
    uint256 internal constant _ROLE_211 = 1 << 211;
    uint256 internal constant _ROLE_212 = 1 << 212;
    uint256 internal constant _ROLE_213 = 1 << 213;
    uint256 internal constant _ROLE_214 = 1 << 214;
    uint256 internal constant _ROLE_215 = 1 << 215;
    uint256 internal constant _ROLE_216 = 1 << 216;
    uint256 internal constant _ROLE_217 = 1 << 217;
    uint256 internal constant _ROLE_218 = 1 << 218;
    uint256 internal constant _ROLE_219 = 1 << 219;
    uint256 internal constant _ROLE_220 = 1 << 220;
    uint256 internal constant _ROLE_221 = 1 << 221;
    uint256 internal constant _ROLE_222 = 1 << 222;
    uint256 internal constant _ROLE_223 = 1 << 223;
    uint256 internal constant _ROLE_224 = 1 << 224;
    uint256 internal constant _ROLE_225 = 1 << 225;
    uint256 internal constant _ROLE_226 = 1 << 226;
    uint256 internal constant _ROLE_227 = 1 << 227;
    uint256 internal constant _ROLE_228 = 1 << 228;
    uint256 internal constant _ROLE_229 = 1 << 229;
    uint256 internal constant _ROLE_230 = 1 << 230;
    uint256 internal constant _ROLE_231 = 1 << 231;
    uint256 internal constant _ROLE_232 = 1 << 232;
    uint256 internal constant _ROLE_233 = 1 << 233;
    uint256 internal constant _ROLE_234 = 1 << 234;
    uint256 internal constant _ROLE_235 = 1 << 235;
    uint256 internal constant _ROLE_236 = 1 << 236;
    uint256 internal constant _ROLE_237 = 1 << 237;
    uint256 internal constant _ROLE_238 = 1 << 238;
    uint256 internal constant _ROLE_239 = 1 << 239;
    uint256 internal constant _ROLE_240 = 1 << 240;
    uint256 internal constant _ROLE_241 = 1 << 241;
    uint256 internal constant _ROLE_242 = 1 << 242;
    uint256 internal constant _ROLE_243 = 1 << 243;
    uint256 internal constant _ROLE_244 = 1 << 244;
    uint256 internal constant _ROLE_245 = 1 << 245;
    uint256 internal constant _ROLE_246 = 1 << 246;
    uint256 internal constant _ROLE_247 = 1 << 247;
    uint256 internal constant _ROLE_248 = 1 << 248;
    uint256 internal constant _ROLE_249 = 1 << 249;
    uint256 internal constant _ROLE_250 = 1 << 250;
    uint256 internal constant _ROLE_251 = 1 << 251;
    uint256 internal constant _ROLE_252 = 1 << 252;
    uint256 internal constant _ROLE_253 = 1 << 253;
    uint256 internal constant _ROLE_254 = 1 << 254;
    uint256 internal constant _ROLE_255 = 1 << 255;
}

File 3 of 21 : ISoundEditionV2_1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import { IERC721AUpgradeable } from "chiru-labs/ERC721A-Upgradeable/IERC721AUpgradeable.sol";
import { IERC2981Upgradeable } from "openzeppelin-upgradeable/interfaces/IERC2981Upgradeable.sol";
import { IERC165Upgradeable } from "openzeppelin-upgradeable/utils/introspection/IERC165Upgradeable.sol";

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

/**
 * @title ISoundEditionV2_1
 * @notice The interface for Sound edition contracts.
 */
interface ISoundEditionV2_1 is IERC721AUpgradeable, IERC2981Upgradeable {
    // =============================================================
    //                            STRUCTS
    // =============================================================

    /**
     * @dev The information pertaining to a tier.
     */
    struct TierInfo {
        // The tier.
        uint8 tier;
        // The current max mintable amount.
        uint32 maxMintable;
        // The lower bound of the maximum number of tokens that can be minted for the tier.
        uint32 maxMintableLower;
        // The upper bound of the maximum number of tokens that can be minted for the tier.
        uint32 maxMintableUpper;
        // The timestamp (in seconds since unix epoch) after which the
        // max amount of tokens mintable for the tier will drop from
        // `maxMintableUpper` to `maxMintableLower`.
        uint32 cutoffTime;
        // The total number of tokens minted for the tier.
        uint32 minted;
        // The mint randomness for the tier.
        uint256 mintRandomness;
        // Whether the tier mints have concluded.
        bool mintConcluded;
        // Whether the tier has mint randomness enabled.
        bool mintRandomnessEnabled;
        // Whether the tier is frozen.
        bool isFrozen;
    }

    /**
     * @dev A struct containing the arguments for creating a tier.
     */
    struct TierCreation {
        // The tier.
        uint8 tier;
        // The lower bound of the maximum number of tokens that can be minted for the tier.
        uint32 maxMintableLower;
        // The upper bound of the maximum number of tokens that can be minted for the tier.
        uint32 maxMintableUpper;
        // The timestamp (in seconds since unix epoch) after which the
        // max amount of tokens mintable for the tier will drop from
        // `maxMintableUpper` to `maxMintableLower`.
        uint32 cutoffTime;
        // Whether the tier has mint randomness enabled.
        bool mintRandomnessEnabled;
        // Whether the tier is frozen.
        bool isFrozen;
    }

    /**
     * @dev The information pertaining to this edition.
     */
    struct EditionInfo {
        // Base URI for the metadata.
        string baseURI;
        // Contract URI for OpenSea storefront.
        string contractURI;
        // Name of the collection.
        string name;
        // Symbol of the collection.
        string symbol;
        // Address that receives primary and secondary royalties.
        address fundingRecipient;
        // Address of the metadata module. Optional.
        address metadataModule;
        // Whether the metadata is frozen.
        bool isMetadataFrozen;
        // Whether the ability to create tiers is frozen.
        bool isCreateTierFrozen;
        // The royalty BPS (basis points).
        uint16 royaltyBPS;
        // Next token ID to be minted.
        uint256 nextTokenId;
        // Total number of tokens burned.
        uint256 totalBurned;
        // Total number of tokens minted.
        uint256 totalMinted;
        // Total number of tokens currently in existence.
        uint256 totalSupply;
        // An array of tier info. From lowest (0-indexed) to highest.
        TierInfo[] tierInfo;
    }

    /**
     * @dev A struct containing the arguments for initialization.
     */
    struct EditionInitialization {
        // Name of the collection.
        string name;
        // Symbol of the collection.
        string symbol;
        // Address of the metadata module. Optional.
        address metadataModule;
        // Base URI for the metadata.
        string baseURI;
        // Contract URI for OpenSea storefront.
        string contractURI;
        // Address that receives primary and secondary royalties.
        address fundingRecipient;
        // The royalty BPS (basis points).
        uint16 royaltyBPS;
        // Whether the metadata is frozen.
        bool isMetadataFrozen;
        // Whether the ability to create tiers is frozen.
        bool isCreateTierFrozen;
        // An array of tier creation structs. From lowest (0-indexed) to highest.
        TierCreation[] tierCreations;
    }

    // =============================================================
    //                            EVENTS
    // =============================================================

    /**
     * @dev Emitted when the metadata module is set.
     * @param metadataModule the address of the metadata module.
     */
    event MetadataModuleSet(address metadataModule);

    /**
     * @dev Emitted when the `baseURI` is set.
     * @param baseURI the base URI of the edition.
     */
    event BaseURISet(string baseURI);

    /**
     * @dev Emitted when the `contractURI` is set.
     * @param contractURI The contract URI of the edition.
     */
    event ContractURISet(string contractURI);

    /**
     * @dev Emitted when the metadata is frozen (e.g.: `baseURI` can no longer be changed).
     * @param metadataModule The address of the metadata module.
     * @param baseURI        The base URI of the edition.
     * @param contractURI    The contract URI of the edition.
     */
    event MetadataFrozen(address metadataModule, string baseURI, string contractURI);

    /**
     * @dev Emitted when the ability to create tier is removed.
     */
    event CreateTierFrozen();

    /**
     * @dev Emitted when the `fundingRecipient` is set.
     * @param recipient The address of the funding recipient.
     */
    event FundingRecipientSet(address recipient);

    /**
     * @dev Emitted when the `royaltyBPS` is set.
     * @param bps The new royalty, measured in basis points.
     */
    event RoyaltySet(uint16 bps);

    /**
     * @dev Emitted when the tier's maximum mintable token quantity range is set.
     * @param tier  The tier.
     * @param lower The lower limit of the maximum number of tokens that can be minted.
     * @param upper The upper limit of the maximum number of tokens that can be minted.
     */
    event MaxMintableRangeSet(uint8 tier, uint32 lower, uint32 upper);

    /**
     * @dev Emitted when the tier's cutoff time set.
     * @param tier    The tier.
     * @param cutoff The timestamp.
     */
    event CutoffTimeSet(uint8 tier, uint32 cutoff);

    /**
     * @dev Emitted when the `mintRandomnessEnabled` for the tier is set.
     * @param tier    The tier.
     * @param enabled The boolean value.
     */
    event MintRandomnessEnabledSet(uint8 tier, bool enabled);

    /**
     * @dev Emitted upon initialization.
     * @param init The initialization data.
     */
    event SoundEditionInitialized(EditionInitialization init);

    /**
     * @dev Emitted when a tier is created.
     * @param creation The tier creation data.
     */
    event TierCreated(TierCreation creation);

    /**
     * @dev Emitted when a tier is frozen.
     * @param tier The tier.
     */
    event TierFrozen(uint8 tier);

    /**
     * @dev Emitted upon ETH withdrawal.
     * @param recipient The recipient of the withdrawal.
     * @param amount    The amount withdrawn.
     * @param caller    The account that initiated the withdrawal.
     */
    event ETHWithdrawn(address recipient, uint256 amount, address caller);

    /**
     * @dev Emitted upon ERC20 withdrawal.
     * @param recipient The recipient of the withdrawal.
     * @param tokens    The addresses of the ERC20 tokens.
     * @param amounts   The amount of each token withdrawn.
     * @param caller    The account that initiated the withdrawal.
     */
    event ERC20Withdrawn(address recipient, address[] tokens, uint256[] amounts, address caller);

    /**
     * @dev Emitted upon a mint.
     * @param tier                 The tier.
     * @param to                   The address to mint to.
     * @param quantity             The number of minted.
     * @param fromTokenId          The first token ID minted.
     * @param fromTierTokenIdIndex The first token index in the tier.
     */
    event Minted(uint8 tier, address to, uint256 quantity, uint256 fromTokenId, uint32 fromTierTokenIdIndex);

    /**
     * @dev Emitted upon an airdrop.
     * @param tier                 The tier.
     * @param to                   The recipients of the airdrop.
     * @param quantity             The number of tokens airdropped to each address in `to`.
     * @param fromTokenId          The first token ID minted to the first address in `to`.
     * @param fromTierTokenIdIndex The first token index in the tier.
     */
    event Airdropped(uint8 tier, address[] to, uint256 quantity, uint256 fromTokenId, uint32 fromTierTokenIdIndex);

    /**
     * @dev EIP-4906 event to signal marketplaces to refresh the metadata.
     * @param fromTokenId The starting token ID.
     * @param toTokenId   The ending token ID.
     */
    event BatchMetadataUpdate(uint256 fromTokenId, uint256 toTokenId);

    // =============================================================
    //                            ERRORS
    // =============================================================

    /**
     * @dev The edition's metadata is frozen (e.g.: `baseURI` can no longer be changed).
     */
    error MetadataIsFrozen();

    /**
     * @dev The ability to create tiers is frozen.
     */
    error CreateTierIsFrozen();

    /**
     * @dev The given `royaltyBPS` is invalid.
     */
    error InvalidRoyaltyBPS();

    /**
     * @dev A minimum of one tier must be provided to initialize a Sound Edition.
     */
    error ZeroTiersProvided();

    /**
     * @dev The requested quantity exceeds the edition's remaining mintable token quantity.
     */
    error ExceedsAvailableSupply();

    /**
     * @dev The given `fundingRecipient` address is invalid.
     */
    error InvalidFundingRecipient();

    /**
     * @dev The `maxMintableLower` must not be greater than `maxMintableUpper`.
     */
    error InvalidMaxMintableRange();

    /**
     * @dev The mint has already concluded.
     */
    error MintHasConcluded();

    /**
     * @dev The mint has not concluded.
     */
    error MintNotConcluded();

    /**
     * @dev Cannot perform the operation after a token has been minted.
     */
    error MintsAlreadyExist();

    /**
     * @dev Cannot perform the operation after a token has been minted in the tier.
     */
    error TierMintsAlreadyExist();

    /**
     * @dev The token IDs must be in strictly ascending order.
     */
    error TokenIdsNotStrictlyAscending();

    /**
     * @dev The tier does not exist.
     */
    error TierDoesNotExist();

    /**
     * @dev The tier already exists.
     */
    error TierAlreadyExists();

    /**
     * @dev The tier is frozen.
     */
    error TierIsFrozen();

    /**
     * @dev One of more of the tokens do not have the correct token tier.
     */
    error InvalidTokenTier();

    /**
     * @dev Please wait for a while before you burn.
     */
    error CannotBurnImmediately();

    /**
     * @dev The token for the tier query doesn't exist.
     */
    error TierQueryForNonexistentToken();

    // =============================================================
    //               PUBLIC / EXTERNAL WRITE FUNCTIONS
    // =============================================================

    /**
     * @dev Initializes the contract.
     * @param init The initialization struct.
     */
    function initialize(EditionInitialization calldata init) external;

    /**
     * @dev Mints `quantity` tokens to addrress `to`
     *      Each token will be assigned a token ID that is consecutively increasing.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have either the
     *   `ADMIN_ROLE`, `MINTER_ROLE`, which can be granted via {grantRole}.
     *   Multiple minters, such as different minter contracts,
     *   can be authorized simultaneously.
     *
     * @param tier     The tier.
     * @param to       Address to mint to.
     * @param quantity Number of tokens to mint.
     * @return fromTokenId The first token ID minted.
     */
    function mint(
        uint8 tier,
        address to,
        uint256 quantity
    ) external payable returns (uint256 fromTokenId);

    /**
     * @dev Mints `quantity` tokens to each of the addresses in `to`.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the
     *   `ADMIN_ROLE`, which can be granted via {grantRole}.
     *
     * @param tier         The tier.
     * @param to           Address to mint to.
     * @param quantity     Number of tokens to mint.
     * @return fromTokenId The first token ID minted.
     */
    function airdrop(
        uint8 tier,
        address[] calldata to,
        uint256 quantity
    ) external payable returns (uint256 fromTokenId);

    /**
     * @dev Withdraws collected ETH royalties to the fundingRecipient.
     */
    function withdrawETH() external;

    /**
     * @dev Withdraws collected ERC20 royalties to the fundingRecipient.
     * @param tokens array of ERC20 tokens to withdraw
     */
    function withdrawERC20(address[] calldata tokens) external;

    /**
     * @dev Sets metadata module.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     *
     * @param metadataModule Address of metadata module.
     */
    function setMetadataModule(address metadataModule) external;

    /**
     * @dev Sets global base URI.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     *
     * @param baseURI The base URI to be set.
     */
    function setBaseURI(string memory baseURI) external;

    /**
     * @dev Sets contract URI.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     *
     * @param contractURI The contract URI to be set.
     */
    function setContractURI(string memory contractURI) external;

    /**
     * @dev Freezes metadata by preventing any more changes to base URI.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     */
    function freezeMetadata() external;

    /**
     * @dev Freezes the max tier by preventing any more tiers from being added,
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     */
    function freezeCreateTier() external;

    /**
     * @dev Sets funding recipient address.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     *
     * @param fundingRecipient Address to be set as the new funding recipient.
     */
    function setFundingRecipient(address fundingRecipient) external;

    /**
     * @dev Creates a new split wallet via the SplitMain contract, then sets it as the `fundingRecipient`.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     *
     * @param splitMain The address of the SplitMain contract.
     * @param splitData The calldata to forward to the SplitMain contract to create a split.
     * @return split The address of the new split contract.
     */
    function createSplit(address splitMain, bytes calldata splitData) external returns (address split);

    /**
     * @dev Sets royalty amount in bps (basis points).
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     *
     * @param bps The new royalty basis points to be set.
     */
    function setRoyalty(uint16 bps) external;

    /**
     * @dev Freezes the tier.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     *
     * @param tier  The tier.
     */
    function freezeTier(uint8 tier) external;

    /**
     * @dev Sets the edition max mintable range.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     *
     * @param tier  The tier.
     * @param lower The lower limit of the maximum number of tokens that can be minted.
     * @param upper The upper limit of the maximum number of tokens that can be minted.
     */
    function setMaxMintableRange(
        uint8 tier,
        uint32 lower,
        uint32 upper
    ) external;

    /**
     * @dev Sets the timestamp after which, the `editionMaxMintable` drops
     *      from `editionMaxMintableUpper` to `editionMaxMintableLower.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     *
     * @param tier       The tier.
     * @param cutoffTime The timestamp.
     */
    function setCutoffTime(uint8 tier, uint32 cutoffTime) external;

    /**
     * @dev Sets whether the `mintRandomness` is enabled.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     *
     * @param tier    The tier.
     * @param enabled The boolean value.
     */
    function setMintRandomnessEnabled(uint8 tier, bool enabled) external;

    /**
     * @dev Adds a new tier.
     *
     * Calling conditions:
     * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.
     *
     * @param creation The tier creation data.
     */
    function createTier(TierCreation calldata creation) external;

    /**
     * @dev Emits an event to signal to marketplaces to refresh all the metadata.
     */
    function emitAllMetadataUpdate() external;

    // =============================================================
    //               PUBLIC / EXTERNAL VIEW FUNCTIONS
    // =============================================================

    /**
     * @dev Returns the edition info.
     * @return info The latest value.
     */
    function editionInfo() external view returns (EditionInfo memory info);

    /**
     * @dev Returns the tier info.
     * @param tier The tier.
     * @return info The latest value.
     */
    function tierInfo(uint8 tier) external view returns (TierInfo memory info);

    /**
     * @dev Returns the GA tier, which is 0.
     * @return The constant value.
     */
    function GA_TIER() external pure returns (uint8);

    /**
     * @dev Basis points denominator used in fee calculations.
     * @return The constant value.
     */
    function BPS_DENOMINATOR() external pure returns (uint16);

    /**
     * @dev Returns the minter role flag.
     *      Note: This constant will always be 2 for past and future sound protocol contracts.
     * @return The constant value.
     */
    function MINTER_ROLE() external view returns (uint256);

    /**
     * @dev Returns the admin role flag.
     *      Note: This constant will always be 1 for past and future sound protocol contracts.
     * @return The constant value.
     */
    function ADMIN_ROLE() external view returns (uint256);

    /**
     * @dev Returns the tier of the `tokenId`.
     * @param tokenId The token ID.
     * @return The latest value.
     */
    function tokenTier(uint256 tokenId) external view returns (uint8);

    /**
     * @dev Returns the tier of the `tokenId`.
     *      Note: Will NOT revert if any `tokenId` does not exist.
     *      If the token has not been minted, the tier will be zero.
     *      If the token is burned, the tier will be the tier before it was burned.
     * @param tokenId The token ID.
     * @return The latest value.
     */
    function explicitTokenTier(uint256 tokenId) external view returns (uint8);

    /**
     * @dev Returns the tiers of the `tokenIds`.
     *      Note: Will NOT revert if any `tokenId` does not exist.
     *      If the token has not been minted, the tier will be zero.
     *      If the token is burned, the tier will be the tier before it was burned.
     * @param tokenIds The token IDs.
     * @return The latest values.
     */
    function tokenTiers(uint256[] calldata tokenIds) external view returns (uint8[] memory);

    /**
     * @dev Returns an array of all the token IDs in the tier.
     * @param tier The tier.
     * @return tokenIds The array of token IDs in the tier.
     */
    function tierTokenIds(uint8 tier) external view returns (uint256[] memory tokenIds);

    /**
     * @dev Returns an array of all the token IDs in the tier, within the range [start, stop).
     * @param tier  The tier.
     * @param start The start of the range. Inclusive.
     * @param stop  The end of the range. Exclusive.
     * @return tokenIds The array of token IDs in the tier.
     */
    function tierTokenIdsIn(
        uint8 tier,
        uint256 start,
        uint256 stop
    ) external view returns (uint256[] memory tokenIds);

    /**
     * @dev Returns the index of `tokenId` in it's tier token ID array.
     * @param tokenId The token ID to find.
     * @return The index of `tokenId`. If not found, returns `type(uint256).max`.
     */
    function tierTokenIdIndex(uint256 tokenId) external view returns (uint256);

    /**
     * @dev Returns the maximum amount of tokens mintable for the tier.
     * @param tier The tier.
     * @return The configured value.
     */
    function maxMintable(uint8 tier) external view returns (uint32);

    /**
     * @dev Returns the upper bound for the maximum tokens that can be minted for the tier.
     * @param tier The tier.
     * @return The configured value.
     */
    function maxMintableUpper(uint8 tier) external view returns (uint32);

    /**
     * @dev Returns the lower bound for the maximum tokens that can be minted for the tier.
     * @param tier The tier.
     * @return The configured value.
     */
    function maxMintableLower(uint8 tier) external view returns (uint32);

    /**
     * @dev Returns the timestamp after which `maxMintable` drops from
     *      `maxMintableUpper` to `maxMintableLower`.
     * @param tier The tier.
     * @return The configured value.
     */
    function cutoffTime(uint8 tier) external view returns (uint32);

    /**
     * @dev Returns the number of tokens minted for the tier.
     * @param tier The tier.
     * @return The latest value.
     */
    function tierMinted(uint8 tier) external view returns (uint32);

    /**
     * @dev Returns the mint randomness for the tier.
     * @param tier The tier.
     * @return The latest value.
     */
    function mintRandomness(uint8 tier) external view returns (uint256);

    /**
     * @dev Returns the one-of-one token ID for the tier.
     * @param tier The tier.
     * @return The latest value.
     */
    function mintRandomnessOneOfOne(uint8 tier) external view returns (uint32);

    /**
     * @dev Returns whether the `mintRandomness` has been enabled.
     * @return The configured value.
     */
    function mintRandomnessEnabled(uint8 tier) external view returns (bool);

    /**
     * @dev Returns whether the mint has been concluded for the tier.
     * @param tier The tier.
     * @return The latest value.
     */
    function mintConcluded(uint8 tier) external view returns (bool);

    /**
     * @dev Returns the base token URI for the collection.
     * @return The configured value.
     */
    function baseURI() external view returns (string memory);

    /**
     * @dev Returns the contract URI to be used by Opensea.
     *      See: https://docs.opensea.io/docs/contract-level-metadata
     * @return The configured value.
     */
    function contractURI() external view returns (string memory);

    /**
     * @dev Returns the address of the funding recipient.
     * @return The configured value.
     */
    function fundingRecipient() external view returns (address);

    /**
     * @dev Returns the address of the metadata module.
     * @return The configured value.
     */
    function metadataModule() external view returns (address);

    /**
     * @dev Returns the royalty basis points.
     * @return The configured value.
     */
    function royaltyBPS() external view returns (uint16);

    /**
     * @dev Returns whether the tier is frozen.
     * @return The configured value.
     */
    function isFrozen(uint8 tier) external view returns (bool);

    /**
     * @dev Returns whether the metadata module is frozen.
     * @return The configured value.
     */
    function isMetadataFrozen() external view returns (bool);

    /**
     * @dev Returns whether the ability to create tiers is frozen.
     * @return The configured value.
     */
    function isCreateTierFrozen() external view returns (bool);

    /**
     * @dev Returns the next token ID to be minted.
     * @return The latest value.
     */
    function nextTokenId() external view returns (uint256);

    /**
     * @dev Returns the number of tokens minted by `owner`.
     * @param owner Address to query for number minted.
     * @return The latest value.
     */
    function numberMinted(address owner) external view returns (uint256);

    /**
     * @dev Returns the number of tokens burned by `owner`.
     * @param owner Address to query for number burned.
     * @return The latest value.
     */
    function numberBurned(address owner) external view returns (uint256);

    /**
     * @dev Returns the total amount of tokens minted.
     * @return The latest value.
     */
    function totalMinted() external view returns (uint256);

    /**
     * @dev Returns the total amount of tokens burned.
     * @return The latest value.
     */
    function totalBurned() external view returns (uint256);

    /**
     * @dev Returns the token URI of `tokenId`, but without reverting if
     *      the token does not exist.
     * @return The latest value.
     */
    function explicitTokenURI(uint256 tokenId) external view returns (string memory);

    /**
     * @dev Informs other contracts which interfaces this contract supports.
     *      Required by https://eips.ethereum.org/EIPS/eip-165
     * @param interfaceId The interface id to check.
     * @return Whether the `interfaceId` is supported.
     */
    function supportsInterface(bytes4 interfaceId)
        external
        view
        override(IERC721AUpgradeable, IERC165Upgradeable)
        returns (bool);
}

File 4 of 21 : ISuperMinterV2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import { IERC165 } from "openzeppelin/utils/introspection/IERC165.sol";

/**
 * @title ISuperMinterV2
 * @notice The interface for the generalized minter.
 */
interface ISuperMinterV2 is IERC165 {
    // =============================================================
    //                            STRUCTS
    // =============================================================

    /**
     * @dev A struct containing the arguments to create a mint.
     */
    struct MintCreation {
        // The edition address.
        address edition;
        // The base price per token.
        // For `VERIFY_SIGNATURE`, this will be the minimum limit of the signed price.
        // Will be 0 if the `tier` is `GA_TIER`.
        uint96 price;
        // The start time of the mint.
        uint32 startTime;
        // The end time of the mint.
        uint32 endTime;
        // The maximum number of tokens an account can mint in this mint.
        uint32 maxMintablePerAccount;
        // The maximum number of tokens mintable.
        uint32 maxMintable;
        // The affiliate fee BPS.
        uint16 affiliateFeeBPS;
        // The affiliate Merkle root, if any.
        bytes32 affiliateMerkleRoot;
        // The tier of the mint.
        uint8 tier;
        // The address of the platform.
        address platform;
        // The mode of the mint. Options: `DEFAULT`, `VERIFY_MERKLE`, `VERIFY_SIGNATURE`.
        uint8 mode;
        // The Merkle root hash, required if `mode` is `VERIFY_MERKLE`.
        bytes32 merkleRoot;
    }

    /**
     * @dev A struct containing the arguments for mint-to.
     */
    struct MintTo {
        // The mint ID.
        address edition;
        // The tier of the mint.
        uint8 tier;
        // The edition-tier schedule number.
        uint8 scheduleNum;
        // The address to mint to.
        address to;
        // The number of tokens to mint.
        uint32 quantity;
        // The allowlisted address. Used if `mode` is `VERIFY_MERKLE`.
        address allowlisted;
        // The allowlisted quantity. Used if `mode` is `VERIFY_MERKLE`.
        // A default zero value means no limit.
        uint32 allowlistedQuantity;
        // The allowlist Merkle proof.
        bytes32[] allowlistProof;
        // The signed price. Used if `mode` is `VERIFY_SIGNATURE`.
        uint96 signedPrice;
        // The signed quantity. Used if `mode` is `VERIFY_SIGNATURE`.
        uint32 signedQuantity;
        // The signed claimed ticket. Used if `mode` is `VERIFY_SIGNATURE`.
        uint32 signedClaimTicket;
        // The expiry timestamp for the signature. Used if `mode` is `VERIFY_SIGNATURE`.
        uint32 signedDeadline;
        // The signature by the signer. Used if `mode` is `VERIFY_SIGNATURE`.
        bytes signature;
        // The affiliate address. Optional.
        address affiliate;
        // The Merkle proof for the affiliate.
        bytes32[] affiliateProof;
        // The attribution ID, optional.
        uint256 attributionId;
    }

    /**
     * @dev A struct containing the arguments for platformAirdrop.
     */
    struct PlatformAirdrop {
        // The mint ID.
        address edition;
        // The tier of the mint.
        uint8 tier;
        // The edition-tier schedule number.
        uint8 scheduleNum;
        // The addresses to mint to.
        address[] to;
        // The signed quantity.
        uint32 signedQuantity;
        // The signed claimed ticket. Used if `mode` is `VERIFY_SIGNATURE`.
        uint32 signedClaimTicket;
        // The expiry timestamp for the signature. Used if `mode` is `VERIFY_SIGNATURE`.
        uint32 signedDeadline;
        // The signature by the signer. Used if `mode` is `VERIFY_SIGNATURE`.
        bytes signature;
    }

    /**
     * @dev A struct containing the total prices and fees.
     */
    struct TotalPriceAndFees {
        // The required Ether value.
        // (`subTotal + platformTxFlatFee + artistReward + affiliateReward + platformReward`).
        uint256 total;
        // The total price before any additive fees.
        uint256 subTotal;
        // The price per token.
        uint256 unitPrice;
        // The final artist fee (inclusive of `finalArtistReward`).
        uint256 finalArtistFee;
        // The total affiliate fee (inclusive of `finalAffiliateReward`).
        uint256 finalAffiliateFee;
        // The final platform fee
        // (inclusive of `finalPlatformReward`, `perTxFlat`, sum of `perMintBPS`).
        uint256 finalPlatformFee;
    }

    /**
     * @dev A struct containing the log data for the `Minted` event.
     */
    struct MintedLogData {
        // The number of tokens minted.
        uint32 quantity;
        // The starting token ID minted.
        uint256 fromTokenId;
        // The allowlisted address.
        address allowlisted;
        // The allowlisted quantity.
        uint32 allowlistedQuantity;
        // The signed quantity.
        uint32 signedQuantity;
        // The signed claim ticket.
        uint32 signedClaimTicket;
        // The affiliate address.
        address affiliate;
        // Whether the affiliate address is affiliated.
        bool affiliated;
        // The total price paid, inclusive of all fees.
        uint256 requiredEtherValue;
        // The price per token.
        uint256 unitPrice;
        // The final artist fee (inclusive of `finalArtistReward`).
        uint256 finalArtistFee;
        // The total affiliate fee (inclusive of `finalAffiliateReward`).
        uint256 finalAffiliateFee;
        // The final platform fee
        // (inclusive of `finalPlatformReward`, `perTxFlat`, sum of `perMintBPS`).
        uint256 finalPlatformFee;
    }

    /**
     * @dev A struct to hold the fee configuration for a platform and a tier.
     */
    struct PlatformFeeConfig {
        // The amount of reward to give to the artist per mint.
        uint96 artistMintReward;
        // The amount of reward to give to the affiliate per mint.
        uint96 affiliateMintReward;
        // The amount of reward to give to the platform per mint.
        uint96 platformMintReward;
        // If the price is greater than this, the rewards will become the threshold variants.
        uint96 thresholdPrice;
        // The amount of reward to give to the artist (`unitPrice >= thresholdPrice`).
        uint96 thresholdArtistMintReward;
        // The amount of reward to give to the affiliate (`unitPrice >= thresholdPrice`).
        uint96 thresholdAffiliateMintReward;
        // The amount of reward to give to the platform (`unitPrice >= thresholdPrice`).
        uint96 thresholdPlatformMintReward;
        // The per-transaction flat fee.
        uint96 platformTxFlatFee;
        // The per-token fee BPS.
        uint16 platformMintFeeBPS;
        // Whether the fees are active.
        bool active;
    }

    /**
     * @dev A struct containing the mint information.
     */
    struct MintInfo {
        // The mint ID.
        address edition;
        // The tier of the mint.
        uint8 tier;
        // The edition-tier schedule number.
        uint8 scheduleNum;
        // The platform address.
        address platform;
        // The base price per token.
        // For `VERIFY_SIGNATURE` this will be the minimum limit of the signed price.
        // If the `tier` is `GA_TIER`, and the `mode` is NOT `VERIFY_SIGNATURE`,
        // this value will be the GA price instead.
        uint96 price;
        // The start time of the mint.
        uint32 startTime;
        // The end time of the mint.
        uint32 endTime;
        // The maximum number of tokens an account can mint in this mint.
        uint32 maxMintablePerAccount;
        // The maximum number of tokens mintable.
        uint32 maxMintable;
        // The total number of tokens minted.
        uint32 minted;
        // The affiliate fee BPS.
        uint16 affiliateFeeBPS;
        // The mode of the mint.
        uint8 mode;
        // Whether the mint is paused.
        bool paused;
        // Whether the mint already has mints.
        bool hasMints;
        // The affiliate Merkle root, if any.
        bytes32 affiliateMerkleRoot;
        // The Merkle root hash, required if `mode` is `VERIFY_MERKLE`.
        bytes32 merkleRoot;
        // The signer address, used if `mode` is `VERIFY_SIGNATURE` or `PLATFORM_AIRDROP`.
        address signer;
    }

    // =============================================================
    //                            EVENTS
    // =============================================================

    /**
     * @dev Emitted when a new mint is created.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param creation      The mint creation struct.
     */
    event MintCreated(address indexed edition, uint8 tier, uint8 scheduleNum, MintCreation creation);

    /**
     * @dev Emitted when a mint is paused or un-paused.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param paused        Whether the mint is paused.
     */
    event PausedSet(address indexed edition, uint8 tier, uint8 scheduleNum, bool paused);

    /**
     * @dev Emitted when the time range of a mint is updated.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param startTime     The start time.
     * @param endTime       The end time.
     */
    event TimeRangeSet(address indexed edition, uint8 tier, uint8 scheduleNum, uint32 startTime, uint32 endTime);

    /**
     * @dev Emitted when the base per-token price of a mint is updated.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param price         The base per-token price.
     */
    event PriceSet(address indexed edition, uint8 tier, uint8 scheduleNum, uint96 price);

    /**
     * @dev Emitted when the max mintable per account for a mint is updated.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param value         The max mintable per account.
     */
    event MaxMintablePerAccountSet(address indexed edition, uint8 tier, uint8 scheduleNum, uint32 value);

    /**
     * @dev Emitted when the max mintable for a mint is updated.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param value         The max mintable for the mint.
     */
    event MaxMintableSet(address indexed edition, uint8 tier, uint8 scheduleNum, uint32 value);

    /**
     * @dev Emitted when the Merkle root of a mint is updated.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param merkleRoot    The Merkle root of the mint.
     */
    event MerkleRootSet(address indexed edition, uint8 tier, uint8 scheduleNum, bytes32 merkleRoot);

    /**
     * @dev Emitted when the affiliate fee BPS for a mint is updated.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param bps           The affiliate fee BPS.
     */
    event AffiliateFeeSet(address indexed edition, uint8 tier, uint8 scheduleNum, uint16 bps);

    /**
     * @dev Emitted when the affiliate Merkle root for a mint is updated.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param root          The affiliate Merkle root hash.
     */
    event AffiliateMerkleRootSet(address indexed edition, uint8 tier, uint8 scheduleNum, bytes32 root);

    /**
     * @dev Emitted when tokens are minted.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param to            The recipient of the tokens minted.
     * @param data          The mint-to log data.
     * @param attributionId The optional attribution ID.
     */
    event Minted(
        address indexed edition,
        uint8 tier,
        uint8 scheduleNum,
        address indexed to,
        MintedLogData data,
        uint256 indexed attributionId
    );

    /**
     * @dev Emitted when tokens are platform airdropped.
     * @param edition        The address of the Sound Edition.
     * @param tier           The tier.
     * @param scheduleNum    The edition-tier schedule number.
     * @param to             The recipients of the tokens minted.
     * @param signedQuantity The amount of tokens per address.
     * @param fromTokenId    The first token ID minted.
     */
    event PlatformAirdropped(
        address indexed edition,
        uint8 tier,
        uint8 scheduleNum,
        address[] to,
        uint32 signedQuantity,
        uint256 fromTokenId
    );

    /**
     * @dev Emitted when the platform fee configuration for `tier` is updated.
     * @param platform The platform address.
     * @param tier     The tier of the mint.
     * @param config   The platform fee configuration.
     */
    event PlatformFeeConfigSet(address indexed platform, uint8 tier, PlatformFeeConfig config);

    /**
     * @dev Emitted when the default platform fee configuration is updated.
     * @param platform The platform address.
     * @param config   The platform fee configuration.
     */
    event DefaultPlatformFeeConfigSet(address indexed platform, PlatformFeeConfig config);

    /**
     * @dev Emitted when affiliate fees are withdrawn.
     * @param affiliate The recipient of the fees.
     * @param accrued   The amount of Ether accrued and withdrawn.
     */
    event AffiliateFeesWithdrawn(address indexed affiliate, uint256 accrued);

    /**
     * @dev Emitted when platform fees are withdrawn.
     * @param platform  The platform address.
     * @param accrued   The amount of Ether accrued and withdrawn.
     */
    event PlatformFeesWithdrawn(address indexed platform, uint256 accrued);

    /**
     * @dev Emitted when the platform fee recipient address is updated.
     * @param platform  The platform address.
     * @param recipient The platform fee recipient address.
     */
    event PlatformFeeAddressSet(address indexed platform, address recipient);

    /**
     * @dev Emitted when the per-token price for the GA tier is set.
     * @param platform The platform address.
     * @param price    The price per token for the GA tier.
     */
    event GAPriceSet(address indexed platform, uint96 price);

    /**
     * @dev Emitted when the signer for a platform is set.
     * @param platform The platform address.
     * @param signer   The signer for the platform.
     */
    event PlatformSignerSet(address indexed platform, address signer);

    // =============================================================
    //                            ERRORS
    // =============================================================

    /**
     * @dev Exact payment required.
     * @param paid The amount of Ether paid.
     * @param required The amount of Ether required.
     */
    error WrongPayment(uint256 paid, uint256 required);

    /**
     * @dev The mint is not opened.
     * @param blockTimestamp The current block timestamp.
     * @param startTime      The opening time of the mint.
     * @param endTime        The closing time of the mint.
     */
    error MintNotOpen(uint256 blockTimestamp, uint32 startTime, uint32 endTime);

    /**
     * @dev The mint is paused.
     */
    error MintPaused();

    /**
     * @dev Cannot perform the operation when any mints exist.
     */
    error MintsAlreadyExist();

    /**
     * @dev The time range is invalid.
     */
    error InvalidTimeRange();

    /**
     * @dev The max mintable range is invalid.
     */
    error InvalidMaxMintableRange();

    /**
     * @dev The affiliate fee BPS cannot exceed the limit.
     */
    error InvalidAffiliateFeeBPS();

    /**
     * @dev The affiliate fee BPS cannot exceed the limit.
     */
    error InvalidPlatformFeeBPS();

    /**
     * @dev The affiliate fee BPS cannot exceed the limit.
     */
    error InvalidPlatformFlatFee();

    /**
     * @dev Cannot mint more than the maximum limit per account.
     */
    error ExceedsMaxPerAccount();

    /**
     * @dev Cannot mint more than the maximum supply.
     */
    error ExceedsMintSupply();

    /**
     * @dev Cannot mint more than the signed quantity.
     */
    error ExceedsSignedQuantity();

    /**
     * @dev The signature is invalid.
     */
    error InvalidSignature();

    /**
     * @dev The signature has expired.
     */
    error SignatureExpired();

    /**
     * @dev The signature claim ticket has already been used.
     */
    error SignatureAlreadyUsed();

    /**
     * @dev The Merkle root cannot be empty.
     */
    error MerkleRootIsEmpty();

    /**
     * @dev The Merkle proof is invalid.
     */
    error InvalidMerkleProof();

    /**
     * @dev The caller has not been delegated via delegate cash.
     */
    error CallerNotDelegated();

    /**
     * @dev The max mintable amount per account cannot be zero.
     */
    error MaxMintablePerAccountIsZero();

    /**
     * @dev The max mintable value cannot be zero.
     */
    error MaxMintableIsZero();

    /**
     * @dev The plaform fee address cannot be the zero address.
     */
    error PlatformFeeAddressIsZero();

    /**
     * @dev The mint does not exist.
     */
    error MintDoesNotExist();

    /**
     * @dev The affiliate provided is invalid.
     */
    error InvalidAffiliate();

    /**
     * @dev The mint mode provided is invalid.
     */
    error InvalidMode();

    /**
     * @dev The signed price is too low.
     */
    error SignedPriceTooLow();

    /**
     * @dev The platform fee configuration provided is invalid.
     */
    error InvalidPlatformFeeConfig();

    /**
     * @dev The parameter cannot be configured.
     */
    error NotConfigurable();

    // =============================================================
    //               PUBLIC / EXTERNAL WRITE FUNCTIONS
    // =============================================================

    /**
     * @dev Creates a mint.
     * @param c The mint creation struct.
     * @return scheduleNum The mint ID.
     */
    function createEditionMint(MintCreation calldata c) external returns (uint8 scheduleNum);

    /**
     * @dev Performs a mint.
     * @param p The mint-to parameters.
     * @return fromTokenId The first token ID minted.
     */
    function mintTo(MintTo calldata p) external payable returns (uint256 fromTokenId);

    /**
     * @dev Performs a platform airdrop.
     * @param p The platform airdrop parameters.
     * @return fromTokenId The first token ID minted.
     */
    function platformAirdrop(PlatformAirdrop calldata p) external returns (uint256 fromTokenId);

    /**
     * @dev Sets the price of the mint.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param price         The price per token.
     */
    function setPrice(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint96 price
    ) external;

    /**
     * @dev Pause or unpase the the mint.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param paused        Whether to pause the mint.
     */
    function setPaused(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        bool paused
    ) external;

    /**
     * @dev Sets the time range for the the mint.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param startTime     The mint start time.
     * @param endTime       The mint end time.
     */
    function setTimeRange(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32 startTime,
        uint32 endTime
    ) external;

    /**
     * @dev Sets the start time for the the mint.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param startTime     The mint start time.
     */
    function setStartTime(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32 startTime
    ) external;

    /**
     * @dev Sets the affiliate fee BPS for the mint.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param bps           The fee BPS.
     */
    function setAffiliateFee(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint16 bps
    ) external;

    /**
     * @dev Sets the affiliate Merkle root for the mint.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param root          The affiliate Merkle root.
     */
    function setAffiliateMerkleRoot(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        bytes32 root
    ) external;

    /**
     * @dev Sets the max mintable per account.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param value         The max mintable per account.
     */
    function setMaxMintablePerAccount(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32 value
    ) external;

    /**
     * @dev Sets the max mintable for the mint.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param value         The max mintable for the mint.
     */
    function setMaxMintable(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32 value
    ) external;

    /**
     * @dev Sets the mode for the mint. The mint mode must be `VERIFY_MERKLE`.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param merkleRoot    The Merkle root of the mint.
     */
    function setMerkleRoot(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        bytes32 merkleRoot
    ) external;

    /**
     * @dev Withdraws all accrued fees of the affiliate, to the affiliate.
     * @param affiliate The affiliate address.
     */
    function withdrawForAffiliate(address affiliate) external;

    /**
     * @dev Withdraws all accrued fees of the platform, to the their fee address.
     * @param platform The platform address.
     */
    function withdrawForPlatform(address platform) external;

    /**
     * @dev Allows the caller, as a platform, to set their fee address
     * @param recipient The platform fee address of the caller.
     */
    function setPlatformFeeAddress(address recipient) external;

    /**
     * @dev Allows the caller, as a platform, to set their per-tier fee configuration.
     * @param tier The tier of the mint.
     * @param c    The platform fee configuration struct.
     */
    function setPlatformFeeConfig(uint8 tier, PlatformFeeConfig memory c) external;

    /**
     * @dev Allows the caller, as a platform, to set their default fee configuration.
     * @param c    The platform fee configuration struct.
     */
    function setDefaultPlatformFeeConfig(PlatformFeeConfig memory c) external;

    /**
     * @dev Allows the platform to set the price for the GA tier.
     * @param price The price per token for the GA tier.
     */
    function setGAPrice(uint96 price) external;

    /**
     * @dev Allows the platform to set their signer.
     * @param signer The signer for the platform.
     */
    function setPlatformSigner(address signer) external;

    // =============================================================
    //               PUBLIC / EXTERNAL VIEW FUNCTIONS
    // =============================================================

    /**
     * @dev Returns the GA tier. Which is 0.
     * @return The constant value.
     */
    function GA_TIER() external pure returns (uint8);

    /**
     * @dev The EIP-712 typehash for signed mints.
     * @return The constant value.
     */
    function MINT_TO_TYPEHASH() external pure returns (bytes32);

    /**
     * @dev The EIP-712 typehash for platform airdrop mints.
     * @return The constant value.
     */
    function PLATFORM_AIRDROP_TYPEHASH() external pure returns (bytes32);

    /**
     * @dev The default mint mode.
     * @return The constant value.
     */
    function DEFAULT() external pure returns (uint8);

    /**
     * @dev The mint mode for Merkle drops.
     * @return The constant value.
     */
    function VERIFY_MERKLE() external pure returns (uint8);

    /**
     * @dev The mint mode for Merkle drops.
     * @return The constant value.
     */
    function VERIFY_SIGNATURE() external pure returns (uint8);

    /**
     * @dev The mint mode for platform airdrop.
     * @return The constant value.
     */
    function PLATFORM_AIRDROP() external pure returns (uint8);

    /**
     * @dev The denominator used in BPS fee calculations.
     * @return The constant value.
     */
    function BPS_DENOMINATOR() external pure returns (uint16);

    /**
     * @dev The maximum affiliate fee BPS.
     * @return The constant value.
     */
    function MAX_AFFILIATE_FEE_BPS() external pure returns (uint16);

    /**
     * @dev The maximum per-mint platform fee BPS.
     * @return The constant value.
     */
    function MAX_PLATFORM_PER_MINT_FEE_BPS() external pure returns (uint16);

    /**
     * @dev The maximum per-mint reward. Applies to artists, affiliates, platform.
     * @return The constant value.
     */
    function MAX_PER_MINT_REWARD() external pure returns (uint96);

    /**
     * @dev The maximum platform per-transaction flat fee.
     * @return The constant value.
     */
    function MAX_PLATFORM_PER_TX_FLAT_FEE() external pure returns (uint96);

    /**
     * @dev Returns the amount of fees accrued by the platform.
     * @param platform The platform address.
     * @return The latest value.
     */
    function platformFeesAccrued(address platform) external view returns (uint256);

    /**
     * @dev Returns the fee recipient for the platform.
     * @param platform The platform address.
     * @return The configured value.
     */
    function platformFeeAddress(address platform) external view returns (address);

    /**
     * @dev Returns the amount of fees accrued by the affiliate.
     * @param affiliate The affiliate address.
     * @return The latest value.
     */
    function affiliateFeesAccrued(address affiliate) external view returns (uint256);

    /**
     * @dev Returns the EIP-712 digest of the mint-to data for signature mints.
     * @param p The mint-to parameters.
     * @return The computed value.
     */
    function computeMintToDigest(MintTo calldata p) external view returns (bytes32);

    /**
     * @dev Returns the EIP-712 digest of the mint-to data for platform airdrops.
     * @param p The platform airdrop parameters.
     * @return The computed value.
     */
    function computePlatformAirdropDigest(PlatformAirdrop calldata p) external view returns (bytes32);

    /**
     * @dev Returns the total price and fees for the mint.
     * @param edition           The address of the Sound Edition.
     * @param tier              The tier.
     * @param scheduleNum       The edition-tier schedule number.
     * @param quantity          How many tokens to mint.
     * @param hasValidAffiliate Whether there is a valid affiliate for the mint.
     * @return A struct containing the total price and fees.
     */
    function totalPriceAndFees(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32 quantity,
        bool hasValidAffiliate
    ) external view returns (TotalPriceAndFees memory);

    /**
     * @dev Returns the total price and fees for the mint.
     * @param edition          The address of the Sound Edition.
     * @param tier             The tier.
     * @param scheduleNum      The edition-tier schedule number.
     * @param quantity         How many tokens to mint.
     * @param signedPrice      The signed price.
     * @param hasValidAffiliate Whether there is a valid affiliate for the mint.
     * @return A struct containing the total price and fees.
     */
    function totalPriceAndFeesWithSignedPrice(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32 quantity,
        uint96 signedPrice,
        bool hasValidAffiliate
    ) external view returns (TotalPriceAndFees memory);

    /**
     * @dev Returns the GA price for the platform.
     * @param platform The platform address.
     * @return The configured value.
     */
    function gaPrice(address platform) external view returns (uint96);

    /**
     * @dev Returns the signer for the platform.
     * @param platform The platform address.
     * @return The configured value.
     */
    function platformSigner(address platform) external view returns (address);

    /**
     * @dev Returns the next mint schedule number for the edition-tier.
     * @param edition The Sound Edition address.
     * @param tier    The tier.
     * @return The next schedule number for the edition-tier.
     */
    function nextScheduleNum(address edition, uint8 tier) external view returns (uint8);

    /**
     * @dev Returns the number of tokens minted by `collector` for the mint.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param collector     The address which tokens are minted to,
     *                      or in the case of `VERIFY_MERKLE`, is the allowlisted address.
     * @return The number of tokens minted.
     */
    function numberMinted(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        address collector
    ) external view returns (uint32);

    /**
     * @dev Returns whether the affiliate is affiliated for the mint
     * @param edition        The address of the Sound Edition.
     * @param tier           The tier.
     * @param scheduleNum    The edition-tier schedule number.
     * @param affiliate      The affiliate address.
     * @param affiliateProof The Merkle proof for the affiliate.
     * @return The result.
     */
    function isAffiliatedWithProof(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        address affiliate,
        bytes32[] calldata affiliateProof
    ) external view returns (bool);

    /**
     * @dev Returns whether the affiliate is affiliated for the mint.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param affiliate     The affiliate address.
     * @return A boolean on whether the affiliate is affiliated for the mint.
     */
    function isAffiliated(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        address affiliate
    ) external view returns (bool);

    /**
     * @dev Returns whether the claim tickets have been used.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @param claimTickets  An array of claim tickets.
     * @return An array of bools, where true means that a ticket has been used.
     */
    function checkClaimTickets(
        address edition,
        uint8 tier,
        uint8 scheduleNum,
        uint32[] calldata claimTickets
    ) external view returns (bool[] memory);

    /**
     * @dev Returns the platform fee configuration for the tier.
     * @param platform The platform address.
     * @param tier     The tier of the mint.
     * @return The platform fee configuration struct.
     */
    function platformFeeConfig(address platform, uint8 tier) external view returns (PlatformFeeConfig memory);

    /**
     * @dev Returns the default platform fee configuration.
     * @param platform The platform address.
     * @return The platform fee configuration struct.
     */
    function defaultPlatformFeeConfig(address platform) external view returns (PlatformFeeConfig memory);

    /**
     * @dev Returns the effective platform fee configuration.
     * @param platform The platform address.
     * @param tier     The tier of the mint.
     * @return The platform fee configuration struct.
     */
    function effectivePlatformFeeConfig(address platform, uint8 tier) external view returns (PlatformFeeConfig memory);

    /**
     * @dev Returns an array of mint information structs pertaining to the mint.
     * @param edition The Sound Edition address.
     * @return An array of mint information structs.
     */
    function mintInfoList(address edition) external view returns (MintInfo[] memory);

    /**
     * @dev Returns information pertaining to the mint.
     * @param edition       The address of the Sound Edition.
     * @param tier          The tier.
     * @param scheduleNum   The edition-tier schedule number.
     * @return The mint info struct.
     */
    function mintInfo(
        address edition,
        uint8 tier,
        uint8 scheduleNum
    ) external view returns (MintInfo memory);

    /**
     * @dev Retuns the EIP-712 name for the contract.
     * @return The constant value.
     */
    function name() external pure returns (string memory);

    /**
     * @dev Retuns the EIP-712 version for the contract.
     * @return The constant value.
     */
    function version() external pure returns (string memory);
}

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

pragma solidity ^0.8.0;

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

File 6 of 21 : SafeTransferLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
///
/// @dev Note:
/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.
/// - For ERC20s, this implementation won't check that a token has code,
///   responsibility is delegated to the caller.
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.
    uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ETH OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
    //
    // The regular variants:
    // - Forwards all remaining gas to the target.
    // - Reverts if the target reverts.
    // - Reverts if the current contract has insufficient balance.
    //
    // The force variants:
    // - Forwards with an optional gas stipend
    //   (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
    // - If the target reverts, or if the gas stipend is exhausted,
    //   creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
    //   Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
    // - Reverts if the current contract has insufficient balance.
    //
    // The try variants:
    // - Forwards with a mandatory gas stipend.
    // - Instead of reverting, returns whether the transfer succeeded.

    /// @dev Sends `amount` (in wei) ETH to `to`.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`.
    function safeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer all the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // forgefmt: disable-next-item
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function trySafeTransferAllETH(address to, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC20 OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends all of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have their entire balance approved for
    /// the current contract to manage.
    function safeTransferAllFrom(address token, address from, address to)
        internal
        returns (uint256 amount)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
            amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransfer(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sends all of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransferAll(address token, address to) internal returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, address()) // Store the address of the current contract.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x14, to) // Store the `to` argument.
            amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// Reverts upon failure.
    function safeApprove(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
    /// then retries the approval again (some tokens, e.g. USDT, requires this).
    /// Reverts upon failure.
    function safeApproveWithRetry(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, retrying upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x34, 0) // Store 0 for the `amount`.
                mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
                pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.
                mstore(0x34, amount) // Store back the original `amount`.
                // Retry the approval, reverting upon failure.
                if iszero(
                    and(
                        or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                        call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    )
                ) {
                    mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Returns the amount of ERC20 `token` owned by `account`.
    /// Returns zero if the `token` does not exist.
    function balanceOf(address token, address account) internal view returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, account) // Store the `account` argument.
            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            amount :=
                mul(
                    mload(0x20),
                    and( // The arguments of `and` are evaluated from right to left.
                        gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                        staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
                    )
                )
        }
    }
}

File 7 of 21 : EIP712.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Contract for EIP-712 typed structured data hashing and signing.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol)
/// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol)
///
/// @dev Note, this implementation:
/// - Uses `address(this)` for the `verifyingContract` field.
/// - Does NOT use the optional EIP-712 salt.
/// - Does NOT use any EIP-712 extensions.
/// This is for simplicity and to save gas.
/// If you need to customize, please fork / modify accordingly.
abstract contract EIP712 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  CONSTANTS AND IMMUTABLES                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
    bytes32 internal constant _DOMAIN_TYPEHASH =
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    uint256 private immutable _cachedThis;
    uint256 private immutable _cachedChainId;
    bytes32 private immutable _cachedNameHash;
    bytes32 private immutable _cachedVersionHash;
    bytes32 private immutable _cachedDomainSeparator;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CONSTRUCTOR                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Cache the hashes for cheaper runtime gas costs.
    /// In the case of upgradeable contracts (i.e. proxies),
    /// or if the chain id changes due to a hard fork,
    /// the domain separator will be seamlessly calculated on-the-fly.
    constructor() {
        _cachedThis = uint256(uint160(address(this)));
        _cachedChainId = block.chainid;

        string memory name;
        string memory version;
        if (!_domainNameAndVersionMayChange()) (name, version) = _domainNameAndVersion();
        bytes32 nameHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(name));
        bytes32 versionHash =
            _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(version));
        _cachedNameHash = nameHash;
        _cachedVersionHash = versionHash;

        bytes32 separator;
        if (!_domainNameAndVersionMayChange()) {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Load the free memory pointer.
                mstore(m, _DOMAIN_TYPEHASH)
                mstore(add(m, 0x20), nameHash)
                mstore(add(m, 0x40), versionHash)
                mstore(add(m, 0x60), chainid())
                mstore(add(m, 0x80), address())
                separator := keccak256(m, 0xa0)
            }
        }
        _cachedDomainSeparator = separator;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   FUNCTIONS TO OVERRIDE                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Please override this function to return the domain name and version.
    /// ```
    ///     function _domainNameAndVersion()
    ///         internal
    ///         pure
    ///         virtual
    ///         returns (string memory name, string memory version)
    ///     {
    ///         name = "Solady";
    ///         version = "1";
    ///     }
    /// ```
    ///
    /// Note: If the returned result may change after the contract has been deployed,
    /// you must override `_domainNameAndVersionMayChange()` to return true.
    function _domainNameAndVersion()
        internal
        view
        virtual
        returns (string memory name, string memory version);

    /// @dev Returns if `_domainNameAndVersion()` may change
    /// after the contract has been deployed (i.e. after the constructor).
    /// Default: false.
    function _domainNameAndVersionMayChange() internal pure virtual returns (bool result) {}

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the EIP-712 domain separator.
    function _domainSeparator() internal view virtual returns (bytes32 separator) {
        if (_domainNameAndVersionMayChange()) {
            separator = _buildDomainSeparator();
        } else {
            separator = _cachedDomainSeparator;
            if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator();
        }
    }

    /// @dev Returns the hash of the fully encoded EIP-712 message for this domain,
    /// given `structHash`, as defined in
    /// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct.
    ///
    /// The hash can be used together with {ECDSA-recover} to obtain the signer of a message:
    /// ```
    ///     bytes32 digest = _hashTypedData(keccak256(abi.encode(
    ///         keccak256("Mail(address to,string contents)"),
    ///         mailTo,
    ///         keccak256(bytes(mailContents))
    ///     )));
    ///     address signer = ECDSA.recover(digest, signature);
    /// ```
    function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest) {
        // We will use `digest` to store the domain separator to save a bit of gas.
        if (_domainNameAndVersionMayChange()) {
            digest = _buildDomainSeparator();
        } else {
            digest = _cachedDomainSeparator;
            if (_cachedDomainSeparatorInvalidated()) digest = _buildDomainSeparator();
        }
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the digest.
            mstore(0x00, 0x1901000000000000) // Store "\x19\x01".
            mstore(0x1a, digest) // Store the domain separator.
            mstore(0x3a, structHash) // Store the struct hash.
            digest := keccak256(0x18, 0x42)
            // Restore the part of the free memory slot that was overwritten.
            mstore(0x3a, 0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    EIP-5267 OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev See: https://eips.ethereum.org/EIPS/eip-5267
    function eip712Domain()
        public
        view
        virtual
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        fields = hex"0f"; // `0b01111`.
        (name, version) = _domainNameAndVersion();
        chainId = block.chainid;
        verifyingContract = address(this);
        salt = salt; // `bytes32(0)`.
        extensions = extensions; // `new uint256[](0)`.
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the EIP-712 domain separator.
    function _buildDomainSeparator() private view returns (bytes32 separator) {
        // We will use `separator` to store the name hash to save a bit of gas.
        bytes32 versionHash;
        if (_domainNameAndVersionMayChange()) {
            (string memory name, string memory version) = _domainNameAndVersion();
            separator = keccak256(bytes(name));
            versionHash = keccak256(bytes(version));
        } else {
            separator = _cachedNameHash;
            versionHash = _cachedVersionHash;
        }
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Load the free memory pointer.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), separator) // Name hash.
            mstore(add(m, 0x40), versionHash)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            separator := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns if the cached domain separator has been invalidated.
    function _cachedDomainSeparatorInvalidated() private view returns (bool result) {
        uint256 cachedChainId = _cachedChainId;
        uint256 cachedThis = _cachedThis;
        /// @solidity memory-safe-assembly
        assembly {
            result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis)))
        }
    }
}

File 8 of 21 : MerkleProofLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol)
library MerkleProofLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*            MERKLE PROOF VERIFICATION OPERATIONS            */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf)
        internal
        pure
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if mload(proof) {
                // Initialize `offset` to the offset of `proof` elements in memory.
                let offset := add(proof, 0x20)
                // Left shift by 5 is equivalent to multiplying by 0x20.
                let end := add(offset, shl(5, mload(proof)))
                // Iterate over proof elements to compute root hash.
                for {} 1 {} {
                    // Slot of `leaf` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(leaf, mload(offset)))
                    // Store elements to hash contiguously in scratch space.
                    // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
                    mstore(scratch, leaf)
                    mstore(xor(scratch, 0x20), mload(offset))
                    // Reuse `leaf` to store the hash to reduce stack operations.
                    leaf := keccak256(0x00, 0x40)
                    offset := add(offset, 0x20)
                    if iszero(lt(offset, end)) { break }
                }
            }
            isValid := eq(leaf, root)
        }
    }

    /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf)
        internal
        pure
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if proof.length {
                // Left shift by 5 is equivalent to multiplying by 0x20.
                let end := add(proof.offset, shl(5, proof.length))
                // Initialize `offset` to the offset of `proof` in the calldata.
                let offset := proof.offset
                // Iterate over proof elements to compute root hash.
                for {} 1 {} {
                    // Slot of `leaf` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(leaf, calldataload(offset)))
                    // Store elements to hash contiguously in scratch space.
                    // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
                    mstore(scratch, leaf)
                    mstore(xor(scratch, 0x20), calldataload(offset))
                    // Reuse `leaf` to store the hash to reduce stack operations.
                    leaf := keccak256(0x00, 0x40)
                    offset := add(offset, 0x20)
                    if iszero(lt(offset, end)) { break }
                }
            }
            isValid := eq(leaf, root)
        }
    }

    /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
    /// given `proof` and `flags`.
    ///
    /// Note:
    /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length`
    ///   will always return false.
    /// - The sum of the lengths of `proof` and `leaves` must never overflow.
    /// - Any non-zero word in the `flags` array is treated as true.
    /// - The memory offset of `proof` must be non-zero
    ///   (i.e. `proof` is not pointing to the scratch space).
    function verifyMultiProof(
        bytes32[] memory proof,
        bytes32 root,
        bytes32[] memory leaves,
        bool[] memory flags
    ) internal pure returns (bool isValid) {
        // Rebuilds the root by consuming and producing values on a queue.
        // The queue starts with the `leaves` array, and goes into a `hashes` array.
        // After the process, the last element on the queue is verified
        // to be equal to the `root`.
        //
        // The `flags` array denotes whether the sibling
        // should be popped from the queue (`flag == true`), or
        // should be popped from the `proof` (`flag == false`).
        /// @solidity memory-safe-assembly
        assembly {
            // Cache the lengths of the arrays.
            let leavesLength := mload(leaves)
            let proofLength := mload(proof)
            let flagsLength := mload(flags)

            // Advance the pointers of the arrays to point to the data.
            leaves := add(0x20, leaves)
            proof := add(0x20, proof)
            flags := add(0x20, flags)

            // If the number of flags is correct.
            for {} eq(add(leavesLength, proofLength), add(flagsLength, 1)) {} {
                // For the case where `proof.length + leaves.length == 1`.
                if iszero(flagsLength) {
                    // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`.
                    isValid := eq(mload(xor(leaves, mul(xor(proof, leaves), proofLength))), root)
                    break
                }

                // The required final proof offset if `flagsLength` is not zero, otherwise zero.
                let proofEnd := add(proof, shl(5, proofLength))
                // We can use the free memory space for the queue.
                // We don't need to allocate, since the queue is temporary.
                let hashesFront := mload(0x40)
                // Copy the leaves into the hashes.
                // Sometimes, a little memory expansion costs less than branching.
                // Should cost less, even with a high free memory offset of 0x7d00.
                leavesLength := shl(5, leavesLength)
                for { let i := 0 } iszero(eq(i, leavesLength)) { i := add(i, 0x20) } {
                    mstore(add(hashesFront, i), mload(add(leaves, i)))
                }
                // Compute the back of the hashes.
                let hashesBack := add(hashesFront, leavesLength)
                // This is the end of the memory for the queue.
                // We recycle `flagsLength` to save on stack variables (sometimes save gas).
                flagsLength := add(hashesBack, shl(5, flagsLength))

                for {} 1 {} {
                    // Pop from `hashes`.
                    let a := mload(hashesFront)
                    // Pop from `hashes`.
                    let b := mload(add(hashesFront, 0x20))
                    hashesFront := add(hashesFront, 0x40)

                    // If the flag is false, load the next proof,
                    // else, pops from the queue.
                    if iszero(mload(flags)) {
                        // Loads the next proof.
                        b := mload(proof)
                        proof := add(proof, 0x20)
                        // Unpop from `hashes`.
                        hashesFront := sub(hashesFront, 0x20)
                    }

                    // Advance to the next flag.
                    flags := add(flags, 0x20)

                    // Slot of `a` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(a, b))
                    // Hash the scratch space and push the result onto the queue.
                    mstore(scratch, a)
                    mstore(xor(scratch, 0x20), b)
                    mstore(hashesBack, keccak256(0x00, 0x40))
                    hashesBack := add(hashesBack, 0x20)
                    if iszero(lt(hashesBack, flagsLength)) { break }
                }
                isValid :=
                    and(
                        // Checks if the last value in the queue is same as the root.
                        eq(mload(sub(hashesBack, 0x20)), root),
                        // And whether all the proofs are used, if required.
                        eq(proofEnd, proof)
                    )
                break
            }
        }
    }

    /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
    /// given `proof` and `flags`.
    ///
    /// Note:
    /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length`
    ///   will always return false.
    /// - Any non-zero word in the `flags` array is treated as true.
    /// - The calldata offset of `proof` must be non-zero
    ///   (i.e. `proof` is from a regular Solidity function with a 4-byte selector).
    function verifyMultiProofCalldata(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32[] calldata leaves,
        bool[] calldata flags
    ) internal pure returns (bool isValid) {
        // Rebuilds the root by consuming and producing values on a queue.
        // The queue starts with the `leaves` array, and goes into a `hashes` array.
        // After the process, the last element on the queue is verified
        // to be equal to the `root`.
        //
        // The `flags` array denotes whether the sibling
        // should be popped from the queue (`flag == true`), or
        // should be popped from the `proof` (`flag == false`).
        /// @solidity memory-safe-assembly
        assembly {
            // If the number of flags is correct.
            for {} eq(add(leaves.length, proof.length), add(flags.length, 1)) {} {
                // For the case where `proof.length + leaves.length == 1`.
                if iszero(flags.length) {
                    // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`.
                    // forgefmt: disable-next-item
                    isValid := eq(
                        calldataload(
                            xor(leaves.offset, mul(xor(proof.offset, leaves.offset), proof.length))
                        ),
                        root
                    )
                    break
                }

                // The required final proof offset if `flagsLength` is not zero, otherwise zero.
                let proofEnd := add(proof.offset, shl(5, proof.length))
                // We can use the free memory space for the queue.
                // We don't need to allocate, since the queue is temporary.
                let hashesFront := mload(0x40)
                // Copy the leaves into the hashes.
                // Sometimes, a little memory expansion costs less than branching.
                // Should cost less, even with a high free memory offset of 0x7d00.
                calldatacopy(hashesFront, leaves.offset, shl(5, leaves.length))
                // Compute the back of the hashes.
                let hashesBack := add(hashesFront, shl(5, leaves.length))
                // This is the end of the memory for the queue.
                // We recycle `flagsLength` to save on stack variables (sometimes save gas).
                flags.length := add(hashesBack, shl(5, flags.length))

                // We don't need to make a copy of `proof.offset` or `flags.offset`,
                // as they are pass-by-value (this trick may not always save gas).

                for {} 1 {} {
                    // Pop from `hashes`.
                    let a := mload(hashesFront)
                    // Pop from `hashes`.
                    let b := mload(add(hashesFront, 0x20))
                    hashesFront := add(hashesFront, 0x40)

                    // If the flag is false, load the next proof,
                    // else, pops from the queue.
                    if iszero(calldataload(flags.offset)) {
                        // Loads the next proof.
                        b := calldataload(proof.offset)
                        proof.offset := add(proof.offset, 0x20)
                        // Unpop from `hashes`.
                        hashesFront := sub(hashesFront, 0x20)
                    }

                    // Advance to the next flag offset.
                    flags.offset := add(flags.offset, 0x20)

                    // Slot of `a` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(a, b))
                    // Hash the scratch space and push the result onto the queue.
                    mstore(scratch, a)
                    mstore(xor(scratch, 0x20), b)
                    mstore(hashesBack, keccak256(0x00, 0x40))
                    hashesBack := add(hashesBack, 0x20)
                    if iszero(lt(hashesBack, flags.length)) { break }
                }
                isValid :=
                    and(
                        // Checks if the last value in the queue is same as the root.
                        eq(mload(sub(hashesBack, 0x20)), root),
                        // And whether all the proofs are used, if required.
                        eq(proofEnd, proof.offset)
                    )
                break
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   EMPTY CALLDATA HELPERS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an empty calldata bytes32 array.
    function emptyProof() internal pure returns (bytes32[] calldata proof) {
        /// @solidity memory-safe-assembly
        assembly {
            proof.length := 0
        }
    }

    /// @dev Returns an empty calldata bytes32 array.
    function emptyLeaves() internal pure returns (bytes32[] calldata leaves) {
        /// @solidity memory-safe-assembly
        assembly {
            leaves.length := 0
        }
    }

    /// @dev Returns an empty calldata bool array.
    function emptyFlags() internal pure returns (bool[] calldata flags) {
        /// @solidity memory-safe-assembly
        assembly {
            flags.length := 0
        }
    }
}

File 9 of 21 : LibBitmap.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

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

/// @notice Library for storage of packed unsigned booleans.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBitmap.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibBitmap.sol)
/// @author Modified from Solidity-Bits (https://github.com/estarriolvetch/solidity-bits/blob/main/contracts/BitMaps.sol)
library LibBitmap {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The constant returned when a bitmap scan does not find a result.
    uint256 internal constant NOT_FOUND = type(uint256).max;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STRUCTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev A bitmap in storage.
    struct Bitmap {
        mapping(uint256 => uint256) map;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         OPERATIONS                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the boolean value of the bit at `index` in `bitmap`.
    function get(Bitmap storage bitmap, uint256 index) internal view returns (bool isSet) {
        // It is better to set `isSet` to either 0 or 1, than zero vs non-zero.
        // Both cost the same amount of gas, but the former allows the returned value
        // to be reused without cleaning the upper bits.
        uint256 b = (bitmap.map[index >> 8] >> (index & 0xff)) & 1;
        /// @solidity memory-safe-assembly
        assembly {
            isSet := b
        }
    }

    /// @dev Updates the bit at `index` in `bitmap` to true.
    function set(Bitmap storage bitmap, uint256 index) internal {
        bitmap.map[index >> 8] |= (1 << (index & 0xff));
    }

    /// @dev Updates the bit at `index` in `bitmap` to false.
    function unset(Bitmap storage bitmap, uint256 index) internal {
        bitmap.map[index >> 8] &= ~(1 << (index & 0xff));
    }

    /// @dev Flips the bit at `index` in `bitmap`.
    /// Returns the boolean result of the flipped bit.
    function toggle(Bitmap storage bitmap, uint256 index) internal returns (bool newIsSet) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, bitmap.slot)
            mstore(0x00, shr(8, index))
            let storageSlot := keccak256(0x00, 0x40)
            let shift := and(index, 0xff)
            let storageValue := xor(sload(storageSlot), shl(shift, 1))
            // It makes sense to return the `newIsSet`,
            // as it allow us to skip an additional warm `sload`,
            // and it costs minimal gas (about 15),
            // which may be optimized away if the returned value is unused.
            newIsSet := and(1, shr(shift, storageValue))
            sstore(storageSlot, storageValue)
        }
    }

    /// @dev Updates the bit at `index` in `bitmap` to `shouldSet`.
    function setTo(Bitmap storage bitmap, uint256 index, bool shouldSet) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, bitmap.slot)
            mstore(0x00, shr(8, index))
            let storageSlot := keccak256(0x00, 0x40)
            let storageValue := sload(storageSlot)
            let shift := and(index, 0xff)
            sstore(
                storageSlot,
                // Unsets the bit at `shift` via `and`, then sets its new value via `or`.
                or(and(storageValue, not(shl(shift, 1))), shl(shift, iszero(iszero(shouldSet))))
            )
        }
    }

    /// @dev Consecutively sets `amount` of bits starting from the bit at `start`.
    function setBatch(Bitmap storage bitmap, uint256 start, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let max := not(0)
            let shift := and(start, 0xff)
            mstore(0x20, bitmap.slot)
            mstore(0x00, shr(8, start))
            if iszero(lt(add(shift, amount), 257)) {
                let storageSlot := keccak256(0x00, 0x40)
                sstore(storageSlot, or(sload(storageSlot), shl(shift, max)))
                let bucket := add(mload(0x00), 1)
                let bucketEnd := add(mload(0x00), shr(8, add(amount, shift)))
                amount := and(add(amount, shift), 0xff)
                shift := 0
                for {} iszero(eq(bucket, bucketEnd)) { bucket := add(bucket, 1) } {
                    mstore(0x00, bucket)
                    sstore(keccak256(0x00, 0x40), max)
                }
                mstore(0x00, bucket)
            }
            let storageSlot := keccak256(0x00, 0x40)
            sstore(storageSlot, or(sload(storageSlot), shl(shift, shr(sub(256, amount), max))))
        }
    }

    /// @dev Consecutively unsets `amount` of bits starting from the bit at `start`.
    function unsetBatch(Bitmap storage bitmap, uint256 start, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let shift := and(start, 0xff)
            mstore(0x20, bitmap.slot)
            mstore(0x00, shr(8, start))
            if iszero(lt(add(shift, amount), 257)) {
                let storageSlot := keccak256(0x00, 0x40)
                sstore(storageSlot, and(sload(storageSlot), not(shl(shift, not(0)))))
                let bucket := add(mload(0x00), 1)
                let bucketEnd := add(mload(0x00), shr(8, add(amount, shift)))
                amount := and(add(amount, shift), 0xff)
                shift := 0
                for {} iszero(eq(bucket, bucketEnd)) { bucket := add(bucket, 1) } {
                    mstore(0x00, bucket)
                    sstore(keccak256(0x00, 0x40), 0)
                }
                mstore(0x00, bucket)
            }
            let storageSlot := keccak256(0x00, 0x40)
            sstore(
                storageSlot, and(sload(storageSlot), not(shl(shift, shr(sub(256, amount), not(0)))))
            )
        }
    }

    /// @dev Returns number of set bits within a range by
    /// scanning `amount` of bits starting from the bit at `start`.
    function popCount(Bitmap storage bitmap, uint256 start, uint256 amount)
        internal
        view
        returns (uint256 count)
    {
        unchecked {
            uint256 bucket = start >> 8;
            uint256 shift = start & 0xff;
            if (!(amount + shift < 257)) {
                count = LibBit.popCount(bitmap.map[bucket] >> shift);
                uint256 bucketEnd = bucket + ((amount + shift) >> 8);
                amount = (amount + shift) & 0xff;
                shift = 0;
                for (++bucket; bucket != bucketEnd; ++bucket) {
                    count += LibBit.popCount(bitmap.map[bucket]);
                }
            }
            count += LibBit.popCount((bitmap.map[bucket] >> shift) << (256 - amount));
        }
    }

    /// @dev Returns the index of the most significant set bit before the bit at `before`.
    /// If no set bit is found, returns `NOT_FOUND`.
    function findLastSet(Bitmap storage bitmap, uint256 before)
        internal
        view
        returns (uint256 setBitIndex)
    {
        uint256 bucket;
        uint256 bucketBits;
        /// @solidity memory-safe-assembly
        assembly {
            setBitIndex := not(0)
            bucket := shr(8, before)
            mstore(0x00, bucket)
            mstore(0x20, bitmap.slot)
            let offset := and(0xff, not(before)) // `256 - (255 & before) - 1`.
            bucketBits := shr(offset, shl(offset, sload(keccak256(0x00, 0x40))))
            if iszero(or(bucketBits, iszero(bucket))) {
                for {} 1 {} {
                    bucket := add(bucket, setBitIndex) // `sub(bucket, 1)`.
                    mstore(0x00, bucket)
                    bucketBits := sload(keccak256(0x00, 0x40))
                    if or(bucketBits, iszero(bucket)) { break }
                }
            }
        }
        if (bucketBits != 0) {
            setBitIndex = (bucket << 8) | LibBit.fls(bucketBits);
            /// @solidity memory-safe-assembly
            assembly {
                setBitIndex := or(setBitIndex, sub(0, gt(setBitIndex, before)))
            }
        }
    }
}

File 10 of 21 : SignatureCheckerLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Signature verification helper that supports both ECDSA signatures from EOAs
/// and ERC1271 signatures from smart contract wallets like Argent and Gnosis safe.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SignatureCheckerLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/SignatureChecker.sol)
///
/// @dev Note:
/// - The signature checking functions use the ecrecover precompile (0x1).
/// - The `bytes memory signature` variants use the identity precompile (0x4)
///   to copy memory internally.
/// - Unlike ECDSA signatures, contract signatures are revocable.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
///   regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
///   See: https://eips.ethereum.org/EIPS/eip-2098
///   This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT use signatures as unique identifiers:
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
///   EIP-712 also enables readable signing of typed data for better user safety.
/// This implementation does NOT check if a signature is non-malleable.
library SignatureCheckerLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               SIGNATURE CHECKING OPERATIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `signature` is valid for `signer` and `hash`.
    /// If `signer` is a smart contract, the signature is validated with ERC1271.
    /// Otherwise, the signature is validated with `ECDSA.recover`.
    function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits of `signer` in case they are dirty.
            for { signer := shr(96, shl(96, signer)) } signer {} {
                let m := mload(0x40)
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                if eq(mload(signature), 64) {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    let t :=
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            1, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                        isValid := 1
                        mstore(0x60, 0) // Restore the zero slot.
                        mstore(0x40, m) // Restore the free memory pointer.
                        break
                    }
                }
                if eq(mload(signature), 65) {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                    let t :=
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            1, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                        isValid := 1
                        mstore(0x60, 0) // Restore the zero slot.
                        mstore(0x40, m) // Restore the free memory pointer.
                        break
                    }
                }
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.

                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                // Copy the `signature` over.
                let n := add(0x20, mload(signature))
                pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n))
                // forgefmt: disable-next-item
                isValid := and(
                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                    eq(mload(d), f),
                    // Whether the staticcall does not revert.
                    // This must be placed at the end of the `and` clause,
                    // as the arguments are evaluated from right to left.
                    staticcall(
                        gas(), // Remaining gas.
                        signer, // The `signer` address.
                        m, // Offset of calldata in memory.
                        add(returndatasize(), 0x44), // Length of calldata in memory.
                        d, // Offset of returndata.
                        0x20 // Length of returndata to write.
                    )
                )
                break
            }
        }
    }

    /// @dev Returns whether `signature` is valid for `signer` and `hash`.
    /// If `signer` is a smart contract, the signature is validated with ERC1271.
    /// Otherwise, the signature is validated with `ECDSA.recover`.
    function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits of `signer` in case they are dirty.
            for { signer := shr(96, shl(96, signer)) } signer {} {
                let m := mload(0x40)
                mstore(0x00, hash)
                if eq(signature.length, 64) {
                    let vs := calldataload(add(signature.offset, 0x20))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x40, calldataload(signature.offset)) // `r`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    let t :=
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            1, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                        isValid := 1
                        mstore(0x60, 0) // Restore the zero slot.
                        mstore(0x40, m) // Restore the free memory pointer.
                        break
                    }
                }
                if eq(signature.length, 65) {
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                    calldatacopy(0x40, signature.offset, 0x40) // `r`, `s`.
                    let t :=
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            1, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                        isValid := 1
                        mstore(0x60, 0) // Restore the zero slot.
                        mstore(0x40, m) // Restore the free memory pointer.
                        break
                    }
                }
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.

                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                mstore(add(m, 0x44), signature.length)
                // Copy the `signature` over.
                calldatacopy(add(m, 0x64), signature.offset, signature.length)
                // forgefmt: disable-next-item
                isValid := and(
                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                    eq(mload(d), f),
                    // Whether the staticcall does not revert.
                    // This must be placed at the end of the `and` clause,
                    // as the arguments are evaluated from right to left.
                    staticcall(
                        gas(), // Remaining gas.
                        signer, // The `signer` address.
                        m, // Offset of calldata in memory.
                        add(signature.length, 0x64), // Length of calldata in memory.
                        d, // Offset of returndata.
                        0x20 // Length of returndata to write.
                    )
                )
                break
            }
        }
    }

    /// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`.
    /// If `signer` is a smart contract, the signature is validated with ERC1271.
    /// Otherwise, the signature is validated with `ECDSA.recover`.
    function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits of `signer` in case they are dirty.
            for { signer := shr(96, shl(96, signer)) } signer {} {
                let m := mload(0x40)
                mstore(0x00, hash)
                mstore(0x20, add(shr(255, vs), 27)) // `v`.
                mstore(0x40, r) // `r`.
                mstore(0x60, shr(1, shl(1, vs))) // `s`.
                let t :=
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                    isValid := 1
                    mstore(0x60, 0) // Restore the zero slot.
                    mstore(0x40, m) // Restore the free memory pointer.
                    break
                }

                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                mstore(add(m, 0x44), 65) // Length of the signature.
                mstore(add(m, 0x64), r) // `r`.
                mstore(add(m, 0x84), mload(0x60)) // `s`.
                mstore8(add(m, 0xa4), mload(0x20)) // `v`.
                // forgefmt: disable-next-item
                isValid := and(
                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                    eq(mload(d), f),
                    // Whether the staticcall does not revert.
                    // This must be placed at the end of the `and` clause,
                    // as the arguments are evaluated from right to left.
                    staticcall(
                        gas(), // Remaining gas.
                        signer, // The `signer` address.
                        m, // Offset of calldata in memory.
                        0xa5, // Length of calldata in memory.
                        d, // Offset of returndata.
                        0x20 // Length of returndata to write.
                    )
                )
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

    /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`.
    /// If `signer` is a smart contract, the signature is validated with ERC1271.
    /// Otherwise, the signature is validated with `ECDSA.recover`.
    function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits of `signer` in case they are dirty.
            for { signer := shr(96, shl(96, signer)) } signer {} {
                let m := mload(0x40)
                mstore(0x00, hash)
                mstore(0x20, and(v, 0xff)) // `v`.
                mstore(0x40, r) // `r`.
                mstore(0x60, s) // `s`.
                let t :=
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                    isValid := 1
                    mstore(0x60, 0) // Restore the zero slot.
                    mstore(0x40, m) // Restore the free memory pointer.
                    break
                }

                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                mstore(add(m, 0x44), 65) // Length of the signature.
                mstore(add(m, 0x64), r) // `r`.
                mstore(add(m, 0x84), s) // `s`.
                mstore8(add(m, 0xa4), v) // `v`.
                // forgefmt: disable-next-item
                isValid := and(
                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                    eq(mload(d), f),
                    // Whether the staticcall does not revert.
                    // This must be placed at the end of the `and` clause,
                    // as the arguments are evaluated from right to left.
                    staticcall(
                        gas(), // Remaining gas.
                        signer, // The `signer` address.
                        m, // Offset of calldata in memory.
                        0xa5, // Length of calldata in memory.
                        d, // Offset of returndata.
                        0x20 // Length of returndata to write.
                    )
                )
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     ERC1271 OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes memory signature)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            // Copy the `signature` over.
            let n := add(0x20, mload(signature))
            pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n))
            // forgefmt: disable-next-item
            isValid := and(
                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                eq(mload(d), f),
                // Whether the staticcall does not revert.
                // This must be placed at the end of the `and` clause,
                // as the arguments are evaluated from right to left.
                staticcall(
                    gas(), // Remaining gas.
                    signer, // The `signer` address.
                    m, // Offset of calldata in memory.
                    add(returndatasize(), 0x44), // Length of calldata in memory.
                    d, // Offset of returndata.
                    0x20 // Length of returndata to write.
                )
            )
        }
    }

    /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNowCalldata(
        address signer,
        bytes32 hash,
        bytes calldata signature
    ) internal view returns (bool isValid) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            mstore(add(m, 0x44), signature.length)
            // Copy the `signature` over.
            calldatacopy(add(m, 0x64), signature.offset, signature.length)
            // forgefmt: disable-next-item
            isValid := and(
                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                eq(mload(d), f),
                // Whether the staticcall does not revert.
                // This must be placed at the end of the `and` clause,
                // as the arguments are evaluated from right to left.
                staticcall(
                    gas(), // Remaining gas.
                    signer, // The `signer` address.
                    m, // Offset of calldata in memory.
                    add(signature.length, 0x64), // Length of calldata in memory.
                    d, // Offset of returndata.
                    0x20 // Length of returndata to write.
                )
            )
        }
    }

    /// @dev Returns whether the signature (`r`, `vs`) is valid for `hash`
    /// for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            mstore(add(m, 0x44), 65) // Length of the signature.
            mstore(add(m, 0x64), r) // `r`.
            mstore(add(m, 0x84), shr(1, shl(1, vs))) // `s`.
            mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`.
            // forgefmt: disable-next-item
            isValid := and(
                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                eq(mload(d), f),
                // Whether the staticcall does not revert.
                // This must be placed at the end of the `and` clause,
                // as the arguments are evaluated from right to left.
                staticcall(
                    gas(), // Remaining gas.
                    signer, // The `signer` address.
                    m, // Offset of calldata in memory.
                    0xa5, // Length of calldata in memory.
                    d, // Offset of returndata.
                    0x20 // Length of returndata to write.
                )
            )
        }
    }

    /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `hash`
    /// for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            mstore(add(m, 0x44), 65) // Length of the signature.
            mstore(add(m, 0x64), r) // `r`.
            mstore(add(m, 0x84), s) // `s`.
            mstore8(add(m, 0xa4), v) // `v`.
            // forgefmt: disable-next-item
            isValid := and(
                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                eq(mload(d), f),
                // Whether the staticcall does not revert.
                // This must be placed at the end of the `and` clause,
                // as the arguments are evaluated from right to left.
                staticcall(
                    gas(), // Remaining gas.
                    signer, // The `signer` address.
                    m, // Offset of calldata in memory.
                    0xa5, // Length of calldata in memory.
                    d, // Offset of returndata.
                    0x20 // Length of returndata to write.
                )
            )
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an Ethereum Signed Message, created from a `hash`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, hash) // Store into scratch space for keccak256.
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
            result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
        }
    }

    /// @dev Returns an Ethereum Signed Message, created from `s`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    /// Note: Supports lengths of `s` up to 999999 bytes.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let sLength := mload(s)
            let o := 0x20
            mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
            mstore(0x00, 0x00)
            // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
            for { let temp := sLength } 1 {} {
                o := sub(o, 1)
                mstore8(o, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }
            let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
            // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
            returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
            mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
            result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
            mstore(s, sLength) // Restore the length.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   EMPTY CALLDATA HELPERS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an empty calldata bytes.
    function emptySignature() internal pure returns (bytes calldata signature) {
        /// @solidity memory-safe-assembly
        assembly {
            signature.length := 0
        }
    }
}

File 11 of 21 : LibZip.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for compressing and decompressing bytes.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibZip.sol)
/// @author Calldata compression by clabby (https://github.com/clabby/op-kompressor)
/// @author FastLZ by ariya (https://github.com/ariya/FastLZ)
///
/// @dev Note:
/// The accompanying solady.js library includes implementations of
/// FastLZ and calldata operations for convenience.
library LibZip {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     FAST LZ OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // LZ77 implementation based on FastLZ.
    // Equivalent to level 1 compression and decompression at the following commit:
    // https://github.com/ariya/FastLZ/commit/344eb4025f9ae866ebf7a2ec48850f7113a97a42
    // Decompression is backwards compatible.

    /// @dev Returns the compressed `data`.
    function flzCompress(bytes memory data) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            function ms8(d_, v_) -> _d {
                mstore8(d_, v_)
                _d := add(d_, 1)
            }
            function u24(p_) -> _u {
                let w := mload(p_)
                _u := or(shl(16, byte(2, w)), or(shl(8, byte(1, w)), byte(0, w)))
            }
            function cmp(p_, q_, e_) -> _l {
                for { e_ := sub(e_, q_) } lt(_l, e_) { _l := add(_l, 1) } {
                    e_ := mul(iszero(byte(0, xor(mload(add(p_, _l)), mload(add(q_, _l))))), e_)
                }
            }
            function literals(runs_, src_, dest_) -> _o {
                for { _o := dest_ } iszero(lt(runs_, 0x20)) { runs_ := sub(runs_, 0x20) } {
                    mstore(ms8(_o, 31), mload(src_))
                    _o := add(_o, 0x21)
                    src_ := add(src_, 0x20)
                }
                if iszero(runs_) { leave }
                mstore(ms8(_o, sub(runs_, 1)), mload(src_))
                _o := add(1, add(_o, runs_))
            }
            function match(l_, d_, o_) -> _o {
                for { d_ := sub(d_, 1) } iszero(lt(l_, 263)) { l_ := sub(l_, 262) } {
                    o_ := ms8(ms8(ms8(o_, add(224, shr(8, d_))), 253), and(0xff, d_))
                }
                if iszero(lt(l_, 7)) {
                    _o := ms8(ms8(ms8(o_, add(224, shr(8, d_))), sub(l_, 7)), and(0xff, d_))
                    leave
                }
                _o := ms8(ms8(o_, add(shl(5, l_), shr(8, d_))), and(0xff, d_))
            }
            function setHash(i_, v_) {
                let p := add(mload(0x40), shl(2, i_))
                mstore(p, xor(mload(p), shl(224, xor(shr(224, mload(p)), v_))))
            }
            function getHash(i_) -> _h {
                _h := shr(224, mload(add(mload(0x40), shl(2, i_))))
            }
            function hash(v_) -> _r {
                _r := and(shr(19, mul(2654435769, v_)), 0x1fff)
            }
            function setNextHash(ip_, ipStart_) -> _ip {
                setHash(hash(u24(ip_)), sub(ip_, ipStart_))
                _ip := add(ip_, 1)
            }
            codecopy(mload(0x40), codesize(), 0x8000) // Zeroize the hashmap.
            let op := add(mload(0x40), 0x8000)
            let a := add(data, 0x20)
            let ipStart := a
            let ipLimit := sub(add(ipStart, mload(data)), 13)
            for { let ip := add(2, a) } lt(ip, ipLimit) {} {
                let r := 0
                let d := 0
                for {} 1 {} {
                    let s := u24(ip)
                    let h := hash(s)
                    r := add(ipStart, getHash(h))
                    setHash(h, sub(ip, ipStart))
                    d := sub(ip, r)
                    if iszero(lt(ip, ipLimit)) { break }
                    ip := add(ip, 1)
                    if iszero(gt(d, 0x1fff)) { if eq(s, u24(r)) { break } }
                }
                if iszero(lt(ip, ipLimit)) { break }
                ip := sub(ip, 1)
                if gt(ip, a) { op := literals(sub(ip, a), a, op) }
                let l := cmp(add(r, 3), add(ip, 3), add(ipLimit, 9))
                op := match(l, d, op)
                ip := setNextHash(setNextHash(add(ip, l), ipStart), ipStart)
                a := ip
            }
            op := literals(sub(add(ipStart, mload(data)), a), a, op)
            result := mload(0x40)
            let t := add(result, 0x8000)
            let n := sub(op, t)
            mstore(result, n) // Store the length.
            // Copy the result to compact the memory, overwriting the hashmap.
            let o := add(result, 0x20)
            for { let i } lt(i, n) { i := add(i, 0x20) } { mstore(add(o, i), mload(add(t, i))) }
            mstore(add(o, n), 0) // Zeroize the slot after the string.
            mstore(0x40, add(add(o, n), 0x20)) // Allocate the memory.
        }
    }

    /// @dev Returns the decompressed `data`.
    function flzDecompress(bytes memory data) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            let n := 0
            let end := add(add(data, 0x20), mload(data))
            result := mload(0x40)
            let op := add(result, 0x20)
            for { data := add(data, 0x20) } lt(data, end) {} {
                let w := mload(data)
                let c := byte(0, w)
                let t := shr(5, c)
                if iszero(t) {
                    mstore(add(op, n), mload(add(data, 1)))
                    data := add(data, add(2, c))
                    n := add(n, add(1, c))
                    continue
                }
                let g := eq(t, 7)
                let l := add(2, xor(t, mul(g, xor(t, add(7, byte(1, w))))))
                for {
                    let s := add(add(shl(8, and(0x1f, c)), byte(add(1, g), w)), 1)
                    let r := add(op, sub(n, s))
                    let o := add(op, n)
                    let f := xor(s, mul(gt(s, 0x20), xor(s, 0x20)))
                    let j := 0
                } 1 {} {
                    mstore(add(o, j), mload(add(r, j)))
                    j := add(j, f)
                    if iszero(lt(j, l)) { break }
                }
                data := add(data, add(2, g))
                n := add(n, l)
            }
            mstore(result, n) // Store the length.
            let o := add(add(result, 0x20), n)
            mstore(o, 0) // Zeroize the slot after the string.
            mstore(0x40, add(o, 0x20)) // Allocate the memory.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    CALLDATA OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // Calldata compression and decompression using selective run length encoding:
    // - Sequences of 0x00 (up to 128 consecutive).
    // - Sequences of 0xff (up to 32 consecutive).
    //
    // A run length encoded block consists of two bytes:
    // (0) 0x00
    // (1) A control byte with the following bit layout:
    //     - [7]     `0: 0x00, 1: 0xff`.
    //     - [0..6]  `runLength - 1`.
    //
    // The first 4 bytes are bitwise negated so that the compressed calldata
    // can be dispatched into the `fallback` and `receive` functions.

    /// @dev Returns the compressed `data`.
    function cdCompress(bytes memory data) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            function rle(v_, o_, d_) -> _o, _d {
                mstore(o_, shl(240, or(and(0xff, add(d_, 0xff)), and(0x80, v_))))
                _o := add(o_, 2)
            }
            result := mload(0x40)
            let o := add(result, 0x20)
            let z := 0 // Number of consecutive 0x00.
            let y := 0 // Number of consecutive 0xff.
            for { let end := add(data, mload(data)) } iszero(eq(data, end)) {} {
                data := add(data, 1)
                let c := byte(31, mload(data))
                if iszero(c) {
                    if y { o, y := rle(0xff, o, y) }
                    z := add(z, 1)
                    if eq(z, 0x80) { o, z := rle(0x00, o, 0x80) }
                    continue
                }
                if eq(c, 0xff) {
                    if z { o, z := rle(0x00, o, z) }
                    y := add(y, 1)
                    if eq(y, 0x20) { o, y := rle(0xff, o, 0x20) }
                    continue
                }
                if y { o, y := rle(0xff, o, y) }
                if z { o, z := rle(0x00, o, z) }
                mstore8(o, c)
                o := add(o, 1)
            }
            if y { o, y := rle(0xff, o, y) }
            if z { o, z := rle(0x00, o, z) }
            // Bitwise negate the first 4 bytes.
            mstore(add(result, 4), not(mload(add(result, 4))))
            mstore(result, sub(o, add(result, 0x20))) // Store the length.
            mstore(o, 0) // Zeroize the slot after the string.
            mstore(0x40, add(o, 0x20)) // Allocate the memory.
        }
    }

    /// @dev Returns the decompressed `data`.
    function cdDecompress(bytes memory data) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            if mload(data) {
                result := mload(0x40)
                let o := add(result, 0x20)
                let s := add(data, 4)
                let v := mload(s)
                let end := add(data, mload(data))
                mstore(s, not(v)) // Bitwise negate the first 4 bytes.
                for {} lt(data, end) {} {
                    data := add(data, 1)
                    let c := byte(31, mload(data))
                    if iszero(c) {
                        data := add(data, 1)
                        let d := byte(31, mload(data))
                        // Fill with either 0xff or 0x00.
                        mstore(o, not(0))
                        if iszero(gt(d, 0x7f)) { codecopy(o, codesize(), add(d, 1)) }
                        o := add(o, add(and(d, 0x7f), 1))
                        continue
                    }
                    mstore8(o, c)
                    o := add(o, 1)
                }
                mstore(s, v) // Restore the first 4 bytes.
                mstore(result, sub(o, add(result, 0x20))) // Store the length.
                mstore(o, 0) // Zeroize the slot after the string.
                mstore(0x40, add(o, 0x20)) // Allocate the memory.
            }
        }
    }

    /// @dev To be called in the `receive` and `fallback` functions.
    /// ```
    ///     receive() external payable { LibZip.cdFallback(); }
    ///     fallback() external payable { LibZip.cdFallback(); }
    /// ```
    /// For efficiency, this function will directly return the results, terminating the context.
    /// If called internally, it must be called at the end of the function.
    function cdFallback() internal {
        assembly {
            if iszero(calldatasize()) { return(calldatasize(), calldatasize()) }
            let o := 0
            let f := not(3) // For negating the first 4 bytes.
            for { let i := 0 } lt(i, calldatasize()) {} {
                let c := byte(0, xor(add(i, f), calldataload(i)))
                i := add(i, 1)
                if iszero(c) {
                    let d := byte(0, xor(add(i, f), calldataload(i)))
                    i := add(i, 1)
                    // Fill with either 0xff or 0x00.
                    mstore(o, not(0))
                    if iszero(gt(d, 0x7f)) { codecopy(o, codesize(), add(d, 1)) }
                    o := add(o, add(and(d, 0x7f), 1))
                    continue
                }
                mstore8(o, c)
                o := add(o, 1)
            }
            let success := delegatecall(gas(), address(), 0x00, o, codesize(), 0x00)
            returndatacopy(0x00, 0x00, returndatasize())
            if iszero(success) { revert(0x00, returndatasize()) }
            return(0x00, returndatasize())
        }
    }
}

File 12 of 21 : LibMap.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for storage of packed unsigned integers.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibMap.sol)
library LibMap {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STRUCTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev A uint8 map in storage.
    struct Uint8Map {
        mapping(uint256 => uint256) map;
    }

    /// @dev A uint16 map in storage.
    struct Uint16Map {
        mapping(uint256 => uint256) map;
    }

    /// @dev A uint32 map in storage.
    struct Uint32Map {
        mapping(uint256 => uint256) map;
    }

    /// @dev A uint40 map in storage. Useful for storing timestamps up to 34841 A.D.
    struct Uint40Map {
        mapping(uint256 => uint256) map;
    }

    /// @dev A uint64 map in storage.
    struct Uint64Map {
        mapping(uint256 => uint256) map;
    }

    /// @dev A uint128 map in storage.
    struct Uint128Map {
        mapping(uint256 => uint256) map;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     GETTERS / SETTERS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the uint8 value at `index` in `map`.
    function get(Uint8Map storage map, uint256 index) internal view returns (uint8 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, map.slot)
            mstore(0x00, shr(5, index))
            result := byte(and(31, not(index)), sload(keccak256(0x00, 0x40)))
        }
    }

    /// @dev Updates the uint8 value at `index` in `map`.
    function set(Uint8Map storage map, uint256 index, uint8 value) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, map.slot)
            mstore(0x00, shr(5, index))
            let s := keccak256(0x00, 0x40) // Storage slot.
            mstore(0x00, sload(s))
            mstore8(and(31, not(index)), value)
            sstore(s, mload(0x00))
        }
    }

    /// @dev Returns the uint16 value at `index` in `map`.
    function get(Uint16Map storage map, uint256 index) internal view returns (uint16 result) {
        result = uint16(map.map[index >> 4] >> ((index & 15) << 4));
    }

    /// @dev Updates the uint16 value at `index` in `map`.
    function set(Uint16Map storage map, uint256 index, uint16 value) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, map.slot)
            mstore(0x00, shr(4, index))
            let s := keccak256(0x00, 0x40) // Storage slot.
            let o := shl(4, and(index, 15)) // Storage slot offset (bits).
            let v := sload(s) // Storage slot value.
            let m := 0xffff // Value mask.
            sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value)))))
        }
    }

    /// @dev Returns the uint32 value at `index` in `map`.
    function get(Uint32Map storage map, uint256 index) internal view returns (uint32 result) {
        result = uint32(map.map[index >> 3] >> ((index & 7) << 5));
    }

    /// @dev Updates the uint32 value at `index` in `map`.
    function set(Uint32Map storage map, uint256 index, uint32 value) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, map.slot)
            mstore(0x00, shr(3, index))
            let s := keccak256(0x00, 0x40) // Storage slot.
            let o := shl(5, and(index, 7)) // Storage slot offset (bits).
            let v := sload(s) // Storage slot value.
            let m := 0xffffffff // Value mask.
            sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value)))))
        }
    }

    /// @dev Returns the uint40 value at `index` in `map`.
    function get(Uint40Map storage map, uint256 index) internal view returns (uint40 result) {
        unchecked {
            result = uint40(map.map[index / 6] >> ((index % 6) * 40));
        }
    }

    /// @dev Updates the uint40 value at `index` in `map`.
    function set(Uint40Map storage map, uint256 index, uint40 value) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, map.slot)
            mstore(0x00, div(index, 6))
            let s := keccak256(0x00, 0x40) // Storage slot.
            let o := mul(40, mod(index, 6)) // Storage slot offset (bits).
            let v := sload(s) // Storage slot value.
            let m := 0xffffffffff // Value mask.
            sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value)))))
        }
    }

    /// @dev Returns the uint64 value at `index` in `map`.
    function get(Uint64Map storage map, uint256 index) internal view returns (uint64 result) {
        result = uint64(map.map[index >> 2] >> ((index & 3) << 6));
    }

    /// @dev Updates the uint64 value at `index` in `map`.
    function set(Uint64Map storage map, uint256 index, uint64 value) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, map.slot)
            mstore(0x00, shr(2, index))
            let s := keccak256(0x00, 0x40) // Storage slot.
            let o := shl(6, and(index, 3)) // Storage slot offset (bits).
            let v := sload(s) // Storage slot value.
            let m := 0xffffffffffffffff // Value mask.
            sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value)))))
        }
    }

    /// @dev Returns the uint128 value at `index` in `map`.
    function get(Uint128Map storage map, uint256 index) internal view returns (uint128 result) {
        result = uint128(map.map[index >> 1] >> ((index & 1) << 7));
    }

    /// @dev Updates the uint128 value at `index` in `map`.
    function set(Uint128Map storage map, uint256 index, uint128 value) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, map.slot)
            mstore(0x00, shr(1, index))
            let s := keccak256(0x00, 0x40) // Storage slot.
            let o := shl(7, and(index, 1)) // Storage slot offset (bits).
            let v := sload(s) // Storage slot value.
            let m := 0xffffffffffffffffffffffffffffffff // Value mask.
            sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value)))))
        }
    }

    /// @dev Returns the value at `index` in `map`.
    function get(mapping(uint256 => uint256) storage map, uint256 index, uint256 bitWidth)
        internal
        view
        returns (uint256 result)
    {
        unchecked {
            uint256 d = _rawDiv(256, bitWidth); // Bucket size.
            uint256 m = (1 << bitWidth) - 1; // Value mask.
            result = (map[_rawDiv(index, d)] >> (_rawMod(index, d) * bitWidth)) & m;
        }
    }

    /// @dev Updates the value at `index` in `map`.
    function set(
        mapping(uint256 => uint256) storage map,
        uint256 index,
        uint256 value,
        uint256 bitWidth
    ) internal {
        unchecked {
            uint256 d = _rawDiv(256, bitWidth); // Bucket size.
            uint256 m = (1 << bitWidth) - 1; // Value mask.
            uint256 o = _rawMod(index, d) * bitWidth; // Storage slot offset (bits).
            map[_rawDiv(index, d)] ^= (((map[_rawDiv(index, d)] >> o) ^ value) & m) << o;
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       BINARY SEARCH                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // The following functions search in the range of [`start`, `end`)
    // (i.e. `start <= index < end`).
    // The range must be sorted in ascending order.
    // `index` precedence: equal to > nearest before > nearest after.
    // An invalid search range will simply return `(found = false, index = start)`.

    /// @dev Returns whether `map` contains `needle`, and the index of `needle`.
    function searchSorted(Uint8Map storage map, uint8 needle, uint256 start, uint256 end)
        internal
        view
        returns (bool found, uint256 index)
    {
        return searchSorted(map.map, needle, start, end, 8);
    }

    /// @dev Returns whether `map` contains `needle`, and the index of `needle`.
    function searchSorted(Uint16Map storage map, uint16 needle, uint256 start, uint256 end)
        internal
        view
        returns (bool found, uint256 index)
    {
        return searchSorted(map.map, needle, start, end, 16);
    }

    /// @dev Returns whether `map` contains `needle`, and the index of `needle`.
    function searchSorted(Uint32Map storage map, uint32 needle, uint256 start, uint256 end)
        internal
        view
        returns (bool found, uint256 index)
    {
        return searchSorted(map.map, needle, start, end, 32);
    }

    /// @dev Returns whether `map` contains `needle`, and the index of `needle`.
    function searchSorted(Uint40Map storage map, uint40 needle, uint256 start, uint256 end)
        internal
        view
        returns (bool found, uint256 index)
    {
        return searchSorted(map.map, needle, start, end, 40);
    }

    /// @dev Returns whether `map` contains `needle`, and the index of `needle`.
    function searchSorted(Uint64Map storage map, uint64 needle, uint256 start, uint256 end)
        internal
        view
        returns (bool found, uint256 index)
    {
        return searchSorted(map.map, needle, start, end, 64);
    }

    /// @dev Returns whether `map` contains `needle`, and the index of `needle`.
    function searchSorted(Uint128Map storage map, uint128 needle, uint256 start, uint256 end)
        internal
        view
        returns (bool found, uint256 index)
    {
        return searchSorted(map.map, needle, start, end, 128);
    }

    /// @dev Returns whether `map` contains `needle`, and the index of `needle`.
    function searchSorted(
        mapping(uint256 => uint256) storage map,
        uint256 needle,
        uint256 start,
        uint256 end,
        uint256 bitWidth
    ) internal view returns (bool found, uint256 index) {
        unchecked {
            if (start >= end) end = start;
            uint256 t;
            uint256 o = start - 1; // Offset to derive the actual index.
            uint256 l = 1; // Low.
            uint256 d = _rawDiv(256, bitWidth); // Bucket size.
            uint256 m = (1 << bitWidth) - 1; // Value mask.
            uint256 h = end - start; // High.
            while (true) {
                index = (l & h) + ((l ^ h) >> 1);
                if (l > h) break;
                t = (map[_rawDiv(index + o, d)] >> (_rawMod(index + o, d) * bitWidth)) & m;
                if (t == needle) break;
                if (needle <= t) h = index - 1;
                else l = index + 1;
            }
            /// @solidity memory-safe-assembly
            assembly {
                m := or(iszero(index), iszero(bitWidth))
                found := iszero(or(xor(t, needle), m))
                index := add(o, xor(index, mul(xor(index, 1), m)))
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `x / y`, returning 0 if `y` is zero.
    function _rawDiv(uint256 x, uint256 y) private pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := div(x, y)
        }
    }

    /// @dev Returns `x % y`, returning 0 if `y` is zero.
    function _rawMod(uint256 x, uint256 y) private pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mod(x, y)
        }
    }
}

File 13 of 21 : DelegateCashLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

library DelegateCashLib {
    address internal constant REGISTRY_V2 = 0x00000000000000447e69651d841bD8D104Bed493;

    function checkDelegateForAll(address delegate, address vault) internal view returns (bool result) {
        assembly {
            // Cache the free memory pointer.
            let m := mload(0x40)
            // Store the function selector of `checkDelegateForAll(address,address,bytes32)`.
            mstore(0x00, 0xe839bd53)
            // Store the `delegate`.
            mstore(0x20, delegate)
            // Store the `vault`.
            mstore(0x40, vault)
            // The `bytes32 right` argument points to 0x60, which is zero.

            // Arguments are evaulated last to first.
            result := and(
                // The returndata is 1, which represents a bool true.
                eq(mload(0x00), 1),
                // The staticcall is successful.
                staticcall(gas(), REGISTRY_V2, 0x1c, 0x64, 0x00, 0x20)
            )

            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }
}

File 14 of 21 : LibOps.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

/**
 * @title LibOps
 * @dev Shared utilities.
 */
library LibOps {
    // =============================================================
    //                            ERRORS
    // =============================================================

    /**
     * @dev Error for overflows.
     */
    error Overflow();

    /**
     * @dev Error for unauthorized access.
     */
    error Unauthorized();

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

    /**
     * @dev A role every minter module must have in order to mint new tokens.
     *      IMPORTANT: This constant must NEVER be changed!
     *      It will always be 2 across all past and future sound protocol contracts.
     */
    uint256 internal constant MINTER_ROLE = 1 << 1;

    /**
     * @dev A role the owner can grant for performing admin actions.
     *      IMPORTANT: This constant must NEVER be changed!
     *      It will always be 1 across all past and future sound protocol contracts.
     */
    uint256 internal constant ADMIN_ROLE = 1 << 0;

    /**
     * @dev Basis points denominator used in fee calculations.
     *      IMPORTANT: This constant must NEVER be changed!
     *      It will always be 10000 across all past and future sound protocol contracts.
     */
    uint16 internal constant BPS_DENOMINATOR = 10000;

    // =============================================================
    //                           FUNCTIONS
    // =============================================================

    /**
     * @dev `isOn ? flag : 0`.
     */
    function toFlag(bool isOn, uint8 flag) internal pure returns (uint8 result) {
        assembly {
            result := mul(iszero(iszero(isOn)), flag)
        }
    }

    /**
     * @dev `(flags & flag != 0) != isOn ? flags ^ flag : flags`.
     *      Sets `flag` in `flags` to 1 if `isOn` is true.
     *      Sets `flag` in `flags` to 0 if `isOn` is false.
     */
    function setFlagTo(
        uint8 flags,
        uint8 flag,
        bool isOn
    ) internal pure returns (uint8 result) {
        assembly {
            result := xor(flags, mul(xor(iszero(and(0xff, and(flags, flag))), iszero(isOn)), flag))
        }
    }

    /**
     * @dev `x > y ? x : y`.
     */
    function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
        assembly {
            z := xor(x, mul(xor(x, y), gt(y, x)))
        }
    }

    /**
     * @dev `x < y ? x : y`.
     */
    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
        assembly {
            z := xor(x, mul(xor(x, y), lt(y, x)))
        }
    }

    /**
     * @dev `(a * b) / d`. Returns 0 if `d` is zero.
     */
    function rawMulDiv(
        uint256 a,
        uint256 b,
        uint256 d
    ) internal pure returns (uint256 z) {
        assembly {
            z := div(mul(a, b), d)
        }
    }

    /**
     * @dev `a / d`. Returns 0 if `d` is zero.
     */
    function rawMod(uint256 a, uint256 d) internal pure returns (uint256 z) {
        assembly {
            z := mod(a, d)
        }
    }

    /**
     * @dev `a | b`.
     */
    function or(bool a, bool b) internal pure returns (bool z) {
        assembly {
            z := or(iszero(iszero(a)), iszero(iszero(b)))
        }
    }

    /**
     * @dev `a | b | c`.
     */
    function or(
        bool a,
        bool b,
        bool c
    ) internal pure returns (bool z) {
        z = or(a, or(b, c));
    }

    /**
     * @dev `a | b | c | d`.
     */
    function or(
        bool a,
        bool b,
        bool c,
        bool d
    ) internal pure returns (bool z) {
        z = or(a, or(b, or(c, d)));
    }

    /**
     * @dev `a & b`.
     */
    function and(bool a, bool b) internal pure returns (bool z) {
        assembly {
            z := and(iszero(iszero(a)), iszero(iszero(b)))
        }
    }

    /**
     * @dev `x == 0 ? type(uint256).max : x`
     */
    function maxIfZero(uint256 x) internal pure returns (uint256 z) {
        assembly {
            z := sub(x, iszero(x))
        }
    }

    /**
     * @dev Packs an address and an index to create an unique identifier.
     * @param a The address.
     * @param i The index.
     * @return result The packed result.
     */
    function packId(address a, uint96 i) internal pure returns (uint256 result) {
        assembly {
            result := or(shl(96, a), shr(160, shl(160, i)))
        }
    }

    /**
     * @dev Packs `edition`, `tier`, `scheduleNum` to create an unique identifier.
     * @param edition     The address of the Sound Edition.
     * @param tier        The tier.
     * @param scheduleNum The edition-tier schedule number.
     * @return result The packed result.
     */
    function packId(
        address edition,
        uint8 tier,
        uint8 scheduleNum
    ) internal pure returns (uint256 result) {
        assembly {
            mstore(0x00, shl(96, edition))
            mstore8(0x1e, tier)
            mstore8(0x1f, scheduleNum)
            result := mload(0x00)
        }
    }

    /**
     * @dev `revert Overflow()`.
     */
    function revertOverflow() internal pure {
        assembly {
            mstore(0x00, 0x35278d12) // `Overflow()`.
            revert(0x1c, 0x04)
        }
    }

    /**
     * @dev `revert Unauthorized()`.
     */
    function revertUnauthorized() internal pure {
        assembly {
            mstore(0x00, 0x82b42900) // `Unauthorized()`.
            revert(0x1c, 0x04)
        }
    }
}

File 15 of 21 : LibMulticaller.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * @title LibMulticaller
 * @author vectorized.eth
 * @notice Library to read the `msg.sender` of the multicaller with sender contract.
 *
 * @dev Note:
 * The functions in this library do NOT guard against reentrancy.
 * A single transaction can recurse through different Multicallers
 * (e.g. `MulticallerWithSender -> contract -> MulticallerWithSigner -> contract`).
 *
 * Think of these functions like `msg.sender`.
 *
 * If your contract `C` can handle reentrancy safely with plain old `msg.sender`
 * for any `A -> C -> B -> C`, you should be fine substituting `msg.sender` with these functions.
 */
library LibMulticaller {
    /**
     * @dev The address of the multicaller contract.
     */
    address internal constant MULTICALLER = 0x0000000000002Bdbf1Bf3279983603Ec279CC6dF;

    /**
     * @dev The address of the multicaller with sender contract.
     */
    address internal constant MULTICALLER_WITH_SENDER = 0x00000000002Fd5Aeb385D324B580FCa7c83823A0;

    /**
     * @dev The address of the multicaller with signer contract.
     */
    address internal constant MULTICALLER_WITH_SIGNER = 0x000000000000D9ECebf3C23529de49815Dac1c4c;

    /**
     * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`.
     */
    function multicallerSender() internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x00)
            if iszero(staticcall(gas(), MULTICALLER_WITH_SENDER, codesize(), 0x00, 0x00, 0x20)) {
                revert(codesize(), codesize()) // For better gas estimation.
            }
            result := mload(0x00)
        }
    }

    /**
     * @dev Returns the signer of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`.
     */
    function multicallerSigner() internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x00)
            if iszero(staticcall(gas(), MULTICALLER_WITH_SIGNER, codesize(), 0x00, 0x00, 0x20)) {
                revert(codesize(), codesize()) // For better gas estimation.
            }
            result := mload(0x00)
        }
    }

    /**
     * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`,
     *      if the current context's `msg.sender` is `MULTICALLER_WITH_SENDER`.
     *      Otherwise, returns `msg.sender`.
     */
    function sender() internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, caller())
            let withSender := MULTICALLER_WITH_SENDER
            if eq(caller(), withSender) {
                if iszero(staticcall(gas(), withSender, codesize(), 0x00, 0x00, 0x20)) {
                    revert(codesize(), codesize()) // For better gas estimation.
                }
            }
            result := mload(0x00)
        }
    }

    /**
     * @dev Returns the caller of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`,
     *      if the current context's `msg.sender` is `MULTICALLER_WITH_SIGNER`.
     *      Otherwise, returns `msg.sender`.
     */
    function signer() internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, caller())
            let withSigner := MULTICALLER_WITH_SIGNER
            if eq(caller(), withSigner) {
                if iszero(staticcall(gas(), withSigner, codesize(), 0x00, 0x00, 0x20)) {
                    revert(codesize(), codesize()) // For better gas estimation.
                }
            }
            result := mload(0x00)
        }
    }

    /**
     * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`,
     *      if the current context's `msg.sender` is `MULTICALLER_WITH_SENDER`.
     *      Returns the signer of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`,
     *      if the current context's `msg.sender` is `MULTICALLER_WITH_SIGNER`.
     *      Otherwise, returns `msg.sender`.
     */
    function senderOrSigner() internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, caller())
            let withSender := MULTICALLER_WITH_SENDER
            if eq(caller(), withSender) {
                if iszero(staticcall(gas(), withSender, codesize(), 0x00, 0x00, 0x20)) {
                    revert(codesize(), codesize()) // For better gas estimation.
                }
            }
            let withSigner := MULTICALLER_WITH_SIGNER
            if eq(caller(), withSigner) {
                if iszero(staticcall(gas(), withSigner, codesize(), 0x00, 0x00, 0x20)) {
                    revert(codesize(), codesize()) // For better gas estimation.
                }
            }
            result := mload(0x00)
        }
    }
}

File 16 of 21 : Ownable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The caller is not authorized to call the function.
    error Unauthorized();

    /// @dev The `newOwner` cannot be the zero address.
    error NewOwnerIsZeroAddress();

    /// @dev The `pendingOwner` does not have a valid handover request.
    error NoHandoverRequest();

    /// @dev Cannot double-initialize.
    error AlreadyInitialized();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ownership is transferred from `oldOwner` to `newOwner`.
    /// This event is intentionally kept the same as OpenZeppelin's Ownable to be
    /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
    /// despite it not being as lightweight as a single argument event.
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

    /// @dev An ownership handover to `pendingOwner` has been requested.
    event OwnershipHandoverRequested(address indexed pendingOwner);

    /// @dev The ownership handover to `pendingOwner` has been canceled.
    event OwnershipHandoverCanceled(address indexed pendingOwner);

    /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
    uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
        0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;

    /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
        0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;

    /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
        0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The owner slot is given by:
    /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
    /// It is intentionally chosen to be a high value
    /// to avoid collision with lower slots.
    /// The choice of manual storage layout is to enable compatibility
    /// with both regular and upgradeable contracts.
    bytes32 internal constant _OWNER_SLOT =
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;

    /// The ownership handover slot of `newOwner` is given by:
    /// ```
    ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
    ///     let handoverSlot := keccak256(0x00, 0x20)
    /// ```
    /// It stores the expiry timestamp of the two-step ownership handover.
    uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
    function _guardInitializeOwner() internal pure virtual returns (bool guard) {}

    /// @dev Initializes the owner directly without authorization guard.
    /// This function must be called upon initialization,
    /// regardless of whether the contract is upgradeable or not.
    /// This is to enable generalization to both regular and upgradeable contracts,
    /// and to save gas in case the initial owner is not the caller.
    /// For performance reasons, this function will not check if there
    /// is an existing owner.
    function _initializeOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                if sload(ownerSlot) {
                    mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
                    revert(0x1c, 0x04)
                }
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(_OWNER_SLOT, newOwner)
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        }
    }

    /// @dev Sets the owner directly without authorization guard.
    function _setOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, newOwner)
            }
        }
    }

    /// @dev Throws if the sender is not the owner.
    function _checkOwner() internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // If the caller is not the stored owner, revert.
            if iszero(eq(caller(), sload(_OWNER_SLOT))) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns how long a two-step ownership handover is valid for in seconds.
    /// Override to return a different value if needed.
    /// Made internal to conserve bytecode. Wrap it in a public function if needed.
    function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
        return 48 * 3600;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  PUBLIC UPDATE FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Allows the owner to transfer the ownership to `newOwner`.
    function transferOwnership(address newOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(shl(96, newOwner)) {
                mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
                revert(0x1c, 0x04)
            }
        }
        _setOwner(newOwner);
    }

    /// @dev Allows the owner to renounce their ownership.
    function renounceOwnership() public payable virtual onlyOwner {
        _setOwner(address(0));
    }

    /// @dev Request a two-step ownership handover to the caller.
    /// The request will automatically expire in 48 hours (172800 seconds) by default.
    function requestOwnershipHandover() public payable virtual {
        unchecked {
            uint256 expires = block.timestamp + _ownershipHandoverValidFor();
            /// @solidity memory-safe-assembly
            assembly {
                // Compute and set the handover slot to `expires`.
                mstore(0x0c, _HANDOVER_SLOT_SEED)
                mstore(0x00, caller())
                sstore(keccak256(0x0c, 0x20), expires)
                // Emit the {OwnershipHandoverRequested} event.
                log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
            }
        }
    }

    /// @dev Cancels the two-step ownership handover to the caller, if any.
    function cancelOwnershipHandover() public payable virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x20), 0)
            // Emit the {OwnershipHandoverCanceled} event.
            log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
        }
    }

    /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
    /// Reverts if there is no existing ownership handover requested by `pendingOwner`.
    function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            let handoverSlot := keccak256(0x0c, 0x20)
            // If the handover does not exist, or has expired.
            if gt(timestamp(), sload(handoverSlot)) {
                mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
                revert(0x1c, 0x04)
            }
            // Set the handover slot to 0.
            sstore(handoverSlot, 0)
        }
        _setOwner(pendingOwner);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   PUBLIC READ FUNCTIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the owner of the contract.
    function owner() public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(_OWNER_SLOT)
        }
    }

    /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
    function ownershipHandoverExpiresAt(address pendingOwner)
        public
        view
        virtual
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the handover slot.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            // Load the handover slot.
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         MODIFIERS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Marks a function as only callable by the owner.
    modifier onlyOwner() virtual {
        _checkOwner();
        _;
    }
}

File 17 of 21 : IERC721AUpgradeable.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

/**
 * @dev Interface of ERC721A.
 */
interface IERC721AUpgradeable {
    /**
     * 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 18 of 21 : IERC2981Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981Upgradeable is IERC165Upgradeable {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}

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

pragma solidity ^0.8.0;

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

File 20 of 21 : IMetadataModule.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

/**
 * @title IMetadataModule
 * @notice The interface for custom metadata modules.
 */
interface IMetadataModule {
    /**
     * @dev When implemented, SoundEdition's `tokenURI` redirects execution to this `tokenURI`.
     * @param tokenId The token ID to retrieve the token URI for.
     * @return The token URI string.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 21 of 21 : LibBit.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for bit twiddling and boolean operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBit.sol)
/// @author Inspired by (https://graphics.stanford.edu/~seander/bithacks.html)
library LibBit {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  BIT TWIDDLING OPERATIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Find last set.
    /// Returns the index of the most significant bit of `x`,
    /// counting from the least significant bit position.
    /// If `x` is zero, returns 256.
    function fls(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, x)))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            // forgefmt: disable-next-item
            r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
                0x0706060506020504060203020504030106050205030304010505030400000000))
        }
    }

    /// @dev Count leading zeros.
    /// Returns the number of zeros preceding the most significant one bit.
    /// If `x` is zero, returns 256.
    function clz(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            // forgefmt: disable-next-item
            r := add(xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
                0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff)), iszero(x))
        }
    }

    /// @dev Find first set.
    /// Returns the index of the least significant bit of `x`,
    /// counting from the least significant bit position.
    /// If `x` is zero, returns 256.
    /// Equivalent to `ctz` (count trailing zeros), which gives
    /// the number of zeros following the least significant one bit.
    function ffs(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Isolate the least significant bit.
            let b := and(x, add(not(x), 1))

            r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, b)))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, b))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, b))))

            // For the remaining 32 bits, use a De Bruijn lookup.
            // forgefmt: disable-next-item
            r := or(r, byte(and(div(0xd76453e0, shr(r, b)), 0x1f),
                0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))
        }
    }

    /// @dev Returns the number of set bits in `x`.
    function popCount(uint256 x) internal pure returns (uint256 c) {
        /// @solidity memory-safe-assembly
        assembly {
            let max := not(0)
            let isMax := eq(x, max)
            x := sub(x, and(shr(1, x), div(max, 3)))
            x := add(and(x, div(max, 5)), and(shr(2, x), div(max, 5)))
            x := and(add(x, shr(4, x)), div(max, 17))
            c := or(shl(8, isMax), shr(248, mul(x, div(max, 255))))
        }
    }

    /// @dev Returns whether `x` is a power of 2.
    function isPo2(uint256 x) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `x && !(x & (x - 1))`.
            result := iszero(add(and(x, sub(x, 1)), iszero(x)))
        }
    }

    /// @dev Returns `x` reversed at the bit level.
    function reverseBits(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Computing masks on-the-fly reduces bytecode size by about 500 bytes.
            let m := not(0)
            r := x
            for { let s := 128 } 1 {} {
                m := xor(m, shl(s, m))
                r := or(and(shr(s, r), m), and(shl(s, r), not(m)))
                s := shr(1, s)
                if iszero(s) { break }
            }
        }
    }

    /// @dev Returns `x` reversed at the byte level.
    function reverseBytes(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Computing masks on-the-fly reduces bytecode size by about 200 bytes.
            let m := not(0)
            r := x
            for { let s := 128 } 1 {} {
                m := xor(m, shl(s, m))
                r := or(and(shr(s, r), m), and(shl(s, r), not(m)))
                s := shr(1, s)
                if eq(s, 4) { break }
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     BOOLEAN OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // A Solidity bool on the stack or memory is represented as a 256-bit word.
    // Non-zero values are true, zero is false.
    // A clean bool is either 0 (false) or 1 (true) under the hood.
    // Usually, if not always, the bool result of a regular Solidity expression,
    // or the argument of a public/external function will be a clean bool.
    // You can usually use the raw variants for more performance.
    // If uncertain, test (best with exact compiler settings).
    // Or use the non-raw variants (compiler can sometimes optimize out the double `iszero`s).

    /// @dev Returns `x & y`. Inputs must be clean.
    function rawAnd(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := and(x, y)
        }
    }

    /// @dev Returns `x & y`.
    function and(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := and(iszero(iszero(x)), iszero(iszero(y)))
        }
    }

    /// @dev Returns `x | y`. Inputs must be clean.
    function rawOr(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := or(x, y)
        }
    }

    /// @dev Returns `x | y`.
    function or(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := or(iszero(iszero(x)), iszero(iszero(y)))
        }
    }

    /// @dev Returns 1 if `b` is true, else 0. Input must be clean.
    function rawToUint(bool b) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := b
        }
    }

    /// @dev Returns 1 if `b` is true, else 0.
    function toUint(bool b) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(iszero(b))
        }
    }
}

Settings
{
  "remappings": [
    "openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "chiru-labs/ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/",
    "solady/=lib/solady/src/",
    "closedsea/=lib/closedsea/src/",
    "preapprove/=lib/preapprove/src/",
    "multicaller/=lib/multicaller/src/",
    "@core/=contracts/core/",
    "@modules/=contracts/modules/",
    "forge-std/=lib/forge-std/src/",
    "ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/",
    "ds-test/=lib/solady/lib/ds-test/src/",
    "erc4626-tests/=lib/closedsea/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "erc721a-upgradeable/=lib/multicaller/lib/erc721a-upgradeable/contracts/",
    "erc721a/=lib/multicaller/lib/erc721a/contracts/",
    "murky/=lib/murky/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "operator-filter-registry/=lib/closedsea/lib/operator-filter-registry/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"name":"CallerNotDelegated","type":"error"},{"inputs":[],"name":"ExceedsMaxPerAccount","type":"error"},{"inputs":[],"name":"ExceedsMintSupply","type":"error"},{"inputs":[],"name":"ExceedsSignedQuantity","type":"error"},{"inputs":[],"name":"InvalidAffiliate","type":"error"},{"inputs":[],"name":"InvalidAffiliateFeeBPS","type":"error"},{"inputs":[],"name":"InvalidMaxMintableRange","type":"error"},{"inputs":[],"name":"InvalidMerkleProof","type":"error"},{"inputs":[],"name":"InvalidMode","type":"error"},{"inputs":[],"name":"InvalidPlatformFeeBPS","type":"error"},{"inputs":[],"name":"InvalidPlatformFeeConfig","type":"error"},{"inputs":[],"name":"InvalidPlatformFlatFee","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidTimeRange","type":"error"},{"inputs":[],"name":"MaxMintableIsZero","type":"error"},{"inputs":[],"name":"MaxMintablePerAccountIsZero","type":"error"},{"inputs":[],"name":"MerkleRootIsEmpty","type":"error"},{"inputs":[],"name":"MintDoesNotExist","type":"error"},{"inputs":[{"internalType":"uint256","name":"blockTimestamp","type":"uint256"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"}],"name":"MintNotOpen","type":"error"},{"inputs":[],"name":"MintPaused","type":"error"},{"inputs":[],"name":"MintsAlreadyExist","type":"error"},{"inputs":[],"name":"NotConfigurable","type":"error"},{"inputs":[],"name":"PlatformFeeAddressIsZero","type":"error"},{"inputs":[],"name":"SignatureAlreadyUsed","type":"error"},{"inputs":[],"name":"SignatureExpired","type":"error"},{"inputs":[],"name":"SignedPriceTooLow","type":"error"},{"inputs":[{"internalType":"uint256","name":"paid","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"WrongPayment","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"uint16","name":"bps","type":"uint16"}],"name":"AffiliateFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"affiliate","type":"address"},{"indexed":false,"internalType":"uint256","name":"accrued","type":"uint256"}],"name":"AffiliateFeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"AffiliateMerkleRootSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platform","type":"address"},{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"indexed":false,"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"config","type":"tuple"}],"name":"DefaultPlatformFeeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platform","type":"address"},{"indexed":false,"internalType":"uint96","name":"price","type":"uint96"}],"name":"GAPriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"value","type":"uint32"}],"name":"MaxMintablePerAccountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"value","type":"uint32"}],"name":"MaxMintableSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"name":"MerkleRootSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint96","name":"price","type":"uint96"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"},{"internalType":"uint32","name":"maxMintable","type":"uint32"},{"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"internalType":"bytes32","name":"affiliateMerkleRoot","type":"bytes32"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint8","name":"mode","type":"uint8"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"indexed":false,"internalType":"struct ISuperMinterV2.MintCreation","name":"creation","type":"tuple"}],"name":"MintCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"components":[{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"internalType":"address","name":"allowlisted","type":"address"},{"internalType":"uint32","name":"allowlistedQuantity","type":"uint32"},{"internalType":"uint32","name":"signedQuantity","type":"uint32"},{"internalType":"uint32","name":"signedClaimTicket","type":"uint32"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bool","name":"affiliated","type":"bool"},{"internalType":"uint256","name":"requiredEtherValue","type":"uint256"},{"internalType":"uint256","name":"unitPrice","type":"uint256"},{"internalType":"uint256","name":"finalArtistFee","type":"uint256"},{"internalType":"uint256","name":"finalAffiliateFee","type":"uint256"},{"internalType":"uint256","name":"finalPlatformFee","type":"uint256"}],"indexed":false,"internalType":"struct ISuperMinterV2.MintedLogData","name":"data","type":"tuple"},{"indexed":true,"internalType":"uint256","name":"attributionId","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"PausedSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"address[]","name":"to","type":"address[]"},{"indexed":false,"internalType":"uint32","name":"signedQuantity","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"fromTokenId","type":"uint256"}],"name":"PlatformAirdropped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platform","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"PlatformFeeAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platform","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"indexed":false,"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"config","type":"tuple"}],"name":"PlatformFeeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platform","type":"address"},{"indexed":false,"internalType":"uint256","name":"accrued","type":"uint256"}],"name":"PlatformFeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platform","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"PlatformSignerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"uint96","name":"price","type":"uint96"}],"name":"PriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"startTime","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"endTime","type":"uint32"}],"name":"TimeRangeSet","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"BPS_DENOMINATOR","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GA_TIER","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_AFFILIATE_FEE_BPS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PER_MINT_REWARD","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PLATFORM_PER_MINT_FEE_BPS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PLATFORM_PER_TX_FLAT_FEE","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_TO_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PLATFORM_AIRDROP","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PLATFORM_AIRDROP_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERIFY_MERKLE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERIFY_SIGNATURE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"affiliateFeesAccrued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32[]","name":"claimTickets","type":"uint32[]"}],"name":"checkClaimTickets","outputs":[{"internalType":"bool[]","name":"claimed","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"address","name":"allowlisted","type":"address"},{"internalType":"uint32","name":"allowlistedQuantity","type":"uint32"},{"internalType":"bytes32[]","name":"allowlistProof","type":"bytes32[]"},{"internalType":"uint96","name":"signedPrice","type":"uint96"},{"internalType":"uint32","name":"signedQuantity","type":"uint32"},{"internalType":"uint32","name":"signedClaimTicket","type":"uint32"},{"internalType":"uint32","name":"signedDeadline","type":"uint32"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bytes32[]","name":"affiliateProof","type":"bytes32[]"},{"internalType":"uint256","name":"attributionId","type":"uint256"}],"internalType":"struct ISuperMinterV2.MintTo","name":"p","type":"tuple"}],"name":"computeMintToDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address[]","name":"to","type":"address[]"},{"internalType":"uint32","name":"signedQuantity","type":"uint32"},{"internalType":"uint32","name":"signedClaimTicket","type":"uint32"},{"internalType":"uint32","name":"signedDeadline","type":"uint32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct ISuperMinterV2.PlatformAirdrop","name":"p","type":"tuple"}],"name":"computePlatformAirdropDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint96","name":"price","type":"uint96"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"},{"internalType":"uint32","name":"maxMintable","type":"uint32"},{"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"internalType":"bytes32","name":"affiliateMerkleRoot","type":"bytes32"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint8","name":"mode","type":"uint8"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"internalType":"struct ISuperMinterV2.MintCreation","name":"c","type":"tuple"}],"name":"createEditionMint","outputs":[{"internalType":"uint8","name":"scheduleNum","type":"uint8"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"platform","type":"address"}],"name":"defaultPlatformFeeConfig","outputs":[{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"effectivePlatformFeeConfig","outputs":[{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gaPrice","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"affiliate","type":"address"}],"name":"isAffiliated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bytes32[]","name":"affiliateProof","type":"bytes32[]"}],"name":"isAffiliatedWithProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"}],"name":"mintInfo","outputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint96","name":"price","type":"uint96"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"},{"internalType":"uint32","name":"maxMintable","type":"uint32"},{"internalType":"uint32","name":"minted","type":"uint32"},{"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"internalType":"uint8","name":"mode","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"hasMints","type":"bool"},{"internalType":"bytes32","name":"affiliateMerkleRoot","type":"bytes32"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct ISuperMinterV2.MintInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"}],"name":"mintInfoList","outputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint96","name":"price","type":"uint96"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"},{"internalType":"uint32","name":"maxMintable","type":"uint32"},{"internalType":"uint32","name":"minted","type":"uint32"},{"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"internalType":"uint8","name":"mode","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"hasMints","type":"bool"},{"internalType":"bytes32","name":"affiliateMerkleRoot","type":"bytes32"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct ISuperMinterV2.MintInfo[]","name":"a","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"address","name":"allowlisted","type":"address"},{"internalType":"uint32","name":"allowlistedQuantity","type":"uint32"},{"internalType":"bytes32[]","name":"allowlistProof","type":"bytes32[]"},{"internalType":"uint96","name":"signedPrice","type":"uint96"},{"internalType":"uint32","name":"signedQuantity","type":"uint32"},{"internalType":"uint32","name":"signedClaimTicket","type":"uint32"},{"internalType":"uint32","name":"signedDeadline","type":"uint32"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bytes32[]","name":"affiliateProof","type":"bytes32[]"},{"internalType":"uint256","name":"attributionId","type":"uint256"}],"internalType":"struct ISuperMinterV2.MintTo","name":"p","type":"tuple"}],"name":"mintTo","outputs":[{"internalType":"uint256","name":"fromTokenId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"name_","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"nextScheduleNum","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"collector","type":"address"}],"name":"numberMinted","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address[]","name":"to","type":"address[]"},{"internalType":"uint32","name":"signedQuantity","type":"uint32"},{"internalType":"uint32","name":"signedClaimTicket","type":"uint32"},{"internalType":"uint32","name":"signedDeadline","type":"uint32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct ISuperMinterV2.PlatformAirdrop","name":"p","type":"tuple"}],"name":"platformAirdrop","outputs":[{"internalType":"uint256","name":"fromTokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"platformFeeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"platformFeeConfig","outputs":[{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"platformFeesAccrued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"platformSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint16","name":"bps","type":"uint16"}],"name":"setAffiliateFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"setAffiliateMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"c","type":"tuple"}],"name":"setDefaultPlatformFeeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"price","type":"uint96"}],"name":"setGAPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32","name":"value","type":"uint32"}],"name":"setMaxMintable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32","name":"value","type":"uint32"}],"name":"setMaxMintablePerAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"setPlatformFeeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"},{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"c","type":"tuple"}],"name":"setPlatformFeeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"setPlatformSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint96","name":"price","type":"uint96"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32","name":"startTime","type":"uint32"}],"name":"setStartTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"}],"name":"setTimeRange","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":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"bool","name":"hasValidAffiliate","type":"bool"}],"name":"totalPriceAndFees","outputs":[{"components":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"subTotal","type":"uint256"},{"internalType":"uint256","name":"unitPrice","type":"uint256"},{"internalType":"uint256","name":"finalArtistFee","type":"uint256"},{"internalType":"uint256","name":"finalAffiliateFee","type":"uint256"},{"internalType":"uint256","name":"finalPlatformFee","type":"uint256"}],"internalType":"struct ISuperMinterV2.TotalPriceAndFees","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"uint96","name":"signedPrice","type":"uint96"},{"internalType":"bool","name":"hasValidAffiliate","type":"bool"}],"name":"totalPriceAndFeesWithSignedPrice","outputs":[{"components":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"subTotal","type":"uint256"},{"internalType":"uint256","name":"unitPrice","type":"uint256"},{"internalType":"uint256","name":"finalArtistFee","type":"uint256"},{"internalType":"uint256","name":"finalAffiliateFee","type":"uint256"},{"internalType":"uint256","name":"finalPlatformFee","type":"uint256"}],"internalType":"struct ISuperMinterV2.TotalPriceAndFees","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"affiliate","type":"address"}],"name":"withdrawForAffiliate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"platform","type":"address"}],"name":"withdrawForPlatform","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101206040523480156200001257600080fd5b50306080524660a05260608062000061604080518082018252600b81526a29bab832b926b4b73a32b960a91b60208083019190915282518084019093526003835262315f3160e81b9083015291565b815160209283012081519183019190912060c082905260e0819052604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8152938401929092529082015246606082015230608082015260a090206101005250620000cb9050565b60805160a05160c05160e051610100516151676200011060003960006139fa01526000613ab401526000613a8e01526000613a3e01526000613a1b01526151676000f3fe6080604052600436106103545760003560e01c8063a01efa34116101c6578063d3ec6f59116100f7578063ea25045411610095578063f57402961161006f578063f574029614610ae9578063f7b2f1bf14610b09578063fb128c83146103a0578063fe1c0c4b14610b1e57610363565b8063ea25045414610a89578063edb3a0a314610aa9578063ef8e19b814610ac957610363565b8063e3d47d5c116100d1578063e3d47d5c146109fc578063e544144314610a29578063e62a61a714610a49578063e7cb88f114610a6957610363565b8063d3ec6f591461097b578063e1a45218146109b0578063e1f3e17d146109c657610363565b8063b276be3511610164578063c4f0c1c21161013e578063c4f0c1c2146108d7578063cbd8aff214610925578063d03206a414610674578063d379ab5f1461095b57610363565b8063b276be3514610863578063b9ee495414610883578063bd3e8fc9146108a357610363565b8063ab986897116101a0578063ab986897146107c9578063ac1fc22c146107f6578063ae85945714610823578063b05786881461084357610363565b8063a01efa3414610774578063a0aefa2a14610794578063a167fd5f146107b457610363565b8063532cf596116102a057806370304e2f1161023e57806384b0196e1161021857806384b0196e146106ff57806387d4d28c146107275780639375da5a1461075457806393e8bcf9146103f657610363565b806370304e2f1461069d578063752d8e91146106ca578063843f92aa146106ea57610363565b80635e7876821161027a5780635e7876821461061457806361b26ea4146106345780636a7319cf146106545780636c5f55f71461067457610363565b8063532cf5961461056657806354fd4d501461059357806359b9370a146105a857610363565b80631b98e5101161030d57806344a8246f116102e757806344a8246f146104f35780634618d76214610513578063498120a0146105335780634a04a1c91461055357610363565b80631b98e5101461047f57806320606b701461049f5780633b79c44f146104d357610363565b806301ffc9a71461036b5780630597fa30146103a057806306fdde03146103d45780630a25dea9146103f657806310bc37791461041d5780631542b7fc1461045f57610363565b3661036357610361610b3e565b005b610361610b3e565b34801561037757600080fd5b5061038b610386366004614075565b610bd6565b60405190151581526020015b60405180910390f35b3480156103ac57600080fd5b506103bc67016345785d8a000081565b6040516001600160601b039091168152602001610397565b3480156103e057600080fd5b506103e9610c01565b60405161039791906140e5565b34801561040257600080fd5b5061040b600081565b60405160ff9091168152602001610397565b34801561042957600080fd5b506104517fbeeccead3be397d17079af6fbbbb014209a75062141befe787822f16816d9da581565b604051908152602001610397565b34801561046b57600080fd5b5061036161047a366004614129565b610c11565b34801561048b57600080fd5b5061040b61049a366004614176565b610c99565b3480156104ab57600080fd5b506104517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b3480156104df57600080fd5b506103616104ee3660046141ab565b610cd1565b3480156104ff57600080fd5b5061036161050e3660046141dc565b610d45565b34801561051f57600080fd5b5061036161052e366004614243565b610e3a565b34801561053f57600080fd5b5061036161054e3660046142b0565b610f18565b6104516105613660046142fb565b611015565b34801561057257600080fd5b50610586610581366004614176565b6114c0565b6040516103979190614423565b34801561059f57600080fd5b506103e9611657565b3480156105b457600080fd5b506105c86105c336600461444b565b611661565b6040516103979190600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b34801561062057600080fd5b5061058661062f3660046141ab565b611699565b34801561064057600080fd5b5061036161064f3660046144c5565b611758565b34801561066057600080fd5b5061038b61066f36600461452c565b6117d1565b34801561068057600080fd5b5061068a6103e881565b60405161ffff9091168152602001610397565b3480156106a957600080fd5b506106bd6106b83660046145b6565b6117f5565b604051610397919061462e565b3480156106d657600080fd5b506105866106e5366004614176565b6118d9565b3480156106f657600080fd5b5061040b600381565b34801561070b57600080fd5b50610714611995565b6040516103979796959493929190614674565b34801561073357600080fd5b506104516107423660046141ab565b60006020819052908152604090205481565b34801561076057600080fd5b5061036161076f3660046141ab565b6119bc565b34801561078057600080fd5b5061036161078f366004614129565b611a31565b3480156107a057600080fd5b506103616107af366004614865565b611ae4565b3480156107c057600080fd5b5061040b600281565b3480156107d557600080fd5b506107e96107e43660046141ab565b611c27565b60405161039791906149c2565b34801561080257600080fd5b506104516108113660046141ab565b60026020526000908152604090205481565b34801561082f57600080fd5b5061040b61083e366004614a05565b611d1d565b34801561084f57600080fd5b5061036161085e366004614243565b612182565b34801561086f57600080fd5b5061036161087e366004614243565b6122ad565b34801561088f57600080fd5b506105c861089e366004614ae5565b6122f5565b3480156108af57600080fd5b506104517fc03e2545e609fd0b7813d6074f00235b048ae7580a8e57070eed03901dd951ae81565b3480156108e357600080fd5b5061090d6108f23660046141ab565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610397565b34801561093157600080fd5b506103bc6109403660046141ab565b6003602052600090815260409020546001600160601b031681565b34801561096757600080fd5b50610361610976366004614b50565b612316565b34801561098757600080fd5b5061099b610996366004614b9b565b6123b5565b60405163ffffffff9091168152602001610397565b3480156109bc57600080fd5b5061068a61271081565b3480156109d257600080fd5b5061090d6109e13660046141ab565b6001602052600090815260409020546001600160a01b031681565b348015610a0857600080fd5b50610a1c610a17366004614bf3565b612404565b6040516103979190614c38565b348015610a3557600080fd5b50610361610a44366004614c47565b61257c565b348015610a5557600080fd5b50610451610a643660046142fb565b612631565b348015610a7557600080fd5b50610451610a84366004614c94565b612777565b348015610a9557600080fd5b50610361610aa4366004614cd0565b612922565b348015610ab557600080fd5b50610361610ac43660046141ab565b612a75565b348015610ad557600080fd5b50610451610ae4366004614c94565b612b1b565b348015610af557600080fd5b50610361610b043660046141ab565b612c2f565b348015610b1557600080fd5b5061040b600181565b348015610b2a57600080fd5b5061038b610b39366004614b9b565b612cb0565b36610b47573636f35b6000805b80368210610b595750610bb5565b600180830192600319810190351860001a9081610ba557600019855260028301933560021984011860001a607f808211610b94578282013888395b16949094019093019250610b4b9050565b8185538085019450505050610b4b565b50600038826000305af490503d6000803e80610bd0573d6000fd5b503d6000f35b60006301ffc9a760e01b6001600160e01b0319831690811463075dd78560e41b909114175b92915050565b6060610c0b612cc9565b50919050565b83610c1b81612d08565b6000610c28868686612e0b565b90506000610c3582612e27565b600281018590556040805160ff808a168252881660208201529081018690529091506001600160a01b038816907fe08051cfd6c9341327f7f5550f77e02e815f59c1ecba22a4ac006ddca62dec20906060015b60405180910390a250505050505050565b600060056000610cab85856000612e0b565b8152602081019190915260400160002060010154600160e01b900460ff16905092915050565b6000610cdb612e6a565b6001600160a01b0381811660008181526004602090815260409182902080546001600160a01b03191694881694851790559051928352929350917fb9aba67a9619eecb4b3e9fe6ded4a35c9bcdbfb1040f5122f91716de616a799391015b60405180910390a25050565b84610d4f81612d08565b6000610d5c878787612e0b565b90506000610d6982612e27565b905060ff8716158015610d82575063ffffffff84811614155b15610da05760405163d25a973560e01b815260040160405180910390fd5b610daa8585612ec8565b60018101805463ffffffff87811667ffffffffffffffff199092168217640100000000918816918202179092556040805160ff808c1682528a1660208201529081019190915260608101919091526001600160a01b038916907f41ad9ed088bad8a3ad3052c7360f6919b647b45d4b527e478d463edbb8f9a4359060800160405180910390a25050505050505050565b83610e4481612d08565b6000610e51868686612e0b565b90506000610e5e82612e27565b905060ff8616158015610e7d57506001810154600160e81b900460ff16155b15610e9b5760405163d25a973560e01b815260040160405180910390fd5b610ea484612ef5565b60018101805463ffffffff60601b1916600160601b63ffffffff8716908102919091179091556040805160ff808a16825288166020820152908101919091526001600160a01b038816907f5da54689220406b0ee18edb07d2007345f96968da27c7fd0f405f649d26040a890606001610c88565b83610f2281612d08565b6000610f2f868686612e0b565b90506000610f3c82612e27565b905060ff8616158015610f5e57506001810154600160e81b900460ff16600214155b15610f7c5760405163d25a973560e01b815260040160405180910390fd5b6001810154600219600160e81b90910460ff1601610fad5760405163d25a973560e01b815260040160405180910390fd5b80546001600160601b038516600160a01b81026001600160a01b039283161783556040805160ff8a811682528916602082015290810191909152908816907f3b082de0ef84f822f97496af03a3df5a8d5f0c271ea658b5b210819f1310494f90606001610c88565b60008061105561105061102b60208601866141ab565b61103b6040870160208801614cfc565b61104b6060880160408901614cfc565b612e0b565b612e27565b905061106081612f1f565b6001810154600160e81b900460ff166000198101611087576110828285612fb3565b6110c2565b60011960ff82160161109d576110828285613134565b60021960ff8216016110c25760405163a0042b1760e01b815260040160405180910390fd5b6110cd81838661329d565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081018290526101808101919091526111486101c086016101a087016141ab565b6001600160a01b031661116160808701606088016141ab565b6001600160a01b031614611186576111816101c086016101a087016141ab565b611189565b60005b6001600160a01b031660c082018190526111b29084906111ad6101c0890189614d17565b6134a3565b151560e082015260006111fb6111ce6040880160208901614cfc565b856111df60a08a0160808b01614d61565b6111f16101208b016101008c016144c5565b8660e001516134f7565b80519091503414611230578051604051630374cb4760e21b815234600482015260248101919091526044015b60405180910390fd5b606081015161014083015260a0810151610180830152608081015161016083018190521561129557610160820151600260006112746101c08a016101a08b016141ab565b6001600160a01b031681526020810191909152604001600020805490910190555b610180820151156112c75761018082015184546001600160a01b03166000908152602081905260409020805490910190555b60006112d660208801886141ab565b90506112e860a0880160808901614d61565b63ffffffff1683526101408301516001600160a01b0382169063eebab8ef9061131760408b0160208c01614cfc565b61132760808c0160608d016141ab565b61133760a08d0160808e01614d61565b6040516001600160e01b031960e087901b16815260ff90931660048401526001600160a01b03909116602483015263ffffffff16604482015260640160206040518083038185885af1158015611391573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906113b69190614d7c565b60208401526113cb60c0880160a089016141ab565b6001600160a01b031660408401526113e960e0880160c08901614d61565b63ffffffff16606084015261140661016088016101408901614d61565b63ffffffff1660a0840152815161010084015260408201516101208401526101e087013561143a6080890160608a016141ab565b6001600160a01b031661145060208a018a6141ab565b6001600160a01b03167f2a29f7402bd32f0e4bbe17d44be064f7f64d96ee174ed7cb27936d869bf9a88861148a60408c0160208d01614cfc565b61149a60608d0160408e01614cfc565b886040516114aa93929190614d95565b60405180910390a4505060200151949350505050565b6114c8613f5f565b606083811b60ff8481169190911760009081526006602090815260409182902082516101408101845281546001600160601b038082168352600160601b918290048116948301949094526001830154808516958301959095529384900483169581019590955260028101548083166080870152839004821660a08601526003015480821660c08601529182041660e0840152600160c01b810461ffff16610100840152600160d01b9004161515610120820181905261163b5760066000606086901b610100178152602080820192909252604090810160002081516101408101835281546001600160601b038082168352600160601b91829004811695830195909552600183015480861694830194909452928390048416606082015260028201548085166080830152839004841660a082015260039091015480841660c083015291820490921660e0830152600160c01b810461ffff16610100830152600160d01b900460ff16151561012082015290505b8061012001516116505761164d613f5f565b90505b9392505050565b6060610bfb612cc9565b611669613fb3565b6000611676888888612e0b565b905061168d8761168583612e27565b8787876134f7565b98975050505050505050565b6116a1613f5f565b50610100606091821b811760009081526006602090815260409182902082516101408101845281546001600160601b038082168352600160601b918290048116948301949094526001830154808516958301959095529384900483169581019590955260028101548083166080870152839004821660a08601526003015480821660c08601529182041660e084015261ffff600160c01b8204169183019190915260ff600160d01b90910416151561012082015290565b6000611762612e6a565b6001600160a01b03811660008181526003602090815260409182902080546bffffffffffffffffffffffff19166001600160601b038816908117909155915191825292935090917fed3d3f99e57c78ce76ac9a1704a72bb912e8f231cc25c6379fdf5354dbb6481b9101610d39565b6000806117df888888612e0b565b905061168d6117ed82612e27565b8686866134a3565b60606000611804878787612e0b565b60008181526008602052604090209091508367ffffffffffffffff81111561182e5761182e61470a565b604051908082528060200260200182016040528015611857578160200160208202803683370190505b50925060005b8085146118cd576118a386868381811061187957611879614e86565b905060200201602081019061188e9190614d61565b63ffffffff16836137d690919063ffffffff16565b8482815181106118b5576118b5614e86565b9115156020928302919091019091015260010161185d565b50505095945050505050565b6118e1613f5f565b5060ff908116606092831b1760009081526006602090815260409182902082516101408101845281546001600160601b038082168352600160601b918290048116948301949094526001830154808516958301959095529384900483169581019590955260028101548083166080870152839004821660a08601526003015480821660c08601529182041660e084015261ffff600160c01b820416610100840152600160d01b900416151561012082015290565b600f60f81b60608060008080836119aa612cc9565b97989097965046955030945091925090565b60006119c6612e6a565b90506119d1826137f8565b6001600160a01b0381811660008181526001602090815260409182902080546001600160a01b0319169487169485179055905192835290917f3a9b87574e9f01aaafa6d829c77645fe96010be0b3093259c7873f4a93de28e99101610d39565b83611a3b81612d08565b6000611a48868686612e0b565b90506000611a5582612e27565b600180820154919250600160e81b90910460ff1614611a875760405163d25a973560e01b815260040160405180910390fd5b611a908461381f565b600381018490556040805160ff8089168252871660208201529081018590526001600160a01b038816907f0b0a6fe894fe7695ac067d44d6e0de766337e9c3b5f0ee0a61be727383aac5a790606001610c88565b6000611aee612e6a565b9050611af98261383d565b8160066000606084901b610100178152602080820192909252604090810160002083518154938501516001600160601b039182166001600160c01b031995861617600160601b9183168202178355858401516001840180546060890151928516908816179184168302919091179055608086015160028401805460a089015192851690881617918416830291909117905560c08601516003909301805460e088015161010089015161012090990151958516919097161795909216029390931762ffffff60c01b1916600160c01b61ffff9095169490940260ff60d01b191693909317600160d01b93151593909302929092179055516001600160a01b038216907fe6bb0d56f1c8a28e8a4fa4c725b521b129a2d80fa461d8365016d98c4775ab0f90610d39908590614423565b606081811b6000908152600560205260409020600181015461ffff600160d01b8204811691600160c01b9004168167ffffffffffffffff811115611c6d57611c6d61470a565b604051908082528060200260200182016040528015611ca657816020015b611c93613fe9565b815260200190600190039081611c8b5790505b5093505b8115611d155761ffff8116606086901b176000908152600560205260409020611cdb8660ff600885901c1684612404565b85846001900394508481518110611cf457611cf4614e86565b602090810291909101015260010154600160b01b900461ffff169050611caa565b505050919050565b6000611d2c8260000151612d08565b611d398260c00151613979565b61014082015160ff8116611d54576000610160840152611dd9565b60001960ff821601611d7357611d6e83610160015161381f565b611dd9565b60011960ff821601611d9657600061016084015263ffffffff6080840152611dd9565b60021960ff821601611dc0576000610160840181905263ffffffff60808501526020840152611dd9565b60405163a0042b1760e01b815260040160405180910390fd5b61010083015160ff16611e1d5763ffffffff60608401819052608084015260ff8116600214611e0a57600060208401525b60ff8116611e1d5763ffffffff60a08401525b611e2f83604001518460600151612ec8565b611e3c83608001516139a0565b611e498360a00151612ef5565b600060056000611e6486600001518761010001516000612e0b565b815260208082019290925260409081016000908120875160601b8252600590935220600180830154600160e01b900460ff1695509192509084016101008110611eaf57611eaf6139c7565b6001808401805460ff909316600160e01b0260ff60e01b19909316929092179091558181015461ffff600160d01b9091041601620100008110611ef457611ef46139c7565b60018201805461ffff60d01b1916600160d01b61ffff8416021790558551610100870151600091611f259188612e0b565b905060006005600083815260200190815260200160002090508761012001518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555087602001518160000160146101000a8154816001600160601b0302191690836001600160601b0316021790555087604001518160010160006101000a81548163ffffffff021916908363ffffffff16021790555087606001518160010160046101000a81548163ffffffff021916908363ffffffff16021790555087608001518160010160086101000a81548163ffffffff021916908363ffffffff1602179055508760a0015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055508760c001518160010160146101000a81548161ffff021916908361ffff16021790555087610140015181600101601d6101000a81548160ff021916908360ff160217905550600181600101601e6101000a81548160ff021916908360ff1602179055508360010160189054906101000a900461ffff168160010160166101000a81548161ffff021916908361ffff1602179055508660ff16600889610100015160ff16901b178460010160186101000a81548161ffff021916908361ffff1602179055506000801b8860e00151146121125760e088015160028201555b610160880151156121295761016088015160038201555b87600001516001600160a01b03167f71e782e300c458b9de1211d63df057e6f372a85a3b394606ac3335907b14f097896101000151898b60405161216f93929190614e9c565b60405180910390a2505050505050919050565b8361218c81612d08565b6000612199868686612e0b565b905060006121a682612e27565b905060ff86166121c95760405163d25a973560e01b815260040160405180910390fd5b6001810154600119600160e81b90910460ff16016121fa5760405163d25a973560e01b815260040160405180910390fd5b6001810154600219600160e81b90910460ff160161222b5760405163d25a973560e01b815260040160405180910390fd5b612234846139a0565b6001810180546bffffffff00000000000000001916600160401b63ffffffff8716908102919091179091556040805160ff808a16825288166020820152908101919091526001600160a01b038816907f674233c20daf715ad9e94f9e5818adc53482b77e9556564e5fe3766678246e8e90606001610c88565b60006122ba858585612e0b565b6000818152600560205260409020600101549091506122ee908690869086908690640100000000900463ffffffff16610d45565b5050505050565b6122fd613fb3565b61230c86868686600087611661565b9695505050505050565b8361232081612d08565b600061232d868686612e0b565b9050600061233a82612e27565b905061234584613979565b60018101805461ffff60a01b1916600160a01b61ffff8716908102919091179091556040805160ff808a16825288166020820152908101919091526001600160a01b038816907fcdff4ec2999e249a9a848accff5e46b43263f82c4076334cd70300e07326472d90606001610c88565b6000806123c3868686612e0b565b6001600160a01b0384166000908152600760209081526040808320600385901c845290915290205490915060e0600583901b161c5b9150505b949350505050565b61240c613fe9565b6000612419858585612e0b565b9050600061242682612e27565b6001600160a01b03808816855260ff8088166020870181905290871660408701528254909116606086015290915015801561247057506001810154600160e81b900460ff16600214155b61248b578054600160a01b90046001600160601b03166124af565b80546001600160a01b03166000908152600360205260409020546001600160601b03165b6001600160601b03166080840152600181015463ffffffff80821660a08601526401000000008204811660c0860152600160401b8204811660e0860152600160601b82048116610100860152600160801b820416610120850152600160a01b810461ffff16610140850152600160e81b810460ff166101608501526002600160f01b909104811615156101808501528101546101c084015260038101546101e0840152546001600160a01b0390811660009081526004602052604090205416610200830152509392505050565b8361258681612d08565b6000612593868686612e0b565b905060006125a082612e27565b60018101549091506125c99060ff600160f01b9091041660028660ff8383161615901518021890565b60018201805460ff60f01b1916600160f01b60ff938416021790556040805188831681529187166020830152851515908201526001600160a01b038816907f81bd379475659273b35365d353d46c7de87aa468a01efc54544fcee90ae0d3b690606001610c88565b6000610bfb7fc03e2545e609fd0b7813d6074f00235b048ae7580a8e57070eed03901dd951ae61266460208501856141ab565b6126746040860160208701614cfc565b6126846060870160408801614cfc565b61269460808801606089016141ab565b6126a661014089016101208a01614d61565b6126b86101608a016101408b01614d61565b6126ca6101208b016101008c016144c5565b6126dc6101808c016101608d01614d61565b6126ee6101c08d016101a08e016141ab565b60408051602081019b909b526001600160a01b03998a16908b015260ff97881660608b015296909516608089015292861660a088015263ffffffff91821660c0880152811660e08701526001600160601b039091166101008601521661012084015216610140820152610160015b604051602081830303815290604052805190602001206139f8565b60008061278d61105061102b60208601866141ab565b905061279881612f1f565b6001810154600160e81b900460ff166003146127c75760405163a0042b1760e01b815260040160405180910390fd5b6127d18184613b10565b6127db8184613bc1565b60006127ea60208501856141ab565b90506001600160a01b03811663010fe62c61280b6040870160208801614cfc565b6128186060880188614d17565b61282860a08a0160808b01614d61565b6040518563ffffffff1660e01b81526004016128479493929190614fe1565b6020604051808303816000875af1158015612866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288a9190614d7c565b925061289960208501856141ab565b6001600160a01b03167f0b4410e982ad454e02d2fb1663c16f53389d5126913f7223d14d8a8b311c33246128d36040870160208801614cfc565b6128e36060880160408901614cfc565b6128f06060890189614d17565b61290060a08b0160808c01614d61565b8960405161291396959493929190615015565b60405180910390a25050919050565b600061292c612e6a565b90506129378261383d565b8160066000606084901b60ff8716178152602080820192909252604090810160002083518154938501516001600160601b039182166001600160c01b031995861617600160601b9183168202178355858401516001840180546060890151928516908816179184168302919091179055608086015160028401805460a089015192851690881617918416830291909117905560c08601516003909301805460e088015161010089015161012090990151958516919097161795909216029390931762ffffff60c01b1916600160c01b61ffff9095169490940260ff60d01b191693909317600160d01b93151593909302929092179055516001600160a01b038216907f7fcaf05e0d01e61bfcf3c7d5035259d2bbdb13b68a9c0f183b52d074a3f1110490612a689086908690615056565b60405180910390a2505050565b6001600160a01b0380821660009081526001602052604090205416612a99816137f8565b6001600160a01b0382166000908152602081905260409020548015612b16576001600160a01b038316600090815260208190526040812055612adb8282613d26565b826001600160a01b03167ffc7ad544ff6a06d6499925723d25b6fe70457a42939995b1d3d6f560fe33633382604051612a6891815260200190565b505050565b6000610bfb7fbeeccead3be397d17079af6fbbbb014209a75062141befe787822f16816d9da5612b4e60208501856141ab565b612b5e6040860160208701614cfc565b612b6e6060870160408801614cfc565b612b7b6060880188614d17565b604051602001612b8c92919061506e565b60408051601f198184030181529190528051602090910120612bb460a0890160808a01614d61565b612bc460c08a0160a08b01614d61565b612bd460e08b0160c08c01614d61565b6040805160208101999099526001600160a01b039097169688019690965260ff948516606088015293909216608086015260a085015263ffffffff90811660c085015290811660e0840152166101008201526101200161275c565b6001600160a01b0381166000908152600260205260409020548015612cac576001600160a01b038216600090815260026020526040812055612c718282613d26565b816001600160a01b03167f0a1adaaf9d9caba9cf65528900e946b718d511ebd66ae81d5eb71e7fd0122c4a82604051610d3991815260200190565b5050565b6000612cc08585858536866117d1565b95945050505050565b604080518082018252600b81526a29bab832b926b4b73a32b960a91b60208083019190915282518084019093526003835262315f3160e81b9083015291565b6000612d12612e6a565b9050816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d7691906150b0565b6001600160a01b0316816001600160a01b031614612cac5760405163145398bf60e21b81526001600160a01b0382811660048301526001602483015283169063514e62fc90604401602060405180830381865afa158015612ddb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dff91906150cd565b612cac57612cac613d69565b60008360601b60005282601e5381601f53505060005192915050565b60008181526005602052604081206001808201549192600160f01b909204169003612e655760405163947dbacd60e01b815260040160405180910390fd5b919050565b6000336000526e2fd5aeb385d324b580fca7c83823a0803303612e9857602060008038845afa612e98573838fd5b506dd9ecebf3c23529de49815dac1c4c803303612ec057602060008038845afa612ec0573838fd5b505060005190565b8063ffffffff168263ffffffff161115612cac5760405163536a71af60e01b815260040160405180910390fd5b8063ffffffff16600003612f1c57604051630ccae60160e31b815260040160405180910390fd5b50565b600181015442640100000000820463ffffffff90811682119216111715612f7e57600181015460405163296f4f6960e01b815242600482015263ffffffff80831660248301526401000000009092049091166044820152606401611227565b612f958160010154600160f01b9004600216151590565b15612f1c57604051636be9245d60e11b815260040160405180910390fd5b6000612fc560e0830160c08401614d61565b90506000612fd960c0840160a085016141ab565b90506001600160a01b0381166130025760405163582f497d60e11b815260040160405180910390fd5b63fffffffe1963ffffffff83160161308d57613041846003015461302b836000526014600c2090565b61303860e0870187614d17565b90929091613d77565b15801561306a5750613068846003015461302b8363ffffffff6004526000526018600c2090565b155b156130885760405163582f497d60e11b815260040160405180910390fd5b6130c5565b6130a8846003015461302b83856004526000526018600c2090565b6130c55760405163582f497d60e11b815260040160405180910390fd5b60006130cf612e6a565b90506131096001600160a01b038381169083168114906130f560808801606089016141ab565b6001600160a01b0316149015159015151790565b6122ee576131178183613db1565b6122ee5760405163fe736e0160e01b815260040160405180910390fd5b61314661014082016101208301614d61565b63ffffffff1661315c60a0830160808401614d61565b63ffffffff161115613181576040516352ad28c360e11b815260040160405180910390fd5b81546001600160a01b03908116600090815260046020526040902054166131be816131ab84612631565b6131b96101808601866150ea565b613df2565b6131db57604051638baa579f60e01b815260040160405180910390fd5b6131ed61018083016101608401614d61565b63ffffffff1642111561321357604051630819bdcd60e01b815260040160405180910390fd5b600061324561322560208501856141ab565b6132356040860160208701614cfc565b61104b6060870160408801614cfc565b905061327a61325c61016085016101408601614d61565b60008381526008602052604090209063ffffffff90811690613eeb16565b6132975760405163900bb2c960e01b815260040160405180910390fd5b50505050565b60006132af60a0830160808401614d61565b600184015463ffffffff918216600160801b82048316019250600160601b9004168111156132f057604051637f70f90b60e01b815260040160405180910390fd5b60018301805463ffffffff60801b1916600160801b63ffffffff841602179055600061332261322560208501856141ab565b905060001960ff8616016133fb57600060078161334560c0870160a088016141ab565b6001600160a01b031681526020810191909152604001600020905061337060a0850160808601614d61565b63ffffffff1661338983836139d590919063ffffffff16565b600187015463ffffffff9182169290920194506133cc91600160401b90041684116133ba60e0870160c08801614d61565b63ffffffff1685119015159015151790565b156133ea57604051631b75136560e01b815260040160405180910390fd5b6133f5818385613f17565b506122ee565b600060078161341060808701606088016141ab565b6001600160a01b031681526020810191909152604001600020905061343b60a0850160808601614d61565b63ffffffff1661345483836139d590919063ffffffff16565b600187015463ffffffff918216929092019450600160401b9091041683111561349057604051631b75136560e01b815260040160405180910390fd5b61349b818385613f17565b505050505050565b6002840154600090806134c35750506001600160a01b03831615156123fc565b6123f86001600160a01b03861615156134ee836134e5896000526014600c2090565b88918891613d77565b15159015151690565b6134ff613fb3565b8454600090613517906001600160a01b0316886114c0565b6001870154909150600119600160e81b90910460ff160161357c5785546001600160601b03600160a01b909104811690851610156135685760405163dcdc2f1560e01b815260040160405180910390fd5b6001600160601b03841660408301526135ca565b60ff87166135b25785546001600160a01b031660009081526003602052604090819020546001600160601b0316908301526135ca565b8554600160a01b90046001600160601b031660408301525b604082015163ffffffff8616026020830181905260608301526001860154600160a01b900461ffff16158015906135fe5750825b156136335760208201516001870154600091612710600160a01b90920461ffff16020460608401805182900390526080840152505b61010081015161ffff161561366d57602082015161010082015160009161271061ffff9092160204606084018051829003905260a0840152505b80606001516001600160601b031682604001511161371457805160608301805163ffffffff88166001600160601b039384168102909101909152604083015160a0850180519190931690910201905282156136eb5760208101516080830180516001600160601b0390921663ffffffff8816029190910190526137a3565b602081015160a0830180516001600160601b0390921663ffffffff8816029190910190526137a3565b608081015160608301805163ffffffff88166001600160601b03938416810290910190915260c083015160a08501805191909316909102019052821561377d5760a08101516080830180516001600160601b0390921663ffffffff8816029190910190526137a3565b8463ffffffff168160a001516001600160601b0316028260a00181815101915081815250505b60e0015160a0820180516001600160601b0390921690910190819052608082015160608301510101815295945050505050565b600881901c6000908152602092909252604090912054600160ff9092161c1690565b6001600160a01b038116612f1c576040516362ccef3360e01b815260040160405180910390fd5b80612f1c5760405163caa2867f60e01b815260040160405180910390fd5b61395b61388067016345785d8a00006001600160601b03168360e001516001600160601b0316116103e861ffff1684610100015161ffff16119015159015151790565b6138eb67016345785d8a00006001600160601b031684600001516001600160601b03161167016345785d8a00006001600160601b031685602001516001600160601b03161167016345785d8a00006001600160601b031686604001516001600160601b031611613f4b565b61395667016345785d8a00006001600160601b031685608001516001600160601b03161167016345785d8a00006001600160601b03168660a001516001600160601b03161167016345785d8a00006001600160601b03168760c001516001600160601b031611613f4b565b613f4b565b15612f1c5760405163b17424c360e01b815260040160405180910390fd5b6103e861ffff82161115612f1c57604051631a52ce6f60e01b815260040160405180910390fd5b8063ffffffff16600003612f1c5760405163a017714560e01b815260040160405180910390fd5b6335278d126000526004601cfd5b600381901c600090815260209290925260409091205460059190911b60e0161c90565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000030147f0000000000000000000000000000000000000000000000000000000000000000461416613aeb5750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f00000000000000000000000000000000000000000000000000000000000000009181019190915246606082015230608082015260a090205b67190100000000000060005280601a5281603a52604260182090506000603a52919050565b81546001600160a01b0390811660009081526004602052604090205416613b4781613b3a84612b1b565b6131b960e08601866150ea565b613b6457604051638baa579f60e01b815260040160405180910390fd5b613b7460e0830160c08401614d61565b63ffffffff16421115613b9a57604051630819bdcd60e01b815260040160405180910390fd5b6000613bac61322560208501856141ab565b905061327a61325c60c0850160a08601614d61565b6000613bf3613bd360208401846141ab565b613be36040850160208601614cfc565b61104b6060860160408701614cfc565b90506000613c046060840184614d17565b915060009050613c1a60a0850160808601614d61565b600186015463ffffffff9182168402600160801b82048316019250600160601b900416811115613c5d57604051637f70f90b60e01b815260040160405180910390fd5b60018501805463ffffffff60801b1916600160801b63ffffffff84160217905560005b82811461349b576000600781613c996060890189614d17565b85818110613ca957613ca9614e86565b9050602002016020810190613cbe91906141ab565b6001600160a01b0316815260208101919091526040016000209050613d1d85613ced60a0890160808a01614d61565b63ffffffff16613d0688856139d590919063ffffffff16565b63ffffffff160183613f179092919063ffffffff16565b50600101613c80565b80471015613d3c5763b12d13eb6000526004601cfd5b6000386000388486620186a0f1612cac57816000526073600b5360ff6020536016600b82f0612cac573838fd5b6382b429006000526004601cfd5b60008315613da9578360051b8501855b803580851160051b94855260209485185260406000209301818110613d875750505b501492915050565b600060405163e839bd536000528360205282604052602060006064601c6c447e69651d841bd8d104bed4935afa600160005114169150806040525092915050565b6001600160a01b0390931692600084156123fc576040518460005260408303613e5d5760208481013560ff81901c601b01825285356040526001600160ff1b0316606052600160806000825afa805187183d1517613e5b575060006060526040525060016123fc565b505b60418303613ea057604084013560001a602052604084604037602060016080600060015afa805187183d1517613e9e575060006060526040525060016123fc565b505b600060605280604052631626ba7e60e01b80825285600483015260248201604081528460448401528486606485013760208160648701858b5afa905190911416915050949350505050565b602091909152600881901c6000908152604090208054600160ff90931683811b909118918290551c1690565b826020528160031c60005260406000206007831660051b815463ffffffff8482841c188116831b8218845550505050505050565b6000831515831515831515171515176123fc565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e0810182905261020081019190915290565b60006020828403121561408757600080fd5b81356001600160e01b03198116811461165057600080fd5b6000815180845260005b818110156140c5576020818501810151868301820152016140a9565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000611650602083018461409f565b6001600160a01b0381168114612f1c57600080fd5b8035612e65816140f8565b803560ff81168114612e6557600080fd5b6000806000806080858703121561413f57600080fd5b843561414a816140f8565b935061415860208601614118565b925061416660408601614118565b9396929550929360600135925050565b6000806040838503121561418957600080fd5b8235614194816140f8565b91506141a260208401614118565b90509250929050565b6000602082840312156141bd57600080fd5b8135611650816140f8565b803563ffffffff81168114612e6557600080fd5b600080600080600060a086880312156141f457600080fd5b85356141ff816140f8565b945061420d60208701614118565b935061421b60408701614118565b9250614229606087016141c8565b9150614237608087016141c8565b90509295509295909350565b6000806000806080858703121561425957600080fd5b8435614264816140f8565b935061427260208601614118565b925061428060408601614118565b915061428e606086016141c8565b905092959194509250565b80356001600160601b0381168114612e6557600080fd5b600080600080608085870312156142c657600080fd5b84356142d1816140f8565b93506142df60208601614118565b92506142ed60408601614118565b915061428e60608601614299565b60006020828403121561430d57600080fd5b813567ffffffffffffffff81111561432457600080fd5b8201610200818503121561165057600080fd5b80516001600160601b03168252602081015161435e60208401826001600160601b03169052565b50604081015161437960408401826001600160601b03169052565b50606081015161439460608401826001600160601b03169052565b5060808101516143af60808401826001600160601b03169052565b5060a08101516143ca60a08401826001600160601b03169052565b5060c08101516143e560c08401826001600160601b03169052565b5060e081015161440060e08401826001600160601b03169052565b506101008181015161ffff16908301526101208082015180151582850152613297565b6101408101610bfb8284614337565b8015158114612f1c57600080fd5b8035612e6581614432565b60008060008060008060c0878903121561446457600080fd5b863561446f816140f8565b955061447d60208801614118565b945061448b60408801614118565b9350614499606088016141c8565b92506144a760808801614299565b915060a08701356144b781614432565b809150509295509295509295565b6000602082840312156144d757600080fd5b61165082614299565b60008083601f8401126144f257600080fd5b50813567ffffffffffffffff81111561450a57600080fd5b6020830191508360208260051b850101111561452557600080fd5b9250929050565b60008060008060008060a0878903121561454557600080fd5b8635614550816140f8565b955061455e60208801614118565b945061456c60408801614118565b9350606087013561457c816140f8565b9250608087013567ffffffffffffffff81111561459857600080fd5b6145a489828a016144e0565b979a9699509497509295939492505050565b6000806000806000608086880312156145ce57600080fd5b85356145d9816140f8565b94506145e760208701614118565b93506145f560408701614118565b9250606086013567ffffffffffffffff81111561461157600080fd5b61461d888289016144e0565b969995985093965092949392505050565b6020808252825182820181905260009190848201906040850190845b8181101561466857835115158352928401929184019160010161464a565b50909695505050505050565b60ff60f81b881681526000602060e08184015261469460e084018a61409f565b83810360408501526146a6818a61409f565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156146f8578351835292840192918401916001016146dc565b50909c9b505050505050505050505050565b634e487b7160e01b600052604160045260246000fd5b604051610140810167ffffffffffffffff8111828210171561475257634e487b7160e01b600052604160045260246000fd5b60405290565b604051610180810167ffffffffffffffff8111828210171561475257634e487b7160e01b600052604160045260246000fd5b803561ffff81168114612e6557600080fd5b600061014082840312156147af57600080fd5b6147b7614720565b90506147c282614299565b81526147d060208301614299565b60208201526147e160408301614299565b60408201526147f260608301614299565b606082015261480360808301614299565b608082015261481460a08301614299565b60a082015261482560c08301614299565b60c082015261483660e08301614299565b60e082015261010061484981840161478a565b9082015261012061485b838201614440565b9082015292915050565b6000610140828403121561487857600080fd5b611650838361479c565b80516001600160a01b0316825260208101516148a3602084018260ff169052565b5060408101516148b8604084018260ff169052565b5060608101516148d360608401826001600160a01b03169052565b5060808101516148ee60808401826001600160601b03169052565b5060a081015161490660a084018263ffffffff169052565b5060c081015161491e60c084018263ffffffff169052565b5060e081015161493660e084018263ffffffff169052565b506101008181015163ffffffff9081169184019190915261012080830151909116908301526101408082015161ffff16908301526101608082015160ff1690830152610180808201511515908301526101a0808201511515908301526101c080820151908301526101e08082015190830152610200808201516001600160a01b03811682850152613297565b6020808252825182820181905260009190848201906040850190845b81811015614668576149f1838551614882565b9284019261022092909201916001016149de565b60006101808284031215614a1857600080fd5b614a20614758565b614a298361410d565b8152614a3760208401614299565b6020820152614a48604084016141c8565b6040820152614a59606084016141c8565b6060820152614a6a608084016141c8565b6080820152614a7b60a084016141c8565b60a0820152614a8c60c0840161478a565b60c082015260e083013560e0820152610100614aa9818501614118565b90820152610120614abb84820161410d565b90820152610140614acd848201614118565b90820152610160928301359281019290925250919050565b600080600080600060a08688031215614afd57600080fd5b8535614b08816140f8565b9450614b1660208701614118565b9350614b2460408701614118565b9250614b32606087016141c8565b91506080860135614b4281614432565b809150509295509295909350565b60008060008060808587031215614b6657600080fd5b8435614b71816140f8565b9350614b7f60208601614118565b9250614b8d60408601614118565b915061428e6060860161478a565b60008060008060808587031215614bb157600080fd5b8435614bbc816140f8565b9350614bca60208601614118565b9250614bd860408601614118565b91506060850135614be8816140f8565b939692955090935050565b600080600060608486031215614c0857600080fd5b8335614c13816140f8565b9250614c2160208501614118565b9150614c2f60408501614118565b90509250925092565b6102208101610bfb8284614882565b60008060008060808587031215614c5d57600080fd5b8435614c68816140f8565b9350614c7660208601614118565b9250614c8460408601614118565b91506060850135614be881614432565b600060208284031215614ca657600080fd5b813567ffffffffffffffff811115614cbd57600080fd5b8201610100818503121561165057600080fd5b6000806101608385031215614ce457600080fd5b614ced83614118565b91506141a2846020850161479c565b600060208284031215614d0e57600080fd5b61165082614118565b6000808335601e19843603018112614d2e57600080fd5b83018035915067ffffffffffffffff821115614d4957600080fd5b6020019150600581901b360382131561452557600080fd5b600060208284031215614d7357600080fd5b611650826141c8565b600060208284031215614d8e57600080fd5b5051919050565b60ff848116825283166020820152815163ffffffff1660408201526101e081016020830151606083015260408301516001600160a01b038116608084015250606083015163ffffffff811660a084015250608083015163ffffffff811660c08401525060a083015163ffffffff811660e08401525060c0830151610100614e26818501836001600160a01b03169052565b60e08501519150610120614e3d8186018415159052565b908501516101408581019190915290850151610160808601919091529085015161018080860191909152908501516101a0850152909301516101c0909201919091529392505050565b634e487b7160e01b600052603260045260246000fd5b60ff84811682528316602082015281516001600160a01b031660408201526101c0810160208301516001600160601b038116606084015250604083015163ffffffff8116608084015250606083015163ffffffff811660a084015250608083015163ffffffff811660c08401525060a083015163ffffffff811660e08401525060c0830151610100614f338185018361ffff169052565b60e08501516101208581019190915290850151915061014090614f5a8286018460ff169052565b8501519150610160614f76858201846001600160a01b03169052565b9085015160ff16610180850152909301516101a0909201919091529392505050565b8183526000602080850194508260005b85811015614fd6578135614fbb816140f8565b6001600160a01b031687529582019590820190600101614fa8565b509495945050505050565b60ff85168152606060208201526000614ffe606083018587614f98565b905063ffffffff8316604083015295945050505050565b60ff8716815260ff8616602082015260a06040820152600061503b60a083018688614f98565b63ffffffff9490941660608301525060800152949350505050565b60ff8316815261016081016116506020830184614337565b60008184825b858110156150a5578135615087816140f8565b6001600160a01b031683526020928301929190910190600101615074565b509095945050505050565b6000602082840312156150c257600080fd5b8151611650816140f8565b6000602082840312156150df57600080fd5b815161165081614432565b6000808335601e1984360301811261510157600080fd5b83018035915067ffffffffffffffff82111561511c57600080fd5b60200191503681900382131561452557600080fdfea26469706673582212207ebafb7b76188b79b0bde174d599a0d340478ed83ec0a06d25b34aede972729964736f6c63430008130033

Deployed Bytecode

0x6080604052600436106103545760003560e01c8063a01efa34116101c6578063d3ec6f59116100f7578063ea25045411610095578063f57402961161006f578063f574029614610ae9578063f7b2f1bf14610b09578063fb128c83146103a0578063fe1c0c4b14610b1e57610363565b8063ea25045414610a89578063edb3a0a314610aa9578063ef8e19b814610ac957610363565b8063e3d47d5c116100d1578063e3d47d5c146109fc578063e544144314610a29578063e62a61a714610a49578063e7cb88f114610a6957610363565b8063d3ec6f591461097b578063e1a45218146109b0578063e1f3e17d146109c657610363565b8063b276be3511610164578063c4f0c1c21161013e578063c4f0c1c2146108d7578063cbd8aff214610925578063d03206a414610674578063d379ab5f1461095b57610363565b8063b276be3514610863578063b9ee495414610883578063bd3e8fc9146108a357610363565b8063ab986897116101a0578063ab986897146107c9578063ac1fc22c146107f6578063ae85945714610823578063b05786881461084357610363565b8063a01efa3414610774578063a0aefa2a14610794578063a167fd5f146107b457610363565b8063532cf596116102a057806370304e2f1161023e57806384b0196e1161021857806384b0196e146106ff57806387d4d28c146107275780639375da5a1461075457806393e8bcf9146103f657610363565b806370304e2f1461069d578063752d8e91146106ca578063843f92aa146106ea57610363565b80635e7876821161027a5780635e7876821461061457806361b26ea4146106345780636a7319cf146106545780636c5f55f71461067457610363565b8063532cf5961461056657806354fd4d501461059357806359b9370a146105a857610363565b80631b98e5101161030d57806344a8246f116102e757806344a8246f146104f35780634618d76214610513578063498120a0146105335780634a04a1c91461055357610363565b80631b98e5101461047f57806320606b701461049f5780633b79c44f146104d357610363565b806301ffc9a71461036b5780630597fa30146103a057806306fdde03146103d45780630a25dea9146103f657806310bc37791461041d5780631542b7fc1461045f57610363565b3661036357610361610b3e565b005b610361610b3e565b34801561037757600080fd5b5061038b610386366004614075565b610bd6565b60405190151581526020015b60405180910390f35b3480156103ac57600080fd5b506103bc67016345785d8a000081565b6040516001600160601b039091168152602001610397565b3480156103e057600080fd5b506103e9610c01565b60405161039791906140e5565b34801561040257600080fd5b5061040b600081565b60405160ff9091168152602001610397565b34801561042957600080fd5b506104517fbeeccead3be397d17079af6fbbbb014209a75062141befe787822f16816d9da581565b604051908152602001610397565b34801561046b57600080fd5b5061036161047a366004614129565b610c11565b34801561048b57600080fd5b5061040b61049a366004614176565b610c99565b3480156104ab57600080fd5b506104517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b3480156104df57600080fd5b506103616104ee3660046141ab565b610cd1565b3480156104ff57600080fd5b5061036161050e3660046141dc565b610d45565b34801561051f57600080fd5b5061036161052e366004614243565b610e3a565b34801561053f57600080fd5b5061036161054e3660046142b0565b610f18565b6104516105613660046142fb565b611015565b34801561057257600080fd5b50610586610581366004614176565b6114c0565b6040516103979190614423565b34801561059f57600080fd5b506103e9611657565b3480156105b457600080fd5b506105c86105c336600461444b565b611661565b6040516103979190600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b34801561062057600080fd5b5061058661062f3660046141ab565b611699565b34801561064057600080fd5b5061036161064f3660046144c5565b611758565b34801561066057600080fd5b5061038b61066f36600461452c565b6117d1565b34801561068057600080fd5b5061068a6103e881565b60405161ffff9091168152602001610397565b3480156106a957600080fd5b506106bd6106b83660046145b6565b6117f5565b604051610397919061462e565b3480156106d657600080fd5b506105866106e5366004614176565b6118d9565b3480156106f657600080fd5b5061040b600381565b34801561070b57600080fd5b50610714611995565b6040516103979796959493929190614674565b34801561073357600080fd5b506104516107423660046141ab565b60006020819052908152604090205481565b34801561076057600080fd5b5061036161076f3660046141ab565b6119bc565b34801561078057600080fd5b5061036161078f366004614129565b611a31565b3480156107a057600080fd5b506103616107af366004614865565b611ae4565b3480156107c057600080fd5b5061040b600281565b3480156107d557600080fd5b506107e96107e43660046141ab565b611c27565b60405161039791906149c2565b34801561080257600080fd5b506104516108113660046141ab565b60026020526000908152604090205481565b34801561082f57600080fd5b5061040b61083e366004614a05565b611d1d565b34801561084f57600080fd5b5061036161085e366004614243565b612182565b34801561086f57600080fd5b5061036161087e366004614243565b6122ad565b34801561088f57600080fd5b506105c861089e366004614ae5565b6122f5565b3480156108af57600080fd5b506104517fc03e2545e609fd0b7813d6074f00235b048ae7580a8e57070eed03901dd951ae81565b3480156108e357600080fd5b5061090d6108f23660046141ab565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610397565b34801561093157600080fd5b506103bc6109403660046141ab565b6003602052600090815260409020546001600160601b031681565b34801561096757600080fd5b50610361610976366004614b50565b612316565b34801561098757600080fd5b5061099b610996366004614b9b565b6123b5565b60405163ffffffff9091168152602001610397565b3480156109bc57600080fd5b5061068a61271081565b3480156109d257600080fd5b5061090d6109e13660046141ab565b6001602052600090815260409020546001600160a01b031681565b348015610a0857600080fd5b50610a1c610a17366004614bf3565b612404565b6040516103979190614c38565b348015610a3557600080fd5b50610361610a44366004614c47565b61257c565b348015610a5557600080fd5b50610451610a643660046142fb565b612631565b348015610a7557600080fd5b50610451610a84366004614c94565b612777565b348015610a9557600080fd5b50610361610aa4366004614cd0565b612922565b348015610ab557600080fd5b50610361610ac43660046141ab565b612a75565b348015610ad557600080fd5b50610451610ae4366004614c94565b612b1b565b348015610af557600080fd5b50610361610b043660046141ab565b612c2f565b348015610b1557600080fd5b5061040b600181565b348015610b2a57600080fd5b5061038b610b39366004614b9b565b612cb0565b36610b47573636f35b6000805b80368210610b595750610bb5565b600180830192600319810190351860001a9081610ba557600019855260028301933560021984011860001a607f808211610b94578282013888395b16949094019093019250610b4b9050565b8185538085019450505050610b4b565b50600038826000305af490503d6000803e80610bd0573d6000fd5b503d6000f35b60006301ffc9a760e01b6001600160e01b0319831690811463075dd78560e41b909114175b92915050565b6060610c0b612cc9565b50919050565b83610c1b81612d08565b6000610c28868686612e0b565b90506000610c3582612e27565b600281018590556040805160ff808a168252881660208201529081018690529091506001600160a01b038816907fe08051cfd6c9341327f7f5550f77e02e815f59c1ecba22a4ac006ddca62dec20906060015b60405180910390a250505050505050565b600060056000610cab85856000612e0b565b8152602081019190915260400160002060010154600160e01b900460ff16905092915050565b6000610cdb612e6a565b6001600160a01b0381811660008181526004602090815260409182902080546001600160a01b03191694881694851790559051928352929350917fb9aba67a9619eecb4b3e9fe6ded4a35c9bcdbfb1040f5122f91716de616a799391015b60405180910390a25050565b84610d4f81612d08565b6000610d5c878787612e0b565b90506000610d6982612e27565b905060ff8716158015610d82575063ffffffff84811614155b15610da05760405163d25a973560e01b815260040160405180910390fd5b610daa8585612ec8565b60018101805463ffffffff87811667ffffffffffffffff199092168217640100000000918816918202179092556040805160ff808c1682528a1660208201529081019190915260608101919091526001600160a01b038916907f41ad9ed088bad8a3ad3052c7360f6919b647b45d4b527e478d463edbb8f9a4359060800160405180910390a25050505050505050565b83610e4481612d08565b6000610e51868686612e0b565b90506000610e5e82612e27565b905060ff8616158015610e7d57506001810154600160e81b900460ff16155b15610e9b5760405163d25a973560e01b815260040160405180910390fd5b610ea484612ef5565b60018101805463ffffffff60601b1916600160601b63ffffffff8716908102919091179091556040805160ff808a16825288166020820152908101919091526001600160a01b038816907f5da54689220406b0ee18edb07d2007345f96968da27c7fd0f405f649d26040a890606001610c88565b83610f2281612d08565b6000610f2f868686612e0b565b90506000610f3c82612e27565b905060ff8616158015610f5e57506001810154600160e81b900460ff16600214155b15610f7c5760405163d25a973560e01b815260040160405180910390fd5b6001810154600219600160e81b90910460ff1601610fad5760405163d25a973560e01b815260040160405180910390fd5b80546001600160601b038516600160a01b81026001600160a01b039283161783556040805160ff8a811682528916602082015290810191909152908816907f3b082de0ef84f822f97496af03a3df5a8d5f0c271ea658b5b210819f1310494f90606001610c88565b60008061105561105061102b60208601866141ab565b61103b6040870160208801614cfc565b61104b6060880160408901614cfc565b612e0b565b612e27565b905061106081612f1f565b6001810154600160e81b900460ff166000198101611087576110828285612fb3565b6110c2565b60011960ff82160161109d576110828285613134565b60021960ff8216016110c25760405163a0042b1760e01b815260040160405180910390fd5b6110cd81838661329d565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081018290526101808101919091526111486101c086016101a087016141ab565b6001600160a01b031661116160808701606088016141ab565b6001600160a01b031614611186576111816101c086016101a087016141ab565b611189565b60005b6001600160a01b031660c082018190526111b29084906111ad6101c0890189614d17565b6134a3565b151560e082015260006111fb6111ce6040880160208901614cfc565b856111df60a08a0160808b01614d61565b6111f16101208b016101008c016144c5565b8660e001516134f7565b80519091503414611230578051604051630374cb4760e21b815234600482015260248101919091526044015b60405180910390fd5b606081015161014083015260a0810151610180830152608081015161016083018190521561129557610160820151600260006112746101c08a016101a08b016141ab565b6001600160a01b031681526020810191909152604001600020805490910190555b610180820151156112c75761018082015184546001600160a01b03166000908152602081905260409020805490910190555b60006112d660208801886141ab565b90506112e860a0880160808901614d61565b63ffffffff1683526101408301516001600160a01b0382169063eebab8ef9061131760408b0160208c01614cfc565b61132760808c0160608d016141ab565b61133760a08d0160808e01614d61565b6040516001600160e01b031960e087901b16815260ff90931660048401526001600160a01b03909116602483015263ffffffff16604482015260640160206040518083038185885af1158015611391573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906113b69190614d7c565b60208401526113cb60c0880160a089016141ab565b6001600160a01b031660408401526113e960e0880160c08901614d61565b63ffffffff16606084015261140661016088016101408901614d61565b63ffffffff1660a0840152815161010084015260408201516101208401526101e087013561143a6080890160608a016141ab565b6001600160a01b031661145060208a018a6141ab565b6001600160a01b03167f2a29f7402bd32f0e4bbe17d44be064f7f64d96ee174ed7cb27936d869bf9a88861148a60408c0160208d01614cfc565b61149a60608d0160408e01614cfc565b886040516114aa93929190614d95565b60405180910390a4505060200151949350505050565b6114c8613f5f565b606083811b60ff8481169190911760009081526006602090815260409182902082516101408101845281546001600160601b038082168352600160601b918290048116948301949094526001830154808516958301959095529384900483169581019590955260028101548083166080870152839004821660a08601526003015480821660c08601529182041660e0840152600160c01b810461ffff16610100840152600160d01b9004161515610120820181905261163b5760066000606086901b610100178152602080820192909252604090810160002081516101408101835281546001600160601b038082168352600160601b91829004811695830195909552600183015480861694830194909452928390048416606082015260028201548085166080830152839004841660a082015260039091015480841660c083015291820490921660e0830152600160c01b810461ffff16610100830152600160d01b900460ff16151561012082015290505b8061012001516116505761164d613f5f565b90505b9392505050565b6060610bfb612cc9565b611669613fb3565b6000611676888888612e0b565b905061168d8761168583612e27565b8787876134f7565b98975050505050505050565b6116a1613f5f565b50610100606091821b811760009081526006602090815260409182902082516101408101845281546001600160601b038082168352600160601b918290048116948301949094526001830154808516958301959095529384900483169581019590955260028101548083166080870152839004821660a08601526003015480821660c08601529182041660e084015261ffff600160c01b8204169183019190915260ff600160d01b90910416151561012082015290565b6000611762612e6a565b6001600160a01b03811660008181526003602090815260409182902080546bffffffffffffffffffffffff19166001600160601b038816908117909155915191825292935090917fed3d3f99e57c78ce76ac9a1704a72bb912e8f231cc25c6379fdf5354dbb6481b9101610d39565b6000806117df888888612e0b565b905061168d6117ed82612e27565b8686866134a3565b60606000611804878787612e0b565b60008181526008602052604090209091508367ffffffffffffffff81111561182e5761182e61470a565b604051908082528060200260200182016040528015611857578160200160208202803683370190505b50925060005b8085146118cd576118a386868381811061187957611879614e86565b905060200201602081019061188e9190614d61565b63ffffffff16836137d690919063ffffffff16565b8482815181106118b5576118b5614e86565b9115156020928302919091019091015260010161185d565b50505095945050505050565b6118e1613f5f565b5060ff908116606092831b1760009081526006602090815260409182902082516101408101845281546001600160601b038082168352600160601b918290048116948301949094526001830154808516958301959095529384900483169581019590955260028101548083166080870152839004821660a08601526003015480821660c08601529182041660e084015261ffff600160c01b820416610100840152600160d01b900416151561012082015290565b600f60f81b60608060008080836119aa612cc9565b97989097965046955030945091925090565b60006119c6612e6a565b90506119d1826137f8565b6001600160a01b0381811660008181526001602090815260409182902080546001600160a01b0319169487169485179055905192835290917f3a9b87574e9f01aaafa6d829c77645fe96010be0b3093259c7873f4a93de28e99101610d39565b83611a3b81612d08565b6000611a48868686612e0b565b90506000611a5582612e27565b600180820154919250600160e81b90910460ff1614611a875760405163d25a973560e01b815260040160405180910390fd5b611a908461381f565b600381018490556040805160ff8089168252871660208201529081018590526001600160a01b038816907f0b0a6fe894fe7695ac067d44d6e0de766337e9c3b5f0ee0a61be727383aac5a790606001610c88565b6000611aee612e6a565b9050611af98261383d565b8160066000606084901b610100178152602080820192909252604090810160002083518154938501516001600160601b039182166001600160c01b031995861617600160601b9183168202178355858401516001840180546060890151928516908816179184168302919091179055608086015160028401805460a089015192851690881617918416830291909117905560c08601516003909301805460e088015161010089015161012090990151958516919097161795909216029390931762ffffff60c01b1916600160c01b61ffff9095169490940260ff60d01b191693909317600160d01b93151593909302929092179055516001600160a01b038216907fe6bb0d56f1c8a28e8a4fa4c725b521b129a2d80fa461d8365016d98c4775ab0f90610d39908590614423565b606081811b6000908152600560205260409020600181015461ffff600160d01b8204811691600160c01b9004168167ffffffffffffffff811115611c6d57611c6d61470a565b604051908082528060200260200182016040528015611ca657816020015b611c93613fe9565b815260200190600190039081611c8b5790505b5093505b8115611d155761ffff8116606086901b176000908152600560205260409020611cdb8660ff600885901c1684612404565b85846001900394508481518110611cf457611cf4614e86565b602090810291909101015260010154600160b01b900461ffff169050611caa565b505050919050565b6000611d2c8260000151612d08565b611d398260c00151613979565b61014082015160ff8116611d54576000610160840152611dd9565b60001960ff821601611d7357611d6e83610160015161381f565b611dd9565b60011960ff821601611d9657600061016084015263ffffffff6080840152611dd9565b60021960ff821601611dc0576000610160840181905263ffffffff60808501526020840152611dd9565b60405163a0042b1760e01b815260040160405180910390fd5b61010083015160ff16611e1d5763ffffffff60608401819052608084015260ff8116600214611e0a57600060208401525b60ff8116611e1d5763ffffffff60a08401525b611e2f83604001518460600151612ec8565b611e3c83608001516139a0565b611e498360a00151612ef5565b600060056000611e6486600001518761010001516000612e0b565b815260208082019290925260409081016000908120875160601b8252600590935220600180830154600160e01b900460ff1695509192509084016101008110611eaf57611eaf6139c7565b6001808401805460ff909316600160e01b0260ff60e01b19909316929092179091558181015461ffff600160d01b9091041601620100008110611ef457611ef46139c7565b60018201805461ffff60d01b1916600160d01b61ffff8416021790558551610100870151600091611f259188612e0b565b905060006005600083815260200190815260200160002090508761012001518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555087602001518160000160146101000a8154816001600160601b0302191690836001600160601b0316021790555087604001518160010160006101000a81548163ffffffff021916908363ffffffff16021790555087606001518160010160046101000a81548163ffffffff021916908363ffffffff16021790555087608001518160010160086101000a81548163ffffffff021916908363ffffffff1602179055508760a0015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055508760c001518160010160146101000a81548161ffff021916908361ffff16021790555087610140015181600101601d6101000a81548160ff021916908360ff160217905550600181600101601e6101000a81548160ff021916908360ff1602179055508360010160189054906101000a900461ffff168160010160166101000a81548161ffff021916908361ffff1602179055508660ff16600889610100015160ff16901b178460010160186101000a81548161ffff021916908361ffff1602179055506000801b8860e00151146121125760e088015160028201555b610160880151156121295761016088015160038201555b87600001516001600160a01b03167f71e782e300c458b9de1211d63df057e6f372a85a3b394606ac3335907b14f097896101000151898b60405161216f93929190614e9c565b60405180910390a2505050505050919050565b8361218c81612d08565b6000612199868686612e0b565b905060006121a682612e27565b905060ff86166121c95760405163d25a973560e01b815260040160405180910390fd5b6001810154600119600160e81b90910460ff16016121fa5760405163d25a973560e01b815260040160405180910390fd5b6001810154600219600160e81b90910460ff160161222b5760405163d25a973560e01b815260040160405180910390fd5b612234846139a0565b6001810180546bffffffff00000000000000001916600160401b63ffffffff8716908102919091179091556040805160ff808a16825288166020820152908101919091526001600160a01b038816907f674233c20daf715ad9e94f9e5818adc53482b77e9556564e5fe3766678246e8e90606001610c88565b60006122ba858585612e0b565b6000818152600560205260409020600101549091506122ee908690869086908690640100000000900463ffffffff16610d45565b5050505050565b6122fd613fb3565b61230c86868686600087611661565b9695505050505050565b8361232081612d08565b600061232d868686612e0b565b9050600061233a82612e27565b905061234584613979565b60018101805461ffff60a01b1916600160a01b61ffff8716908102919091179091556040805160ff808a16825288166020820152908101919091526001600160a01b038816907fcdff4ec2999e249a9a848accff5e46b43263f82c4076334cd70300e07326472d90606001610c88565b6000806123c3868686612e0b565b6001600160a01b0384166000908152600760209081526040808320600385901c845290915290205490915060e0600583901b161c5b9150505b949350505050565b61240c613fe9565b6000612419858585612e0b565b9050600061242682612e27565b6001600160a01b03808816855260ff8088166020870181905290871660408701528254909116606086015290915015801561247057506001810154600160e81b900460ff16600214155b61248b578054600160a01b90046001600160601b03166124af565b80546001600160a01b03166000908152600360205260409020546001600160601b03165b6001600160601b03166080840152600181015463ffffffff80821660a08601526401000000008204811660c0860152600160401b8204811660e0860152600160601b82048116610100860152600160801b820416610120850152600160a01b810461ffff16610140850152600160e81b810460ff166101608501526002600160f01b909104811615156101808501528101546101c084015260038101546101e0840152546001600160a01b0390811660009081526004602052604090205416610200830152509392505050565b8361258681612d08565b6000612593868686612e0b565b905060006125a082612e27565b60018101549091506125c99060ff600160f01b9091041660028660ff8383161615901518021890565b60018201805460ff60f01b1916600160f01b60ff938416021790556040805188831681529187166020830152851515908201526001600160a01b038816907f81bd379475659273b35365d353d46c7de87aa468a01efc54544fcee90ae0d3b690606001610c88565b6000610bfb7fc03e2545e609fd0b7813d6074f00235b048ae7580a8e57070eed03901dd951ae61266460208501856141ab565b6126746040860160208701614cfc565b6126846060870160408801614cfc565b61269460808801606089016141ab565b6126a661014089016101208a01614d61565b6126b86101608a016101408b01614d61565b6126ca6101208b016101008c016144c5565b6126dc6101808c016101608d01614d61565b6126ee6101c08d016101a08e016141ab565b60408051602081019b909b526001600160a01b03998a16908b015260ff97881660608b015296909516608089015292861660a088015263ffffffff91821660c0880152811660e08701526001600160601b039091166101008601521661012084015216610140820152610160015b604051602081830303815290604052805190602001206139f8565b60008061278d61105061102b60208601866141ab565b905061279881612f1f565b6001810154600160e81b900460ff166003146127c75760405163a0042b1760e01b815260040160405180910390fd5b6127d18184613b10565b6127db8184613bc1565b60006127ea60208501856141ab565b90506001600160a01b03811663010fe62c61280b6040870160208801614cfc565b6128186060880188614d17565b61282860a08a0160808b01614d61565b6040518563ffffffff1660e01b81526004016128479493929190614fe1565b6020604051808303816000875af1158015612866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288a9190614d7c565b925061289960208501856141ab565b6001600160a01b03167f0b4410e982ad454e02d2fb1663c16f53389d5126913f7223d14d8a8b311c33246128d36040870160208801614cfc565b6128e36060880160408901614cfc565b6128f06060890189614d17565b61290060a08b0160808c01614d61565b8960405161291396959493929190615015565b60405180910390a25050919050565b600061292c612e6a565b90506129378261383d565b8160066000606084901b60ff8716178152602080820192909252604090810160002083518154938501516001600160601b039182166001600160c01b031995861617600160601b9183168202178355858401516001840180546060890151928516908816179184168302919091179055608086015160028401805460a089015192851690881617918416830291909117905560c08601516003909301805460e088015161010089015161012090990151958516919097161795909216029390931762ffffff60c01b1916600160c01b61ffff9095169490940260ff60d01b191693909317600160d01b93151593909302929092179055516001600160a01b038216907f7fcaf05e0d01e61bfcf3c7d5035259d2bbdb13b68a9c0f183b52d074a3f1110490612a689086908690615056565b60405180910390a2505050565b6001600160a01b0380821660009081526001602052604090205416612a99816137f8565b6001600160a01b0382166000908152602081905260409020548015612b16576001600160a01b038316600090815260208190526040812055612adb8282613d26565b826001600160a01b03167ffc7ad544ff6a06d6499925723d25b6fe70457a42939995b1d3d6f560fe33633382604051612a6891815260200190565b505050565b6000610bfb7fbeeccead3be397d17079af6fbbbb014209a75062141befe787822f16816d9da5612b4e60208501856141ab565b612b5e6040860160208701614cfc565b612b6e6060870160408801614cfc565b612b7b6060880188614d17565b604051602001612b8c92919061506e565b60408051601f198184030181529190528051602090910120612bb460a0890160808a01614d61565b612bc460c08a0160a08b01614d61565b612bd460e08b0160c08c01614d61565b6040805160208101999099526001600160a01b039097169688019690965260ff948516606088015293909216608086015260a085015263ffffffff90811660c085015290811660e0840152166101008201526101200161275c565b6001600160a01b0381166000908152600260205260409020548015612cac576001600160a01b038216600090815260026020526040812055612c718282613d26565b816001600160a01b03167f0a1adaaf9d9caba9cf65528900e946b718d511ebd66ae81d5eb71e7fd0122c4a82604051610d3991815260200190565b5050565b6000612cc08585858536866117d1565b95945050505050565b604080518082018252600b81526a29bab832b926b4b73a32b960a91b60208083019190915282518084019093526003835262315f3160e81b9083015291565b6000612d12612e6a565b9050816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d7691906150b0565b6001600160a01b0316816001600160a01b031614612cac5760405163145398bf60e21b81526001600160a01b0382811660048301526001602483015283169063514e62fc90604401602060405180830381865afa158015612ddb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dff91906150cd565b612cac57612cac613d69565b60008360601b60005282601e5381601f53505060005192915050565b60008181526005602052604081206001808201549192600160f01b909204169003612e655760405163947dbacd60e01b815260040160405180910390fd5b919050565b6000336000526e2fd5aeb385d324b580fca7c83823a0803303612e9857602060008038845afa612e98573838fd5b506dd9ecebf3c23529de49815dac1c4c803303612ec057602060008038845afa612ec0573838fd5b505060005190565b8063ffffffff168263ffffffff161115612cac5760405163536a71af60e01b815260040160405180910390fd5b8063ffffffff16600003612f1c57604051630ccae60160e31b815260040160405180910390fd5b50565b600181015442640100000000820463ffffffff90811682119216111715612f7e57600181015460405163296f4f6960e01b815242600482015263ffffffff80831660248301526401000000009092049091166044820152606401611227565b612f958160010154600160f01b9004600216151590565b15612f1c57604051636be9245d60e11b815260040160405180910390fd5b6000612fc560e0830160c08401614d61565b90506000612fd960c0840160a085016141ab565b90506001600160a01b0381166130025760405163582f497d60e11b815260040160405180910390fd5b63fffffffe1963ffffffff83160161308d57613041846003015461302b836000526014600c2090565b61303860e0870187614d17565b90929091613d77565b15801561306a5750613068846003015461302b8363ffffffff6004526000526018600c2090565b155b156130885760405163582f497d60e11b815260040160405180910390fd5b6130c5565b6130a8846003015461302b83856004526000526018600c2090565b6130c55760405163582f497d60e11b815260040160405180910390fd5b60006130cf612e6a565b90506131096001600160a01b038381169083168114906130f560808801606089016141ab565b6001600160a01b0316149015159015151790565b6122ee576131178183613db1565b6122ee5760405163fe736e0160e01b815260040160405180910390fd5b61314661014082016101208301614d61565b63ffffffff1661315c60a0830160808401614d61565b63ffffffff161115613181576040516352ad28c360e11b815260040160405180910390fd5b81546001600160a01b03908116600090815260046020526040902054166131be816131ab84612631565b6131b96101808601866150ea565b613df2565b6131db57604051638baa579f60e01b815260040160405180910390fd5b6131ed61018083016101608401614d61565b63ffffffff1642111561321357604051630819bdcd60e01b815260040160405180910390fd5b600061324561322560208501856141ab565b6132356040860160208701614cfc565b61104b6060870160408801614cfc565b905061327a61325c61016085016101408601614d61565b60008381526008602052604090209063ffffffff90811690613eeb16565b6132975760405163900bb2c960e01b815260040160405180910390fd5b50505050565b60006132af60a0830160808401614d61565b600184015463ffffffff918216600160801b82048316019250600160601b9004168111156132f057604051637f70f90b60e01b815260040160405180910390fd5b60018301805463ffffffff60801b1916600160801b63ffffffff841602179055600061332261322560208501856141ab565b905060001960ff8616016133fb57600060078161334560c0870160a088016141ab565b6001600160a01b031681526020810191909152604001600020905061337060a0850160808601614d61565b63ffffffff1661338983836139d590919063ffffffff16565b600187015463ffffffff9182169290920194506133cc91600160401b90041684116133ba60e0870160c08801614d61565b63ffffffff1685119015159015151790565b156133ea57604051631b75136560e01b815260040160405180910390fd5b6133f5818385613f17565b506122ee565b600060078161341060808701606088016141ab565b6001600160a01b031681526020810191909152604001600020905061343b60a0850160808601614d61565b63ffffffff1661345483836139d590919063ffffffff16565b600187015463ffffffff918216929092019450600160401b9091041683111561349057604051631b75136560e01b815260040160405180910390fd5b61349b818385613f17565b505050505050565b6002840154600090806134c35750506001600160a01b03831615156123fc565b6123f86001600160a01b03861615156134ee836134e5896000526014600c2090565b88918891613d77565b15159015151690565b6134ff613fb3565b8454600090613517906001600160a01b0316886114c0565b6001870154909150600119600160e81b90910460ff160161357c5785546001600160601b03600160a01b909104811690851610156135685760405163dcdc2f1560e01b815260040160405180910390fd5b6001600160601b03841660408301526135ca565b60ff87166135b25785546001600160a01b031660009081526003602052604090819020546001600160601b0316908301526135ca565b8554600160a01b90046001600160601b031660408301525b604082015163ffffffff8616026020830181905260608301526001860154600160a01b900461ffff16158015906135fe5750825b156136335760208201516001870154600091612710600160a01b90920461ffff16020460608401805182900390526080840152505b61010081015161ffff161561366d57602082015161010082015160009161271061ffff9092160204606084018051829003905260a0840152505b80606001516001600160601b031682604001511161371457805160608301805163ffffffff88166001600160601b039384168102909101909152604083015160a0850180519190931690910201905282156136eb5760208101516080830180516001600160601b0390921663ffffffff8816029190910190526137a3565b602081015160a0830180516001600160601b0390921663ffffffff8816029190910190526137a3565b608081015160608301805163ffffffff88166001600160601b03938416810290910190915260c083015160a08501805191909316909102019052821561377d5760a08101516080830180516001600160601b0390921663ffffffff8816029190910190526137a3565b8463ffffffff168160a001516001600160601b0316028260a00181815101915081815250505b60e0015160a0820180516001600160601b0390921690910190819052608082015160608301510101815295945050505050565b600881901c6000908152602092909252604090912054600160ff9092161c1690565b6001600160a01b038116612f1c576040516362ccef3360e01b815260040160405180910390fd5b80612f1c5760405163caa2867f60e01b815260040160405180910390fd5b61395b61388067016345785d8a00006001600160601b03168360e001516001600160601b0316116103e861ffff1684610100015161ffff16119015159015151790565b6138eb67016345785d8a00006001600160601b031684600001516001600160601b03161167016345785d8a00006001600160601b031685602001516001600160601b03161167016345785d8a00006001600160601b031686604001516001600160601b031611613f4b565b61395667016345785d8a00006001600160601b031685608001516001600160601b03161167016345785d8a00006001600160601b03168660a001516001600160601b03161167016345785d8a00006001600160601b03168760c001516001600160601b031611613f4b565b613f4b565b15612f1c5760405163b17424c360e01b815260040160405180910390fd5b6103e861ffff82161115612f1c57604051631a52ce6f60e01b815260040160405180910390fd5b8063ffffffff16600003612f1c5760405163a017714560e01b815260040160405180910390fd5b6335278d126000526004601cfd5b600381901c600090815260209290925260409091205460059190911b60e0161c90565b7f83e061be5ae459aaeaed173bd089423f8f50b403f581ed0dc7d12cbe0e3d06757f000000000000000000000000000000000001a36777f9930aaeff623771b13e7030147f0000000000000000000000000000000000000000000000000000000000000001461416613aeb5750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527fa6cb2587267be99efde5eb570922efe1ef200501c220db4e8df4187255e6c05060208201527f7bc1c9889e0858302721aa6da0318e4e6eb7eab947465105c4873f8c5c6ee34c9181019190915246606082015230608082015260a090205b67190100000000000060005280601a5281603a52604260182090506000603a52919050565b81546001600160a01b0390811660009081526004602052604090205416613b4781613b3a84612b1b565b6131b960e08601866150ea565b613b6457604051638baa579f60e01b815260040160405180910390fd5b613b7460e0830160c08401614d61565b63ffffffff16421115613b9a57604051630819bdcd60e01b815260040160405180910390fd5b6000613bac61322560208501856141ab565b905061327a61325c60c0850160a08601614d61565b6000613bf3613bd360208401846141ab565b613be36040850160208601614cfc565b61104b6060860160408701614cfc565b90506000613c046060840184614d17565b915060009050613c1a60a0850160808601614d61565b600186015463ffffffff9182168402600160801b82048316019250600160601b900416811115613c5d57604051637f70f90b60e01b815260040160405180910390fd5b60018501805463ffffffff60801b1916600160801b63ffffffff84160217905560005b82811461349b576000600781613c996060890189614d17565b85818110613ca957613ca9614e86565b9050602002016020810190613cbe91906141ab565b6001600160a01b0316815260208101919091526040016000209050613d1d85613ced60a0890160808a01614d61565b63ffffffff16613d0688856139d590919063ffffffff16565b63ffffffff160183613f179092919063ffffffff16565b50600101613c80565b80471015613d3c5763b12d13eb6000526004601cfd5b6000386000388486620186a0f1612cac57816000526073600b5360ff6020536016600b82f0612cac573838fd5b6382b429006000526004601cfd5b60008315613da9578360051b8501855b803580851160051b94855260209485185260406000209301818110613d875750505b501492915050565b600060405163e839bd536000528360205282604052602060006064601c6c447e69651d841bd8d104bed4935afa600160005114169150806040525092915050565b6001600160a01b0390931692600084156123fc576040518460005260408303613e5d5760208481013560ff81901c601b01825285356040526001600160ff1b0316606052600160806000825afa805187183d1517613e5b575060006060526040525060016123fc565b505b60418303613ea057604084013560001a602052604084604037602060016080600060015afa805187183d1517613e9e575060006060526040525060016123fc565b505b600060605280604052631626ba7e60e01b80825285600483015260248201604081528460448401528486606485013760208160648701858b5afa905190911416915050949350505050565b602091909152600881901c6000908152604090208054600160ff90931683811b909118918290551c1690565b826020528160031c60005260406000206007831660051b815463ffffffff8482841c188116831b8218845550505050505050565b6000831515831515831515171515176123fc565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e0810182905261020081019190915290565b60006020828403121561408757600080fd5b81356001600160e01b03198116811461165057600080fd5b6000815180845260005b818110156140c5576020818501810151868301820152016140a9565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000611650602083018461409f565b6001600160a01b0381168114612f1c57600080fd5b8035612e65816140f8565b803560ff81168114612e6557600080fd5b6000806000806080858703121561413f57600080fd5b843561414a816140f8565b935061415860208601614118565b925061416660408601614118565b9396929550929360600135925050565b6000806040838503121561418957600080fd5b8235614194816140f8565b91506141a260208401614118565b90509250929050565b6000602082840312156141bd57600080fd5b8135611650816140f8565b803563ffffffff81168114612e6557600080fd5b600080600080600060a086880312156141f457600080fd5b85356141ff816140f8565b945061420d60208701614118565b935061421b60408701614118565b9250614229606087016141c8565b9150614237608087016141c8565b90509295509295909350565b6000806000806080858703121561425957600080fd5b8435614264816140f8565b935061427260208601614118565b925061428060408601614118565b915061428e606086016141c8565b905092959194509250565b80356001600160601b0381168114612e6557600080fd5b600080600080608085870312156142c657600080fd5b84356142d1816140f8565b93506142df60208601614118565b92506142ed60408601614118565b915061428e60608601614299565b60006020828403121561430d57600080fd5b813567ffffffffffffffff81111561432457600080fd5b8201610200818503121561165057600080fd5b80516001600160601b03168252602081015161435e60208401826001600160601b03169052565b50604081015161437960408401826001600160601b03169052565b50606081015161439460608401826001600160601b03169052565b5060808101516143af60808401826001600160601b03169052565b5060a08101516143ca60a08401826001600160601b03169052565b5060c08101516143e560c08401826001600160601b03169052565b5060e081015161440060e08401826001600160601b03169052565b506101008181015161ffff16908301526101208082015180151582850152613297565b6101408101610bfb8284614337565b8015158114612f1c57600080fd5b8035612e6581614432565b60008060008060008060c0878903121561446457600080fd5b863561446f816140f8565b955061447d60208801614118565b945061448b60408801614118565b9350614499606088016141c8565b92506144a760808801614299565b915060a08701356144b781614432565b809150509295509295509295565b6000602082840312156144d757600080fd5b61165082614299565b60008083601f8401126144f257600080fd5b50813567ffffffffffffffff81111561450a57600080fd5b6020830191508360208260051b850101111561452557600080fd5b9250929050565b60008060008060008060a0878903121561454557600080fd5b8635614550816140f8565b955061455e60208801614118565b945061456c60408801614118565b9350606087013561457c816140f8565b9250608087013567ffffffffffffffff81111561459857600080fd5b6145a489828a016144e0565b979a9699509497509295939492505050565b6000806000806000608086880312156145ce57600080fd5b85356145d9816140f8565b94506145e760208701614118565b93506145f560408701614118565b9250606086013567ffffffffffffffff81111561461157600080fd5b61461d888289016144e0565b969995985093965092949392505050565b6020808252825182820181905260009190848201906040850190845b8181101561466857835115158352928401929184019160010161464a565b50909695505050505050565b60ff60f81b881681526000602060e08184015261469460e084018a61409f565b83810360408501526146a6818a61409f565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156146f8578351835292840192918401916001016146dc565b50909c9b505050505050505050505050565b634e487b7160e01b600052604160045260246000fd5b604051610140810167ffffffffffffffff8111828210171561475257634e487b7160e01b600052604160045260246000fd5b60405290565b604051610180810167ffffffffffffffff8111828210171561475257634e487b7160e01b600052604160045260246000fd5b803561ffff81168114612e6557600080fd5b600061014082840312156147af57600080fd5b6147b7614720565b90506147c282614299565b81526147d060208301614299565b60208201526147e160408301614299565b60408201526147f260608301614299565b606082015261480360808301614299565b608082015261481460a08301614299565b60a082015261482560c08301614299565b60c082015261483660e08301614299565b60e082015261010061484981840161478a565b9082015261012061485b838201614440565b9082015292915050565b6000610140828403121561487857600080fd5b611650838361479c565b80516001600160a01b0316825260208101516148a3602084018260ff169052565b5060408101516148b8604084018260ff169052565b5060608101516148d360608401826001600160a01b03169052565b5060808101516148ee60808401826001600160601b03169052565b5060a081015161490660a084018263ffffffff169052565b5060c081015161491e60c084018263ffffffff169052565b5060e081015161493660e084018263ffffffff169052565b506101008181015163ffffffff9081169184019190915261012080830151909116908301526101408082015161ffff16908301526101608082015160ff1690830152610180808201511515908301526101a0808201511515908301526101c080820151908301526101e08082015190830152610200808201516001600160a01b03811682850152613297565b6020808252825182820181905260009190848201906040850190845b81811015614668576149f1838551614882565b9284019261022092909201916001016149de565b60006101808284031215614a1857600080fd5b614a20614758565b614a298361410d565b8152614a3760208401614299565b6020820152614a48604084016141c8565b6040820152614a59606084016141c8565b6060820152614a6a608084016141c8565b6080820152614a7b60a084016141c8565b60a0820152614a8c60c0840161478a565b60c082015260e083013560e0820152610100614aa9818501614118565b90820152610120614abb84820161410d565b90820152610140614acd848201614118565b90820152610160928301359281019290925250919050565b600080600080600060a08688031215614afd57600080fd5b8535614b08816140f8565b9450614b1660208701614118565b9350614b2460408701614118565b9250614b32606087016141c8565b91506080860135614b4281614432565b809150509295509295909350565b60008060008060808587031215614b6657600080fd5b8435614b71816140f8565b9350614b7f60208601614118565b9250614b8d60408601614118565b915061428e6060860161478a565b60008060008060808587031215614bb157600080fd5b8435614bbc816140f8565b9350614bca60208601614118565b9250614bd860408601614118565b91506060850135614be8816140f8565b939692955090935050565b600080600060608486031215614c0857600080fd5b8335614c13816140f8565b9250614c2160208501614118565b9150614c2f60408501614118565b90509250925092565b6102208101610bfb8284614882565b60008060008060808587031215614c5d57600080fd5b8435614c68816140f8565b9350614c7660208601614118565b9250614c8460408601614118565b91506060850135614be881614432565b600060208284031215614ca657600080fd5b813567ffffffffffffffff811115614cbd57600080fd5b8201610100818503121561165057600080fd5b6000806101608385031215614ce457600080fd5b614ced83614118565b91506141a2846020850161479c565b600060208284031215614d0e57600080fd5b61165082614118565b6000808335601e19843603018112614d2e57600080fd5b83018035915067ffffffffffffffff821115614d4957600080fd5b6020019150600581901b360382131561452557600080fd5b600060208284031215614d7357600080fd5b611650826141c8565b600060208284031215614d8e57600080fd5b5051919050565b60ff848116825283166020820152815163ffffffff1660408201526101e081016020830151606083015260408301516001600160a01b038116608084015250606083015163ffffffff811660a084015250608083015163ffffffff811660c08401525060a083015163ffffffff811660e08401525060c0830151610100614e26818501836001600160a01b03169052565b60e08501519150610120614e3d8186018415159052565b908501516101408581019190915290850151610160808601919091529085015161018080860191909152908501516101a0850152909301516101c0909201919091529392505050565b634e487b7160e01b600052603260045260246000fd5b60ff84811682528316602082015281516001600160a01b031660408201526101c0810160208301516001600160601b038116606084015250604083015163ffffffff8116608084015250606083015163ffffffff811660a084015250608083015163ffffffff811660c08401525060a083015163ffffffff811660e08401525060c0830151610100614f338185018361ffff169052565b60e08501516101208581019190915290850151915061014090614f5a8286018460ff169052565b8501519150610160614f76858201846001600160a01b03169052565b9085015160ff16610180850152909301516101a0909201919091529392505050565b8183526000602080850194508260005b85811015614fd6578135614fbb816140f8565b6001600160a01b031687529582019590820190600101614fa8565b509495945050505050565b60ff85168152606060208201526000614ffe606083018587614f98565b905063ffffffff8316604083015295945050505050565b60ff8716815260ff8616602082015260a06040820152600061503b60a083018688614f98565b63ffffffff9490941660608301525060800152949350505050565b60ff8316815261016081016116506020830184614337565b60008184825b858110156150a5578135615087816140f8565b6001600160a01b031683526020928301929190910190600101615074565b509095945050505050565b6000602082840312156150c257600080fd5b8151611650816140f8565b6000602082840312156150df57600080fd5b815161165081614432565b6000808335601e1984360301811261510157600080fd5b83018035915067ffffffffffffffff82111561511c57600080fd5b60200191503681900382131561452557600080fdfea26469706673582212207ebafb7b76188b79b0bde174d599a0d340478ed83ec0a06d25b34aede972729964736f6c63430008130033

Deployed Bytecode Sourcemap

1041:46050:3:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22458:19;:17;:19::i;:::-;1041:46050;;22335:19;:17;:19::i;29725:224::-;;;;;;;;;;-1:-1:-1;29725:224:3;;;;;:::i;:::-;;:::i;:::-;;;566:14:21;;559:22;541:41;;529:2;514:18;29725:224:3;;;;;;;;5170:54;;;;;;;;;;;;5215:9;5170:54;;;;;-1:-1:-1;;;;;870:39:21;;;852:58;;840:2;825:18;5170:54:3;708:208:21;29387:112:3;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;4325:33::-;;;;;;;;;;;;4357:1;4325:33;;;;;1826:4:21;1814:17;;;1796:36;;1784:2;1769:18;4325:33:3;1654:184:21;3711:413:3;;;;;;;;;;;;3798:326;3711:413;;;;;1989:25:21;;;1977:2;1962:18;3711:413:3;1843:177:21;17054:407:3;;;;;;;;;;-1:-1:-1;17054:407:3;;;;;:::i;:::-;;:::i;24702:164::-;;;;;;;;;;-1:-1:-1;24702:164:3;;;;;:::i;:::-;;:::i;4201:58::-;;;;;;;;;;-1:-1:-1;4201:58:3;1250:66:13;4201:58:3;;21986:204;;;;;;;;;;-1:-1:-1;21986:204:3;;;;;:::i;:::-;;:::i;15510:656::-;;;;;;;;;;-1:-1:-1;15510:656:3;;;;;:::i;:::-;;:::i;18387:569::-;;;;;;;;;;-1:-1:-1;18387:569:3;;;;;:::i;:::-;;:::i;14306:676::-;;;;;;;;;;-1:-1:-1;14306:676:3;;;;;:::i;:::-;;:::i;10813:2439::-;;;;;;:::i;:::-;;:::i;27112:387::-;;;;;;;;;;-1:-1:-1;27112:387:3;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;29555:121::-;;;;;;;;;;;;;:::i;24214:432::-;;;;;;;;;;-1:-1:-1;24214:432:3;;;;;:::i;:::-;;:::i;:::-;;;;;;8520:4:21;8562:3;8551:9;8547:19;8539:27;;8599:6;8593:13;8582:9;8575:32;8663:4;8655:6;8651:17;8645:24;8638:4;8627:9;8623:20;8616:54;8726:4;8718:6;8714:17;8708:24;8701:4;8690:9;8686:20;8679:54;8789:4;8781:6;8777:17;8771:24;8764:4;8753:9;8749:20;8742:54;8852:4;8844:6;8840:17;8834:24;8827:4;8816:9;8812:20;8805:54;8915:4;8907:6;8903:17;8897:24;8890:4;8879:9;8875:20;8868:54;8358:570;;;;;26862:194:3;;;;;;;;;;-1:-1:-1;26862:194:3;;;;;:::i;:::-;;:::i;21751:179::-;;;;;;;;;;-1:-1:-1;21751:179:3;;;;;:::i;:::-;;:::i;25264:377::-;;;;;;;;;;-1:-1:-1;25264:377:3;;;;;:::i;:::-;;:::i;4880:51::-;;;;;;;;;;;;4927:4;4880:51;;;;;10528:6:21;10516:19;;;10498:38;;10486:2;10471:18;4880:51:3;10354:188:21;26028:544:3;;;;;;;;;;-1:-1:-1;26028:544:3;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;26628:178::-;;;;;;;;;;-1:-1:-1;26628:178:3;;;;;:::i;:::-;;:::i;4633:42::-;;;;;;;;;;;;4674:1;4633:42;;6989:596:13;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;6275:54:3:-;;;;;;;;;;-1:-1:-1;6275:54:3;;;;;:::i;:::-;;;;;;;;;;;;;;;20703:273;;;;;;;;;;-1:-1:-1;20703:273:3;;;;;:::i;:::-;;:::i;19012:502::-;;;;;;;;;;-1:-1:-1;19012:502:3;;;;;:::i;:::-;;:::i;21383:312::-;;;;;;;;;;-1:-1:-1;21383:312:3;;;;;:::i;:::-;;:::i;4524:42::-;;;;;;;;;;;;4565:1;4524:42;;27555:751;;;;;;;;;;-1:-1:-1;27555:751:3;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;6538:55::-;;;;;;;;;;-1:-1:-1;6538:55:3;;;;;:::i;:::-;;;;;;;;;;;;;;7658:3099;;;;;;;;;;-1:-1:-1;7658:3099:3;;;;;:::i;:::-;;:::i;17517:814::-;;;;;;;;;;-1:-1:-1;17517:814:3;;;;;:::i;:::-;;:::i;16222:296::-;;;;;;;;;;-1:-1:-1;16222:296:3;;;;;:::i;:::-;;:::i;23833:325::-;;;;;;;;;;-1:-1:-1;23833:325:3;;;;;:::i;:::-;;:::i;3149:468::-;;;;;;;;;;;;3227:390;3149:468;;6785:49;;;;;;;;;;-1:-1:-1;6785:49:3;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;6785:49:3;;;;;;-1:-1:-1;;;;;20158:32:21;;;20140:51;;20128:2;20113:18;6785:49:3;19994:203:21;6664:41:3;;;;;;;;;;-1:-1:-1;6664:41:3;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;6664:41:3;;;16574:424;;;;;;;;;;-1:-1:-1;16574:424:3;;;;;:::i;:::-;;:::i;24922:286::-;;;;;;;;;;-1:-1:-1;24922:286:3;;;;;:::i;:::-;;:::i;:::-;;;21375:10:21;21363:23;;;21345:42;;21333:2;21318:18;24922:286:3;21201:192:21;4751:63:3;;;;;;;;;;;;1495:5:2;4751:63:3;;6407:53;;;;;;;;;;-1:-1:-1;6407:53:3;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;6407:53:3;;;28362:969;;;;;;;;;;-1:-1:-1;28362:969:3;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;15038:416::-;;;;;;;;;;-1:-1:-1;15038:416:3;;;;;:::i;:::-;;:::i;22733:496::-;;;;;;;;;;-1:-1:-1;22733:496:3;;;;;:::i;:::-;;:::i;13308:775::-;;;;;;;;;;-1:-1:-1;13308:775:3;;;;;:::i;:::-;;:::i;21032:295::-;;;;;;;;;;-1:-1:-1;21032:295:3;;;;;:::i;:::-;;:::i;20073:438::-;;;;;;;;;;-1:-1:-1;20073:438:3;;;;;:::i;:::-;;:::i;23285:492::-;;;;;;;;;;-1:-1:-1;23285:492:3;;;;;:::i;:::-;;:::i;19677:340::-;;;;;;;;;;-1:-1:-1;19677:340:3;;;;;:::i;:::-;;:::i;4420:39::-;;;;;;;;;;;;4458:1;4420:39;;25697:275;;;;;;;;;;-1:-1:-1;25697:275:3;;;;;:::i;:::-;;:::i;11272:1126:17:-;11346:14;11336:68;;11346:14;;11364:38;11336:68;11426:1;;11503:628;11522:21;11346:14;11525:1;11522:21;;;-1:-1:-1;;;11522:21:17;11643:1;11636:9;;;;-1:-1:-1;;11586:9:17;;11597:15;;11582:31;11426:1;11574:40;;;11662:394;;-1:-1:-1;;11856:17:17;;11718:9;11772;;;11729:15;-1:-1:-1;;11718:9:17;;11714:31;11426:1;11706:40;11910:4;11904:11;;;11894:61;;11643:1;11947;11943:9;11931:10;11928:1;11919:34;11894:61;11992:12;11981:28;;;;;;;;-1:-1:-1;11503:628:17;;-1:-1:-1;11503:628:17;11662:394;12084:1;12081;12073:13;11643:1;12112;12108:9;12103:14;;;;;11503:628;;;11507:14;11426:1;12199:10;12196:1;11426;12179:9;12172:5;12159:57;12144:72;;12256:16;11426:1;;12229:44;12296:7;12286:53;;12320:16;11426:1;12307:30;12286:53;;12365:16;11426:1;12352:30;29725:224:3;29801:4;-1:-1:-1;;;;;;;;;29846:47:3;;29895:46;;;-1:-1:-1;;;29846:47:3;;;3385:40:2;29836:106:3;29817:125;29725:224;-1:-1:-1;;29725:224:3:o;29387:112::-;29426:19;29469:23;:21;:23::i;:::-;-1:-1:-1;29457:35:3;29387:112;-1:-1:-1;29387:112:3:o;17054:407::-;17217:7;30393:40;30425:7;30393:31;:40::i;:::-;17236:14:::1;17253:41;17267:7;17276:4;17282:11;17253:13;:41::i;:::-;17236:58;;17304:18;17325:20;17338:6;17325:12;:20::i;:::-;17355:21;::::0;::::1;:28:::0;;;17398:56:::1;::::0;;23520:4:21;23508:17;;;23490:36;;23562:17;;23557:2;23542:18;;23535:45;23596:18;;;23589:34;;;17304:41:3;;-1:-1:-1;;;;;;17398:56:3;::::1;::::0;::::1;::::0;23478:2:21;23463:18;17398:56:3::1;;;;;;;;17226:235;;17054:407:::0;;;;;:::o;24702:164::-;24777:5;24801:9;:42;24811:31;24825:7;24834:4;24840:1;24811:13;:31::i;:::-;24801:42;;;;;;;;;;;-1:-1:-1;24801:42:3;:58;;;-1:-1:-1;;;24801:58:3;;;;;-1:-1:-1;24702:164:3;;;;:::o;21986:204::-;22046:14;22063:31;:29;:31::i;:::-;-1:-1:-1;;;;;22104:22:3;;;;;;;:14;:22;;;;;;;;;:31;;-1:-1:-1;;;;;;22104:31:3;;;;;;;;;22150:33;;20140:51:21;;;22104:22:3;;-1:-1:-1;22104:22:3;22150:33;;20113:18:21;22150:33:3;;;;;;;;22036:154;21986:204;:::o;15510:656::-;15691:7;30393:40;30425:7;30393:31;:40::i;:::-;15710:14:::1;15727:41;15741:7;15750:4;15756:11;15727:13;:41::i;:::-;15710:58;;15778:18;15799:20;15812:6;15799:12;:20::i;:::-;15778:41:::0;-1:-1:-1;15902:15:3::1;::::0;::::1;::::0;:46;::::1;;;-1:-1:-1::0;15932:16:3::1;15921:27:::0;;::::1;;;15902:46;15898:76;;;15957:17;;-1:-1:-1::0;;;15957:17:3::1;;;;;;;;;;;15898:76;15984:38;16003:9;16014:7;15984:18;:38::i;:::-;16032:11;::::0;::::1;:23:::0;;::::1;::::0;;::::1;-1:-1:-1::0;;16065:19:3;;;;;;;;::::1;::::0;;::::1;;::::0;;;16099:60:::1;::::0;;23883:4:21;23871:17;;;23853:36;;23925:17;;23920:2;23905:18;;23898:45;23988:18;;;23981:43;;;;24055:2;24040:18;;24033:43;;;;-1:-1:-1;;;;;16099:60:3;::::1;::::0;::::1;::::0;23840:3:21;23825:19;16099:60:3::1;;;;;;;15700:466;;15510:656:::0;;;;;;:::o;18387:569::-;18542:7;30393:40;30425:7;30393:31;:40::i;:::-;18561:14:::1;18578:41;18592:7;18601:4;18607:11;18578:13;:41::i;:::-;18561:58;;18629:18;18650:20;18663:6;18650:12;:20::i;:::-;18629:41:::0;-1:-1:-1;18755:15:3::1;::::0;::::1;::::0;:36;::::1;;;-1:-1:-1::0;18774:6:3::1;::::0;::::1;::::0;-1:-1:-1;;;18774:6:3;::::1;:17;:6;:17:::0;18755:36:::1;18751:66;;;18800:17;;-1:-1:-1::0;;;18800:17:3::1;;;;;;;;;;;18751:66;18827:27;18848:5;18827:20;:27::i;:::-;18864:13;::::0;::::1;:21:::0;;-1:-1:-1;;;;18864:21:3::1;-1:-1:-1::0;;;18864:21:3::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;18900:49:::1;::::0;;24309:4:21;24297:17;;;24279:36;;24351:17;;24346:2;24331:18;;24324:45;24385:18;;;24378:51;;;;-1:-1:-1;;;;;18900:49:3;::::1;::::0;::::1;::::0;24267:2:21;24252:18;18900:49:3::1;24087:348:21::0;14306:676:3;14455:7;30393:40;30425:7;30393:31;:40::i;:::-;14474:14:::1;14491:41;14505:7;14514:4;14520:11;14491:13;:41::i;:::-;14474:58;;14542:18;14563:20;14576:6;14563:12;:20::i;:::-;14542:41:::0;-1:-1:-1;14695:15:3::1;::::0;::::1;::::0;:45;::::1;;;-1:-1:-1::0;14714:6:3::1;::::0;::::1;::::0;-1:-1:-1;;;14714:6:3;::::1;:26;:6;4565:1;14714:26;;14695:45;14691:75;;;14749:17;;-1:-1:-1::0;;;14749:17:3::1;;;;;;;;;;;14691:75;14840:6;::::0;::::1;::::0;-1:-1:-1;;;;;14840:6:3;;::::1;:26;:6;:26:::0;14836:56:::1;;14875:17;;-1:-1:-1::0;;;14875:17:3::1;;;;;;;;;;;14836:56;14902:15:::0;;-1:-1:-1;;;;;14902:15:3;::::1;-1:-1:-1::0;;;14902:15:3;::::1;-1:-1:-1::0;;;;;14902:15:3;;::::1;;::::0;;14932:43:::1;::::0;;24662:4:21;24650:17;;;24632:36;;24704:17;;24699:2;24684:18;;24677:45;24738:18;;;24731:67;;;;14932:43:3;;::::1;::::0;::::1;::::0;24620:2:21;24605:18;14932:43:3::1;24440:364:21::0;10813:2439:3;10872:19;;10924:61;10937:47;10951:9;;;;:1;:9;:::i;:::-;10962:6;;;;;;;;:::i;:::-;10970:13;;;;;;;;:::i;:::-;10937;:47::i;:::-;10924:12;:61::i;:::-;10903:82;;11070:19;11087:1;11070:16;:19::i;:::-;11178:6;;;;-1:-1:-1;;;11178:6:3;;;;-1:-1:-1;;11198:21:3;;11194:186;;11221:19;11235:1;11238;11221:13;:19::i;:::-;11194:186;;;-1:-1:-1;;11259:24:3;;;;11255:125;;11285:30;11310:1;11313;11285:24;:30::i;11255:125::-;-1:-1:-1;;11334:24:3;;;;11330:50;;11367:13;;-1:-1:-1;;;11367:13:3;;;;;;;;;;;11330:50;11391:28;11408:4;11414:1;11417;11391:16;:28::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11639:11:3;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11631:19:3;:4;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11631:19:3;;:46;;11666:11;;;;;;;;:::i;:::-;11631:46;;;11661:1;11631:46;-1:-1:-1;;;;;11617:60:3;:11;;;:60;;;11730:56;;11753:1;;11769:16;;;;:1;:16;:::i;:::-;11730:22;:56::i;:::-;11715:71;;:12;;;:71;11797:26;11826:70;11845:6;;;;;;;;:::i;:::-;11853:1;11856:10;;;;;;;;:::i;:::-;11868:13;;;;;;;;:::i;:::-;11883:1;:12;;;11826:18;:70::i;:::-;11924:7;;11797:99;;-1:-1:-1;11911:9:3;:20;11907:65;;11964:7;;11940:32;;-1:-1:-1;;;11940:32:3;;11953:9;11940:32;;;25909:25:21;25950:18;;;25943:34;;;;25882:18;;11940:32:3;;;;;;;;11907:65;12028:16;;;;12009;;;:35;12075:18;;;;12054;;;:39;12125:19;;;;12103;;;:41;;;12395:24;12391:119;;12476:19;;;;12439:20;:33;12460:11;;;;;;;;:::i;:::-;-1:-1:-1;;;;;12439:33:3;;;;;;;;;;;;-1:-1:-1;12439:33:3;:56;;;;;;;12391:119;12527:18;;;;:23;12523:115;;12605:18;;;;12590:10;;-1:-1:-1;;;;;12590:10:3;12570:19;:31;;;;;;;;;;:53;;;;;;;12523:115;12732:25;12778:9;;;;:1;:9;:::i;:::-;12732:56;-1:-1:-1;12811:10:3;;;;;;;;:::i;:::-;12798:23;;;;12868:16;;;;-1:-1:-1;;;;;12847:12:3;;;;;12887:6;;;;;;;;:::i;:::-;12895:4;;;;;;;;:::i;:::-;12901:10;;;;;;;;:::i;:::-;12847:65;;-1:-1:-1;;;;;;12847:65:3;;;;;;;26215:4:21;26203:17;;;12847:65:3;;;26185:36:21;-1:-1:-1;;;;;26257:32:21;;;26237:18;;;26230:60;12847:65:3;26326:23:21;26306:18;;;26299:51;26158:18;;12847:65:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12831:13;;;:81;12938:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;12922:29:3;:13;;;:29;12985:21;;;;;;;;:::i;:::-;12961:45;;:21;;;:45;13038:19;;;;;;;;:::i;:::-;13016:41;;:19;;;:41;13090:7;;13067:20;;;:30;13121:11;;;;13107;;;:25;13198:15;;;;13189:4;;;;;;;;:::i;:::-;-1:-1:-1;;;;;13148:66:3;13155:9;;;;:1;:9;:::i;:::-;-1:-1:-1;;;;;13148:66:3;;13166:6;;;;;;;;:::i;:::-;13174:13;;;;;;;;:::i;:::-;13195:1;13148:66;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;13232:13:3;;;;10813:2439;-1:-1:-1;;;;10813:2439:3:o;27112:387::-;27199:24;;:::i;:::-;4547:2:2;4543:10;;;27284:29:3;;;;4540:37:2;;;;27235:26:3;27264:50;;;:19;:50;;;;;;;;;27235:79;;;;;;;;;-1:-1:-1;;;;;27235:79:3;;;;;-1:-1:-1;;;27235:79:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;27235:79:3;;;;;;;;-1:-1:-1;;;27235:79:3;;;;;;;;;;;27324:90;;27343:19;:71;4547:2:2;4543:10;;;6014:3:3;4540:37:2;27343:71:3;;;;;;;;;;;;;;-1:-1:-1;27343:71:3;27339:75;;;;;;;;;-1:-1:-1;;;;;27339:75:3;;;;;-1:-1:-1;;;27339:75:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;27339:75:3;;;;;;;;-1:-1:-1;;;27339:75:3;;;;;;;;;;;-1:-1:-1;27324:90:3;27429:1;:8;;;27424:23;;27439:8;;:::i;:::-;;;27424:23;27491:1;27112:387;-1:-1:-1;;;27112:387:3:o;29555:121::-;29597:22;29646:23;:21;:23::i;24214:432::-;24440:24;;:::i;:::-;24476:14;24493:41;24507:7;24516:4;24522:11;24493:13;:41::i;:::-;24476:58;;24551:88;24570:4;24576:20;24589:6;24576:12;:20::i;:::-;24598:8;24608:11;24621:17;24551:18;:88::i;:::-;24544:95;24214:432;-1:-1:-1;;;;;;;;24214:432:3:o;26862:194::-;26935:24;;:::i;:::-;-1:-1:-1;6014:3:3;4547:2:2;4543:10;;;4540:37;;26978:71:3;;;;:19;:71;;;;;;;;;26971:78;;;;;;;;;-1:-1:-1;;;;;26971:78:3;;;;;-1:-1:-1;;;26971:78:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;26971:78:3;;;;;;;;;;;-1:-1:-1;;;26971:78:3;;;;;;;;;;;26862:194::o;21751:179::-;21802:14;21819:31;:29;:31::i;:::-;-1:-1:-1;;;;;21860:15:3;;;;;;:7;:15;;;;;;;;;:23;;-1:-1:-1;;21860:23:3;-1:-1:-1;;;;;21860:23:3;;;;;;;;21898:25;;852:58:21;;;21860:15:3;;-1:-1:-1;21860:15:3;;21898:25;;825:18:21;21898:25:3;708:208:21;25264:377:3;25472:4;25488:14;25505:41;25519:7;25528:4;25534:11;25505:13;:41::i;:::-;25488:58;;25563:71;25586:20;25599:6;25586:12;:20::i;:::-;25608:9;25619:14;;25563:22;:71::i;26028:544::-;26194:21;26227:14;26244:41;26258:7;26267:4;26273:11;26244:13;:41::i;:::-;26295:31;26329:22;;;:14;:22;;;;;26227:58;;-1:-1:-1;26382:12:3;26371:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;26371:31:3;;26361:41;;26441:9;26436:120;26452:24;;;26436:120;;26514:27;26525:12;;26538:1;26525:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;26514:27;;:6;:10;;:27;;;;:::i;:::-;26501:7;26509:1;26501:10;;;;;;;;:::i;:::-;:40;;;:10;;;;;;;;;;;:40;26478:3;;26436:120;;;;26217:355;;26028:544;;;;;;;:::o;26628:178::-;26706:24;;:::i;:::-;-1:-1:-1;26769:29:3;;;;4547:2:2;4543:10;;;4540:37;26749:50:3;;;;:19;:50;;;;;;;;;26742:57;;;;;;;;;-1:-1:-1;;;;;26742:57:3;;;;;-1:-1:-1;;;26742:57:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;26742:57:3;;;;;;;-1:-1:-1;;;26742:57:3;;;;;;;;;;26628:178::o;6989:596:13:-;-1:-1:-1;;;7114:18:13;;7087:13;;;7114:18;7385:23;:21;:23::i;:::-;6989:596;;7367:41;;;-1:-1:-1;7428:13:13;;-1:-1:-1;7479:4:13;;-1:-1:-1;6989:596:13;;-1:-1:-1;6989:596:13;:::o;20703:273:3:-;20770:14;20787:31;:29;:31::i;:::-;20770:48;;20828:38;20856:9;20828:27;:38::i;:::-;-1:-1:-1;;;;;20876:26:3;;;;;;;:18;:26;;;;;;;;;:38;;-1:-1:-1;;;;;;20876:38:3;;;;;;;;;20929:40;;20140:51:21;;;20876:26:3;;20929:40;;20113:18:21;20929:40:3;19994:203:21;19012:502:3;19172:7;30393:40;30425:7;30393:31;:40::i;:::-;19191:14:::1;19208:41;19222:7;19231:4;19237:11;19208:13;:41::i;:::-;19191:58;;19259:18;19280:20;19293:6;19280:12;:20::i;:::-;4458:1;19314:6:::0;;::::1;::::0;19259:41;;-1:-1:-1;;;;19314:6:3;;::::1;:23;:6;:23;19310:53;;19346:17;;-1:-1:-1::0;;;19346:17:3::1;;;;;;;;;;;19310:53;19373:31;19393:10;19373:19;:31::i;:::-;19414:12;::::0;::::1;:25:::0;;;19454:53:::1;::::0;;23520:4:21;23508:17;;;23490:36;;23562:17;;23557:2;23542:18;;23535:45;23596:18;;;23589:34;;;-1:-1:-1;;;;;19454:53:3;::::1;::::0;::::1;::::0;23478:2:21;23463:18;19454:53:3::1;23296:333:21::0;21383:312:3;21465:14;21482:31;:29;:31::i;:::-;21465:48;;21523:29;21550:1;21523:26;:29::i;:::-;21634:1;21562:19;:69;4547:2:2;4543:10;;;6014:3:3;4540:37:2;21562:69:3;;;;;;;;;;;;;;-1:-1:-1;21562:69:3;:73;;;;;;;;-1:-1:-1;;;;;21562:73:3;;;-1:-1:-1;;;;;;21562:73:3;;;;-1:-1:-1;;;21562:73:3;;;;;;;;;;;;-1:-1:-1;21562:73:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;21562:73:3;-1:-1:-1;;;21562:73:3;;;;;;;;-1:-1:-1;;;;21562:73:3;;;;;-1:-1:-1;;;21562:73:3;;;;;;;;;;;;;21650:38;-1:-1:-1;;;;;21650:38:3;;;;;;;21686:1;;21650:38;:::i;27555:751::-;27615:19;4543:10:2;;;27670:28:3;27701:36;;;:9;:36;;;;;27763:23;;;;;-1:-1:-1;;;27763:23:3;;;;;-1:-1:-1;;;27834:16:3;;;27763:23;27900:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;27896:21;;28088:202;28095:6;;28088:202;;28152:25;;;4547:2:2;4543:10;;;4540:37;28121:18:3;28142:36;;;:9;:36;;;;;28205:42;4543:10:2;28229:6:3;28234:1;28229:6;;;;28152:25;28205:8;:42::i;:::-;28196:1;28198:3;;;;;;;28196:6;;;;;;;;:::i;:::-;;;;;;;;;;:51;28269:6;;;-1:-1:-1;;;28269:6:3;;;;;-1:-1:-1;28088:202:3;;;27646:654;;;27555:751;;;:::o;7658:3099::-;7724:17;7753:42;7785:1;:9;;;7753:31;:42::i;:::-;7806:43;7831:1;:17;;;7806:24;:43::i;:::-;7873:6;;;;7894:15;;;7890:569;;7948:1;7925:12;;;:25;7890:569;;;-1:-1:-1;;7971:21:3;;;;7967:492;;8008:33;8028:1;:12;;;8008:19;:33::i;:::-;7967:492;;;-1:-1:-1;;8062:24:3;;;;8058:401;;8125:1;8102:12;;;:25;8167:16;8141:23;;;:42;8058:401;;;-1:-1:-1;;8204:24:3;;;;8200:259;;8267:1;8244:12;;;:25;;;8309:16;8283:23;;;:42;8339:7;;;:11;8200:259;;;8435:13;;-1:-1:-1;;;8435:13:3;;;;;;;;;;;8200:259;8538:6;;;;:17;;8534:586;;8583:16;8571:9;;;:28;;;8613:23;;;:42;8928:24;;;4565:1;8928:24;8924:41;;8964:1;8954:7;;;:11;8924:41;9060:15;;;9056:53;;9093:16;9077:13;;;:32;9056:53;9130:42;9149:1;:11;;;9162:1;:9;;;9130:18;:42::i;:::-;9182:55;9213:1;:23;;;9182:30;:55::i;:::-;9247:35;9268:1;:13;;;9247:20;:35::i;:::-;9317:25;9345:9;:46;9355:35;9369:1;:9;;;9380:1;:6;;;9388:1;9355:13;:35::i;:::-;9345:46;;;;;;;;;;;;;;-1:-1:-1;9345:46:3;;;9460:9;;4547:2:2;4543:10;9436:38:3;;:9;:38;;;;9503:24;;;;;-1:-1:-1;;;9503:24:3;;;;;-1:-1:-1;9345:46:3;;-1:-1:-1;9436:38:3;9582:3;;9503:24;9582:13;;9578:42;;9597:23;:21;:23::i;:::-;9634:24;;;;:35;;;;;;-1:-1:-1;;;9634:35:3;-1:-1:-1;;;;9634:35:3;;;;;;;;;;9688:23;;;;;-1:-1:-1;;;9688:23:3;;;;9729:3;9736:7;9729:14;;9725:43;;9745:23;:21;:23::i;:::-;9782;;;:35;;-1:-1:-1;;;;9782:35:3;-1:-1:-1;;;9782:35:3;;;;;;;9863:9;;9782:35;9874:6;;;-1:-1:-1;;9849:45:3;;9882:11;9849:13;:45::i;:::-;9832:62;;9909:18;9930:9;:17;9940:6;9930:17;;;;;;;;;;;9909:38;;9974:1;:10;;;9961:1;:10;;;:23;;;;;-1:-1:-1;;;;;9961:23:3;;;;;-1:-1:-1;;;;;9961:23:3;;;;;;10008:1;:7;;;9998:1;:7;;;:17;;;;;-1:-1:-1;;;;;9998:17:3;;;;;-1:-1:-1;;;;;9998:17:3;;;;;;10043:1;:11;;;10029:1;:11;;;:25;;;;;;;;;;;;;;;;;;10080:1;:9;;;10068:1;:9;;;:21;;;;;;;;;;;;;;;;;;10129:1;:23;;;10103:1;:23;;;:49;;;;;;;;;;;;;;;;;;10182:1;:13;;;10166:1;:13;;;:29;;;;;;;;;;;;;;;;;;10229:1;:17;;;10209:1;:17;;;:37;;;;;;;;;;;;;;;;;;10269:1;:6;;;10260:1;:6;;;:15;;;;;;;;;;;;;;;;;;5504:6;10289:1;:7;;;:28;;;;;;;;;;;;;;;;;;10340:11;:16;;;;;;;;;;;;10331:1;:6;;;:25;;;;;;;;;;;;;;;;;;10429:11;10421:20;;10416:1;10405;:6;;;10397:15;;:20;;10396:45;10370:11;:16;;;:72;;;;;;;;;;;;;;;;;;10552:1;10544:10;;10519:1;:21;;;:35;10515:86;;10580:21;;;;10556;;;:45;10515:86;10619:12;;;;:26;10615:59;;10662:12;;;;10647;;;:27;10615:59;10706:1;:9;;;-1:-1:-1;;;;;10694:46:3;;10717:1;:6;;;10725:11;10738:1;10694:46;;;;;;;;:::i;:::-;;;;;;;;9293:1458;;;;;7743:3014;7658:3099;;;:::o;17517:814::-;17682:7;30393:40;30425:7;30393:31;:40::i;:::-;17701:14:::1;17718:41;17732:7;17741:4;17747:11;17718:13;:41::i;:::-;17701:58;;17769:18;17790:20;17803:6;17790:12;:20::i;:::-;17769:41:::0;-1:-1:-1;17873:15:3::1;::::0;::::1;17869:45;;17897:17;;-1:-1:-1::0;;;17897:17:3::1;;;;;;;;;;;17869:45;17985:6;::::0;::::1;::::0;-1:-1:-1;;;;;17985:6:3;;::::1;:26;:6;:26:::0;17981:56:::1;;18020:17;;-1:-1:-1::0;;;18020:17:3::1;;;;;;;;;;;17981:56;18110:6;::::0;::::1;::::0;-1:-1:-1;;;;;18110:6:3;;::::1;:26;:6;:26:::0;18106:56:::1;;18145:17;;-1:-1:-1::0;;;18145:17:3::1;;;;;;;;;;;18106:56;18172:37;18203:5;18172:30;:37::i;:::-;18219:23;::::0;::::1;:31:::0;;-1:-1:-1;;18219:31:3::1;-1:-1:-1::0;;;18219:31:3::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;18265:59:::1;::::0;;24309:4:21;24297:17;;;24279:36;;24351:17;;24346:2;24331:18;;24324:45;24385:18;;;24378:51;;;;-1:-1:-1;;;;;18265:59:3;::::1;::::0;::::1;::::0;24267:2:21;24252:18;18265:59:3::1;24087:348:21::0;16222:296:3;16365:14;16382:41;16396:7;16405:4;16411:11;16382:13;:41::i;:::-;16485:17;;;;:9;:17;;;;;:25;;;:17;;-1:-1:-1;16433:78:3;;16446:7;;16455:4;;16461:11;;16474:9;;16485:25;;;;;16433:12;:78::i;:::-;16355:163;16222:296;;;;:::o;23833:325::-;24016:24;;:::i;:::-;24059:92;24092:7;24101:4;24107:11;24120:8;24130:1;24133:17;24059:32;:92::i;:::-;24052:99;23833:325;-1:-1:-1;;;;;;23833:325:3:o;16574:424::-;16728:7;30393:40;30425:7;30393:31;:40::i;:::-;16747:14:::1;16764:41;16778:7;16787:4;16793:11;16764:13;:41::i;:::-;16747:58;;16815:18;16836:20;16849:6;16836:12;:20::i;:::-;16815:41;;16866:29;16891:3;16866:24;:29::i;:::-;16905:17;::::0;::::1;:23:::0;;-1:-1:-1;;;;16905:23:3::1;-1:-1:-1::0;;;16905:23:3::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;16943:48:::1;::::0;;30231:4:21;30219:17;;;30201:36;;30273:17;;30268:2;30253:18;;30246:45;30307:18;;;30300:47;;;;-1:-1:-1;;;;;16943:48:3;::::1;::::0;::::1;::::0;30189:2:21;30174:18;16943:48:3::1;30009:344:21::0;24922:286:3;25072:6;25090:14;25107:41;25121:7;25130:4;25136:11;25107:13;:41::i;:::-;-1:-1:-1;;;;;25165:24:3;;;;;;:13;:24;;;;;;;;3360:1:16;3351:10;;;3343:19;;;;;;;;25090:58:3;;-1:-1:-1;3367:16:16;3382:1;3367:16;;;;3343:41;25165:36:3;25158:43;;;24922:286;;;;;;;:::o;28362:969::-;28479:20;;:::i;:::-;28511:14;28528:41;28542:7;28551:4;28557:11;28528:13;:41::i;:::-;28511:58;;28579:18;28600:20;28613:6;28600:12;:20::i;:::-;-1:-1:-1;;;;;28630:22:3;;;;;28662:16;;;;:9;;;:16;;;28688:30;;;:16;;;:30;28744:10;;;;;28728:13;;;:26;28579:41;;-1:-1:-1;28777:15:3;:45;;;;-1:-1:-1;28796:6:3;;;;-1:-1:-1;;;28796:6:3;;:26;:6;4565:1;28796:26;;28777:45;:77;;28847:7;;-1:-1:-1;;;28847:7:3;;-1:-1:-1;;;;;28847:7:3;28777:77;;;28833:10;;-1:-1:-1;;;;;28833:10:3;28825:19;;;;:7;:19;;;;;;-1:-1:-1;;;;;28825:19:3;28777:77;-1:-1:-1;;;;;28764:90:3;:10;;;:90;28881:11;;;;;;;;28864:14;;;:28;28917:9;;;;;28902:12;;;:24;-1:-1:-1;;;28965:23:3;;;;28936:26;;;:52;-1:-1:-1;;;29017:13:3;;;;28881:11;28998:16;;:32;-1:-1:-1;;;29054:8:3;;;29040:11;;;:22;-1:-1:-1;;;29095:17:3;;;;29072:20;;;:40;-1:-1:-1;;;29134:6:3;;;;29122:9;;;:18;5637:6;-1:-1:-1;;;47050:7:3;;;:27;;:32;;29150:11;;;:26;29213:21;;;29186:24;;;:48;29262:12;;;;29244:15;;;:30;29313:10;-1:-1:-1;;;;;29313:10:3;;;-1:-1:-1;29298:26:3;;;:14;:26;;;;;;;29284:11;;;:40;-1:-1:-1;28764:10:3;29150:4;-1:-1:-1;;;28362:969:3:o;15038:416::-;15187:7;30393:40;30425:7;30393:31;:40::i;:::-;15206:14:::1;15223:41;15237:7;15246:4;15252:11;15223:13;:41::i;:::-;15206:58;;15274:18;15295:20;15308:6;15295:12;:20::i;:::-;15352:7;::::0;::::1;::::0;15274:41;;-1:-1:-1;15335:52:3::1;::::0;15352:7:::1;-1:-1:-1::0;;;15352:7:3;;::::1;;5637:6;15380::::0;2304:4:2;2310:16;;;2300:27;2293:35;2330:12;;2289:54;2285:65;2274:77;;2109:258;15335:52:3::1;15325:7;::::0;::::1;:62:::0;;-1:-1:-1;;;;15325:62:3::1;-1:-1:-1::0;;;15325:62:3::1;::::0;;::::1;;;::::0;;15402:45:::1;::::0;;30564:17:21;;;30546:36;;30618:17;;;30613:2;30598:18;;30591:45;30679:14;;30672:22;30652:18;;;30645:50;-1:-1:-1;;;;;15402:45:3;::::1;::::0;::::1;::::0;30534:2:21;30519:18;15402:45:3::1;30358:343:21::0;22733:496:3;22802:7;22867:355;3227:390;22954:9;;;;:1;:9;:::i;:::-;22981:6;;;;;;;;:::i;:::-;23006:13;;;;;;;;:::i;:::-;23037:4;;;;;;;;:::i;:::-;23059:16;;;;;;;;:::i;:::-;23093:19;;;;;;;;:::i;:::-;23130:13;;;;;;;;:::i;:::-;23161:16;;;;;;;;:::i;:::-;23195:11;;;;;;;;:::i;:::-;22892:328;;;;;;31089:25:21;;;;-1:-1:-1;;;;;31188:15:21;;;31168:18;;;31161:43;31252:4;31240:17;;;31220:18;;;31213:45;31294:17;;;;31274:18;;;31267:45;31349:15;;;31328:19;;;31321:44;31384:10;31431:15;;;31410:19;;;31403:44;31484:15;;31463:19;;;31456:44;-1:-1:-1;;;;;31537:39:21;;;31516:19;;;31509:68;31614:15;31593:19;;;31586:44;31667:15;31646:19;;;31639:44;31061:19;;22892:328:3;;;;;;;;;;;;;22882:339;;;;;;22867:14;:355::i;13308:775::-;13377:19;;13429:61;13442:47;13456:9;;;;:1;:9;:::i;13429:61::-;13408:82;;13575:19;13592:1;13575:16;:19::i;:::-;13609:6;;;;-1:-1:-1;;;13609:6:3;;:26;:6;4674:1;13609:26;13605:52;;13644:13;;-1:-1:-1;;;13644:13:3;;;;;;;;;;;13605:52;13667:44;13706:1;13709;13667:38;:44::i;:::-;13722:37;13754:1;13757;13722:31;:37::i;:::-;13844:25;13890:9;;;;:1;:9;:::i;:::-;13844:56;-1:-1:-1;;;;;;13924:15:3;;;13940:6;;;;;;;;:::i;:::-;13948:4;;;;:1;:4;:::i;:::-;13954:16;;;;;;;;:::i;:::-;13924:47;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13910:61;-1:-1:-1;14006:9:3;;;;:1;:9;:::i;:::-;-1:-1:-1;;;;;13987:89:3;;14017:6;;;;;;;;:::i;:::-;14025:13;;;;;;;;:::i;:::-;14040:4;;;;:1;:4;:::i;:::-;14046:16;;;;;;;;:::i;:::-;14064:11;13987:89;;;;;;;;;;;:::i;:::-;;;;;;;;13398:685;;13308:775;;;:::o;21032:295::-;21119:14;21136:31;:29;:31::i;:::-;21119:48;;21177:29;21204:1;21177:26;:29::i;:::-;21267:1;21216:19;:48;4547:2:2;4543:10;;;21236:27:3;;;4540:37:2;21216:48:3;;;;;;;;;;;;;;-1:-1:-1;21216:48:3;:52;;;;;;;;-1:-1:-1;;;;;21216:52:3;;;-1:-1:-1;;;;;;21216:52:3;;;;-1:-1:-1;;;21216:52:3;;;;;;;;;;;;-1:-1:-1;21216:52:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;21216:52:3;-1:-1:-1;;;21216:52:3;;;;;;;;-1:-1:-1;;;;21216:52:3;;;;;-1:-1:-1;;;21216:52:3;;;;;;;;;;;;;21283:37;-1:-1:-1;;;;;21283:37:3;;;;;;;21312:4;;21318:1;;21283:37;:::i;:::-;;;;;;;;21109:218;21032:295;;:::o;20073:438::-;-1:-1:-1;;;;;20157:28:3;;;20137:17;20157:28;;;:18;:28;;;;;;;20195:38;20157:28;20195:27;:38::i;:::-;-1:-1:-1;;;;;20261:29:3;;20243:15;20261:29;;;;;;;;;;;20304:12;;20300:205;;-1:-1:-1;;;;;20332:29:3;;20364:1;20332:29;;;;;;;;;;:33;20379:56;20416:9;20427:7;20379:36;:56::i;:::-;20476:8;-1:-1:-1;;;;;20454:40:3;;20486:7;20454:40;;;;1989:25:21;;1977:2;1962:18;;1843:177;20300:205:3;20127:384;;20073:438;:::o;23285:492::-;23372:7;23437:333;3798:326;23533:9;;;;:1;:9;:::i;:::-;23560:6;;;;;;;;:::i;:::-;23585:13;;;;;;;;:::i;:::-;23643:4;;;;:1;:4;:::i;:::-;23626:22;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;23626:22:3;;;;;;;;;23616:33;;23626:22;23616:33;;;;23667:16;;;;;;;;:::i;:::-;23701:19;;;;;;;;:::i;:::-;23738:16;;;;;;;;:::i;:::-;23462:306;;;;;;35152:25:21;;;;-1:-1:-1;;;;;35213:32:21;;;35193:18;;;35186:60;;;;35294:4;35282:17;;;35262:18;;;35255:45;35336:17;;;;35316:18;;;35309:45;35370:19;;;35363:35;35417:10;35464:15;;;35443:19;;;35436:44;35517:15;;;35496:19;;;35489:44;35570:15;35549:19;;;35542:44;35124:19;;23462:306:3;34823:769:21;19677:340:3;-1:-1:-1;;;;;19761:31:3;;19743:15;19761:31;;;:20;:31;;;;;;19806:12;;19802:209;;-1:-1:-1;;;;;19834:31:3;;19868:1;19834:31;;;:20;:31;;;;;:35;19883:56;19855:9;19931:7;19883:36;:56::i;:::-;19981:9;-1:-1:-1;;;;;19958:42:3;;19992:7;19958:42;;;;1989:25:21;;1977:2;1962:18;;1843:177;19802:209:3;19733:284;19677:340;:::o;25697:275::-;25853:4;25876:89;25898:7;25907:4;25913:11;25926:9;14090:24:18;25853:4:3;25264:377;:::i;25876:89::-;25869:96;25697:275;-1:-1:-1;;;;;25697:275:3:o;33716:226::-;33888:21;;;;;;;;;;;-1:-1:-1;;;33888:21:3;;;;;;;;33919:16;;;;;;;;;;;-1:-1:-1;;;33919:16:3;;;;33888:21;33716:226::o;30589:297::-;30671:14;30688:31;:29;:31::i;:::-;30671:48;;30756:7;-1:-1:-1;;;;;30743:27:3;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;30733:39:3;:6;-1:-1:-1;;;;;30733:39:3;;30729:150;;30791:59;;-1:-1:-1;;;30791:59:3;;-1:-1:-1;;;;;36045:32:21;;;30791:59:3;;;36027:51:21;1211:6:2;36094:18:21;;;36087:34;30791:32:3;;;;;36000:18:21;;30791:59:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;30786:93;;30852:27;:25;:27::i;4895:317:2:-;5012:14;5082:7;5078:2;5074:16;5068:4;5061:30;5118:4;5112;5104:19;5150:11;5144:4;5136:26;-1:-1:-1;;5191:4:2;5185:11;;4895:317;-1:-1:-1;;4895:317:2:o;46605:193:3:-;46666:18;46700:17;;;:9;:17;;;;;5504:6;46731:7;;;;46700:17;;-1:-1:-1;;;46731:7:3;;;:28;:33;;46727:64;;46773:18;;-1:-1:-1;;;46773:18:3;;;;;;;;;;;46727:64;46605:193;;;:::o;4101:809:7:-;4150:14;4255:8;4249:4;4242:22;4295:23;4347:10;4337:8;4334:24;4331:231;;4441:4;4435;4429;4417:10;4405;4398:5;4387:59;4377:171;;4489:10;4477;4470:30;4377:171;4331:231;4593:23;4645:10;4635:8;4632:24;4629:231;;4739:4;4733;4727;4715:10;4703;4696:5;4685:59;4675:171;;4787:10;4775;4768:30;4675:171;-1:-1:-1;;4889:4:7;4883:11;;4101:809::o;31063:143:3:-;31165:7;31153:19;;:9;:19;;;31149:50;;;31181:18;;-1:-1:-1;;;31181:18:3;;;;;;;;;;;31611:117;31683:5;:10;;31692:1;31683:10;31679:42;;31702:19;;-1:-1:-1;;;31702:19:3;;;;;;;;;;;31679:42;31611:117;:::o;36691:306::-;36793:11;;;;36775:15;36824:9;;;36793:11;36824:9;;;-1:-1:-1;;36793:11:3;;-1:-1:-1;3385:40:2;36761:146:3;;;36884:11;;;;36855:52;;-1:-1:-1;;;36855:52:3;;36867:15;36897:9;36855:52;;36580:25:21;36884:11:3;;;;36650:18:21;;;36643:43;36897:9:3;;;;;;;36702:18:21;;;36695:43;36553:18;;36855:52:3;36382:362:21;36761:146:3;36921:12;36931:1;47050:7;;;-1:-1:-1;;;47050:7:3;;5637:6;47050:27;:32;;;46965:124;36921:12;36917:37;;;36942:12;;-1:-1:-1;;;36942:12:3;;;;;;;;;;;38806:1708;38892:26;38921:21;;;;;;;;:::i;:::-;38892:50;-1:-1:-1;38952:19:3;38974:13;;;;;;;;:::i;:::-;38952:35;-1:-1:-1;;;;;;39164:25:3;;39160:58;;39198:20;;-1:-1:-1;;;39198:20:3;;;;;;;;;;;39160:58;-1:-1:-1;;39367:16:3;39344:39;;;39340:782;;39594:65;39626:1;:12;;;39640:18;39646:11;45719:14;45768:25;45832:4;45826;45816:21;;45660:193;39640:18;39594:16;;;;:1;:16;:::i;:::-;:31;;;;;:65::i;:::-;39593:66;:170;;;;;39680:83;39712:1;:12;;;39726:36;39732:11;39745:16;46282:4;46275:33;46226:14;46321:25;46385:4;46379;46369:21;;46139:267;39680:83;39679:84;39593:170;39572:233;;;39785:20;;-1:-1:-1;;;39785:20:3;;;;;;;;;;;39572:233;39340:782;;;39980:86;40012:1;:12;;;40026:39;40032:11;40045:19;46282:4;46275:33;46226:14;46321:25;46385:4;46379;46369:21;;46139:267;39980:86;39975:136;;40091:20;;-1:-1:-1;;;40091:20:3;;;;;;;;;;;39975:136;40209:14;40226:31;:29;:31::i;:::-;40209:48;-1:-1:-1;40272:53:3;-1:-1:-1;;;;;40282:21:3;;;;;;;;;40305:4;;;;;;;;:::i;:::-;-1:-1:-1;;;;;40305:19:3;;3395:9:2;;3388:17;3414:9;;3407:17;3385:40;;3288:153;40272:53:3;40267:241;;40412:56;40448:6;40456:11;40412:35;:56::i;:::-;40407:90;;40477:20;;-1:-1:-1;;;40477:20:3;;;;;;;;;;;37185:608;37294:16;;;;;;;;:::i;:::-;37281:29;;:10;;;;;;;;:::i;:::-;:29;;;37277:65;;;37319:23;;-1:-1:-1;;;37319:23:3;;;;;;;;;;;37277:65;37384:10;;-1:-1:-1;;;;;37384:10:3;;;37352:14;37369:26;;;:14;:26;;;;;;;37410:92;37369:26;37466:22;37486:1;37466:19;:22::i;:::-;37490:11;;;;:1;:11;:::i;:::-;37410:47;:92::i;:::-;37405:136;;37523:18;;-1:-1:-1;;;37523:18:3;;;;;;;;;;;37405:136;37573:16;;;;;;;;:::i;:::-;37555:34;;:15;:34;37551:65;;;37598:18;;-1:-1:-1;;;37598:18:3;;;;;;;;;;;37551:65;37626:14;37643:47;37657:9;;;;:1;:9;:::i;:::-;37668:6;;;;;;;;:::i;:::-;37676:13;;;;;;;;:::i;37643:47::-;37626:64;-1:-1:-1;37705:50:3;37735:19;;;;;;;;:::i;:::-;37705:22;;;;:14;:22;;;;;;:50;;;;;:29;:50;:::i;:::-;37700:86;;37764:22;;-1:-1:-1;;;37764:22:3;;;;;;;;;;;37700:86;37267:526;;37185:608;;:::o;34217:1324::-;34423:9;34463:10;;;;;;;;:::i;:::-;34443:8;;;;34455:19;;;;-1:-1:-1;;;34443:8:3;;;;34435:39;;-1:-1:-1;;;;34518:13:3;;;34514:17;;34510:49;;;34540:19;;-1:-1:-1;;;34540:19:3;;;;;;;;;;;34510:49;34573:8;;;:20;;-1:-1:-1;;;;34573:20:3;-1:-1:-1;;;34573:20:3;;;;;;;-1:-1:-1;34686:47:3;34700:9;;;;;;:::i;34686:47::-;34669:64;-1:-1:-1;;;34751:21:3;;;;34747:778;;34792:26;34821:13;34792:26;34835:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;34821:28:3;;;;;;;;;;;;-1:-1:-1;34821:28:3;;-1:-1:-1;34904:10:3;;;;;;;;:::i;:::-;34896:19;;34879:13;34885:6;34879:1;:5;;:13;;;;:::i;:::-;35111:23;;;;34871:22;;;;:44;;;;;-1:-1:-1;35097:65:3;;-1:-1:-1;;;35111:23:3;;;35107:27;;35140:21;;;;;;;;:::i;:::-;35136:25;;:1;:25;3395:9:2;;3388:17;3414:9;;3407:17;3385:40;;3288:153;35097:65:3;35093:100;;;35171:22;;-1:-1:-1;;;35171:22:3;;;;;;;;;;;35093:100;35211:24;:1;35217:6;35232:1;35211:5;:24::i;:::-;34774:476;34747:778;;;35274:26;35303:13;35274:26;35317:4;;;;;;;;:::i;:::-;-1:-1:-1;;;;;35303:19:3;;;;;;;;;;;;-1:-1:-1;35303:19:3;;-1:-1:-1;35377:10:3;;;;;;;;:::i;:::-;35369:19;;35352:13;35358:6;35352:1;:5;;:13;;;;:::i;:::-;35414:23;;;;35344:22;;;;:44;;;;;-1:-1:-1;;;;35414:23:3;;;;35410:27;;35406:62;;;35446:22;;-1:-1:-1;;;35446:22:3;;;;;;;;;;;35406:62;35486:24;:1;35492:6;35507:1;35486:5;:24::i;:::-;35256:269;34343:1192;;34217:1324;;;:::o;44729:700::-;44927:21;;;;44896:4;;44927:21;45019:54;;-1:-1:-1;;;;;;;45050:23:3;;;;45043:30;;45019:54;45332:90;-1:-1:-1;;;;;45343:23:3;;;;45368:53;45398:4;45404:16;45343:9;45719:14;45768:25;45832:4;45826;45816:21;;45660:193;45404:16;45368:14;;;;:29;:53::i;:::-;3999:9:2;3992:17;3980:9;;3973:17;3969:41;;3871:155;40875:3559:3;41065:26;;:::i;:::-;41341:10;;41285:26;;41314:44;;-1:-1:-1;;;;;41341:10:3;41353:4;41314:26;:44::i;:::-;41466:6;;;;41285:73;;-1:-1:-1;;;;;;41466:6:3;;;:26;:6;:26;41462:413;;41530:7;;-1:-1:-1;;;;;;;;41530:7:3;;;;;41516:21;;;;41512:53;;;41546:19;;-1:-1:-1;;;41546:19:3;;;;;;;;;;;41512:53;-1:-1:-1;;;;;41611:25:3;;:11;;;:25;41462:413;;;41661:15;;;41657:218;;41718:10;;-1:-1:-1;;;;;41718:10:3;41710:19;;;;:7;:19;;;;;;;;-1:-1:-1;;;;;41710:19:3;41696:11;;;:33;41657:218;;;41827:7;;-1:-1:-1;;;41827:7:3;;-1:-1:-1;;;;;41827:7:3;41813:11;;;:21;41657:218;41959:11;;;;41973:17;;;41959:31;41946:10;;;:44;;;42108:16;;;:29;42228:17;;;;-1:-1:-1;;;42228:17:3;;;;:22;;;;:43;;;42254:17;42228:43;42224:280;;;42334:10;;;;42346:17;;;;42291:23;;1495:5:2;-1:-1:-1;;;42346:17:3;;;;;3012:9:2;3008:17;42399:16:3;;;:35;;;;;;;42452:19;;;:37;-1:-1:-1;42224:280:3;42592:20;;;;:25;;;42588:261;;42679:10;;;;42691:20;;;;42637:22;;1495:5:2;42662:67:3;;;;3012:9:2;3008:17;42747:16:3;;;:34;;;;;;;42799:18;;;:35;-1:-1:-1;42588:261:3;43073:1;:16;;;-1:-1:-1;;;;;43058:31:3;:1;:11;;;:31;43054:1088;;43129:18;;43109:16;;;:58;;43150:17;;;-1:-1:-1;;;;;43129:38:3;;;;;43109:58;;;;;;43207:20;;;;43185:18;;;:62;;43207:40;;;;;;;43185:62;;;43344:238;;;;43412:21;;;;43389:19;;;:64;;-1:-1:-1;;;;;43412:41:3;;;43436:17;;;43412:41;43389:64;;;;;;43054:1088;;43344:238;43522:21;;;;43500:18;;;:63;;-1:-1:-1;;;;;43522:41:3;;;43546:17;;;43522:41;43500:63;;;;;;43054:1088;;;43640:27;;;;43620:16;;;:67;;43670:17;;;-1:-1:-1;;;;;43640:47:3;;;;;43620:67;;;;;;43727:29;;;;43705:18;;;:71;;43727:49;;;;;;;43705:71;;;43872:256;;;;43940:30;;;;43917:19;;;:73;;-1:-1:-1;;;;;43940:50:3;;;43973:17;;;43940:50;43917:73;;;;;;43872:256;;;44100:8;44092:17;;44059:1;:30;;;-1:-1:-1;;;;;44059:50:3;;44037:1;:18;;:72;;;;;;;;;;;43872:256;44219:19;;;44197:18;;;:41;;-1:-1:-1;;;;;44197:41:3;;;;;;;;;;44377:19;;;;44358:16;;;;:38;:59;44348:69;;44197:18;:1;-1:-1:-1;;;;;40875:3559:3:o;1672:479:15:-;2024:1;2015:10;;;1746;2004:22;;;;;;;;;;;;;2048:1;2039:4;2031:12;;;2004:40;2003:46;;1672:479::o;33407:133:3:-;-1:-1:-1;;;;;33483:15:3;;33479:54;;33507:26;;-1:-1:-1;;;33507:26:3;;;;;;;;;;;31849:136;31926:10;31922:56;;31959:19;;-1:-1:-1;;;31959:19:3;;;;;;;;;;;32397:869;32502:713;32529:173;5360:9;-1:-1:-1;;;;;32560:50:3;:1;:19;;;-1:-1:-1;;;;;32560:50:3;;5060:4;32632:52;;:1;:20;;;:52;;;3395:9:2;;3388:17;3414:9;;3407:17;3385:40;;3288:153;32529:173:3;32720:218;5215:9;-1:-1:-1;;;;;32751:40:3;:1;:18;;;-1:-1:-1;;;;;32751:40:3;;5215:9;-1:-1:-1;;;;;32813:43:3;:1;:21;;;-1:-1:-1;;;;;32813:43:3;;5215:9;-1:-1:-1;;;;;32878:42:3;:1;:20;;;-1:-1:-1;;;;;32878:42:3;;32720:9;:218::i;:::-;32956:245;5215:9;-1:-1:-1;;;;;32987:49:3;:1;:27;;;-1:-1:-1;;;;;32987:49:3;;5215:9;-1:-1:-1;;;;;33058:52:3;:1;:30;;;-1:-1:-1;;;;;33058:52:3;;5215:9;-1:-1:-1;;;;;33132:51:3;:1;:29;;;-1:-1:-1;;;;;33132:51:3;;32956:9;:245::i;:::-;32502:9;:713::i;:::-;32485:774;;;33233:26;;-1:-1:-1;;;33233:26:3;;;;;;;;;;;32132:141;4927:4;32206:27;;;;32202:64;;;32242:24;;-1:-1:-1;;;32242:24:3;;;;;;;;;;;31349:137;31431:5;:10;;31440:1;31431:10;31427:52;;31450:29;;-1:-1:-1;;;31450:29:3;;;;;;;;;;;5267:161:2;5353:10;5347:4;5340:24;5407:4;5401;5394:18;3228:164:16;3360:1;3351:10;;;3302:13;3343:19;;;;;;;;;;;;;3382:1;3367:16;;;;;;3343:41;;3228:164::o;5757:885:13:-;6066:22;9114:11;9255:9;9252:25;9069:14;9225:9;9222:28;9218:60;6102:73;;-1:-1:-1;8545:4:13;8539:11;;8606:16;8596:27;;8383:15;8650:4;8643:12;;8636:31;8426:18;8701:12;;;8694:33;;;;8761:9;8754:4;8747:12;;8740:31;8805:9;8798:4;8791:12;;8784:31;8854:4;8841:18;;6102:73;6309:18;6303:4;6296:32;6375:6;6369:4;6362:20;6439:10;6433:4;6426:24;6515:4;6509;6499:21;6489:31;;6624:1;6618:4;6611:15;5757:885;;;:::o;38007:653:3:-;38242:10;;-1:-1:-1;;;;;38242:10:3;;;38210:14;38227:26;;;:14;:26;;;;;;;38268:101;38227:26;38324:31;38353:1;38324:28;:31::i;:::-;38357:11;;;;:1;:11;:::i;38268:101::-;38263:145;;38390:18;;-1:-1:-1;;;38390:18:3;;;;;;;;;;;38263:145;38440:16;;;;;;;;:::i;:::-;38422:34;;:15;:34;38418:65;;;38465:18;;-1:-1:-1;;;38465:18:3;;;;;;;;;;;38418:65;38493:14;38510:47;38524:9;;;;:1;:9;:::i;38510:47::-;38493:64;-1:-1:-1;38572:50:3;38602:19;;;;;;;;:::i;35758:802::-;35890:14;35907:47;35921:9;;;;:1;:9;:::i;:::-;35932:6;;;;;;;;:::i;:::-;35940:13;;;;;;;;:::i;35907:47::-;35890:64;-1:-1:-1;35968:16:3;35987:4;;;;:1;:4;:::i;:::-;:11;-1:-1:-1;36069:9:3;;-1:-1:-1;36120:16:3;;;;;;;;:::i;:::-;36089:8;;;;36112:25;;;;36101:36;;-1:-1:-1;;;36089:8:3;;;;36081:56;;-1:-1:-1;;;;36181:13:3;;;36177:17;;36173:49;;;36203:19;;-1:-1:-1;;;36203:19:3;;;;;;;;;;;36173:49;36236:8;;;:20;;-1:-1:-1;;;;36236:20:3;-1:-1:-1;;;36236:20:3;;;;;;;-1:-1:-1;36333:211:3;36354:8;36349:1;:13;36333:211;;36387:26;36416:13;36387:26;36430:4;;;;:1;:4;:::i;:::-;36435:1;36430:7;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;36416:22:3;;;;;;;;;;;;-1:-1:-1;36416:22:3;;-1:-1:-1;36456:73:3;36462:6;36510:16;;;;;;;;:::i;:::-;36502:25;;36485:13;36491:6;36485:1;:5;;:13;;;;:::i;:::-;36477:22;;:50;36456:1;:5;;:73;;;;;:::i;:::-;-1:-1:-1;36364:3:3;;36333:211;;5496:721:19;5660:6;5645:13;5642:25;5639:146;;;5699:10;5693:4;5686:24;5766:4;5760;5753:18;5639:146;5877:4;5865:10;5859:4;5847:10;5839:6;5835:2;5813:20;5808:74;5798:403;;5915:2;5909:4;5902:16;5988:4;5982;5974:19;6044:4;6038;6030:19;6123:4;6117;6109:6;6102:26;6092:72;;6151:10;6139;6132:30;5487:169:2;5577:10;5571:4;5564:24;5635:4;5629;5622:18;2397:1407:18;2522:12;2619;2616:1134;;;2759:12;2756:1;2752:20;2738:12;2734:39;2885:12;2983:753;3176:20;;3167:30;;;3164:1;3160:38;3391:21;;;3453:4;3440:18;;;3433:48;3608:4;3602;3592:21;;3644:17;3692:15;;;2983:753;3682:36;2987:2;;2616:1134;-1:-1:-1;3774:14:18;;2397:1407;-1:-1:-1;;2397:1407:18:o;176:956:5:-;261:11;368:4;362:11;493:10;487:4;480:24;567:8;561:4;554:22;636:5;630:4;623:19;1020:4;1014;1008;1002;989:11;982:5;971:54;902:1;895:4;889:11;886:18;795:244;785:254;;1114:1;1108:4;1101:15;;176:956;;;;:::o;6365:4213:20:-;-1:-1:-1;;;;;6690:24:20;;;;6505:12;6717:6;6674:3888;;;6760:4;6754:11;6795:4;6789;6782:18;6841:2;6823:16;6820:24;6817:1164;;6912:4;6890:27;;;6877:41;6960:3;6956:12;;;6970:2;6952:21;6939:35;;7016:30;;7010:4;7003:44;-1:-1:-1;;;;;7089:18:20;7083:4;7076:32;7100:1;7399:4;7346;7100:1;7210:5;7170:384;7725:1;7719:8;7711:6;7707:21;7688:16;7681:24;7678:51;7668:295;;-1:-1:-1;7807:1:20;7801:4;7794:15;7867:4;7860:15;-1:-1:-1;7768:1:20;7936:5;;7668:295;;6817:1164;8022:2;8004:16;8001:24;7998:1063;;8104:4;8086:16;8082:27;8069:41;8066:1;8061:50;8055:4;8048:64;8178:4;8160:16;8154:4;8141:42;8585:4;8531;8479;8426;8368:1;8290:5;8250:384;8805:1;8799:8;8791:6;8787:21;8768:16;8761:24;8758:51;8748:295;;-1:-1:-1;8887:1:20;8881:4;8874:15;8947:4;8940:15;-1:-1:-1;8848:1:20;9016:5;;8748:295;;7998:1063;9091:1;9085:4;9078:15;9149:1;9143:4;9136:15;9223:10;9218:3;9214:20;9261:1;9258;9251:12;9360:4;9353;9350:1;9346:12;9339:26;9398:4;9395:1;9391:12;9430:4;9427:1;9420:15;9523:16;9516:4;9513:1;9509:12;9502:38;9648:16;9630;9623:4;9620:1;9616:12;9603:62;10448:4;10396:1;10332:4;10314:16;10310:27;10250:1;10193:6;10144:5;10108:400;9862:8;;9859:15;;;9740:786;;-1:-1:-1;;6365:4213:20;;;;;;:::o;2649:763:15:-;2819:4;2812:25;;;;2867:1;2863:13;;;2721;2850:27;;;2925:4;2909:21;;3009:18;;3040:1;2967:4;2956:16;;;3029:13;;;3005:38;;;3363:33;;;;3325:24;3318:32;;2649:763::o;3457:531:16:-;3620:8;3614:4;3607:22;3662:5;3659:1;3655:13;3649:4;3642:27;3707:4;3701;3691:21;3769:1;3762:5;3758:13;3755:1;3751:21;3831:1;3825:8;3878:10;3962:5;3958:1;3955;3951:9;3947:21;3944:1;3940:29;3937:1;3933:37;3930:1;3926:45;3923:1;3916:56;;;;;3457:531;;;:::o;3488:133:2:-;3577:6;3395:9;;3388:17;3395:9;;3388:17;3414:9;;3407:17;3385:40;3414:9;3407:17;3385:40;3599:15;3288:153;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:286:21:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:21;;209:43;;199:71;;266:1;263;256:12;921:423;963:3;1001:5;995:12;1028:6;1023:3;1016:19;1053:1;1063:162;1077:6;1074:1;1071:13;1063:162;;;1139:4;1195:13;;;1191:22;;1185:29;1167:11;;;1163:20;;1156:59;1092:12;1063:162;;;1067:3;1270:1;1263:4;1254:6;1249:3;1245:16;1241:27;1234:38;1333:4;1326:2;1322:7;1317:2;1309:6;1305:15;1301:29;1296:3;1292:39;1288:50;1281:57;;;921:423;;;;:::o;1349:220::-;1498:2;1487:9;1480:21;1461:4;1518:45;1559:2;1548:9;1544:18;1536:6;1518:45;:::i;2025:131::-;-1:-1:-1;;;;;2100:31:21;;2090:42;;2080:70;;2146:1;2143;2136:12;2161:134;2229:20;;2258:31;2229:20;2258:31;:::i;2300:156::-;2366:20;;2426:4;2415:16;;2405:27;;2395:55;;2446:1;2443;2436:12;2461:456;2543:6;2551;2559;2567;2620:3;2608:9;2599:7;2595:23;2591:33;2588:53;;;2637:1;2634;2627:12;2588:53;2676:9;2663:23;2695:31;2720:5;2695:31;:::i;:::-;2745:5;-1:-1:-1;2769:36:21;2801:2;2786:18;;2769:36;:::i;:::-;2759:46;;2824:36;2856:2;2845:9;2841:18;2824:36;:::i;:::-;2461:456;;;;-1:-1:-1;2814:46:21;;2907:2;2892:18;2879:32;;-1:-1:-1;;2461:456:21:o;2922:317::-;2988:6;2996;3049:2;3037:9;3028:7;3024:23;3020:32;3017:52;;;3065:1;3062;3055:12;3017:52;3104:9;3091:23;3123:31;3148:5;3123:31;:::i;:::-;3173:5;-1:-1:-1;3197:36:21;3229:2;3214:18;;3197:36;:::i;:::-;3187:46;;2922:317;;;;;:::o;3244:247::-;3303:6;3356:2;3344:9;3335:7;3331:23;3327:32;3324:52;;;3372:1;3369;3362:12;3324:52;3411:9;3398:23;3430:31;3455:5;3430:31;:::i;3496:163::-;3563:20;;3623:10;3612:22;;3602:33;;3592:61;;3649:1;3646;3639:12;3664:533;3753:6;3761;3769;3777;3785;3838:3;3826:9;3817:7;3813:23;3809:33;3806:53;;;3855:1;3852;3845:12;3806:53;3894:9;3881:23;3913:31;3938:5;3913:31;:::i;:::-;3963:5;-1:-1:-1;3987:36:21;4019:2;4004:18;;3987:36;:::i;:::-;3977:46;;4042:36;4074:2;4063:9;4059:18;4042:36;:::i;:::-;4032:46;;4097:37;4130:2;4119:9;4115:18;4097:37;:::i;:::-;4087:47;;4153:38;4186:3;4175:9;4171:19;4153:38;:::i;:::-;4143:48;;3664:533;;;;;;;;:::o;4202:460::-;4283:6;4291;4299;4307;4360:3;4348:9;4339:7;4335:23;4331:33;4328:53;;;4377:1;4374;4367:12;4328:53;4416:9;4403:23;4435:31;4460:5;4435:31;:::i;:::-;4485:5;-1:-1:-1;4509:36:21;4541:2;4526:18;;4509:36;:::i;:::-;4499:46;;4564:36;4596:2;4585:9;4581:18;4564:36;:::i;:::-;4554:46;;4619:37;4652:2;4641:9;4637:18;4619:37;:::i;:::-;4609:47;;4202:460;;;;;;;:::o;4667:179::-;4734:20;;-1:-1:-1;;;;;4783:38:21;;4773:49;;4763:77;;4836:1;4833;4826:12;4851:460;4932:6;4940;4948;4956;5009:3;4997:9;4988:7;4984:23;4980:33;4977:53;;;5026:1;5023;5016:12;4977:53;5065:9;5052:23;5084:31;5109:5;5084:31;:::i;:::-;5134:5;-1:-1:-1;5158:36:21;5190:2;5175:18;;5158:36;:::i;:::-;5148:46;;5213:36;5245:2;5234:9;5230:18;5213:36;:::i;:::-;5203:46;;5268:37;5301:2;5290:9;5286:18;5268:37;:::i;5316:386::-;5401:6;5454:2;5442:9;5433:7;5429:23;5425:32;5422:52;;;5470:1;5467;5460:12;5422:52;5510:9;5497:23;5543:18;5535:6;5532:30;5529:50;;;5575:1;5572;5565:12;5529:50;5598:22;;5654:3;5636:16;;;5632:26;5629:46;;;5671:1;5668;5661:12;5984:1157;6073:12;;-1:-1:-1;;;;;658:38:21;646:51;;6137:4;6130:5;6126:16;6120:23;6152:47;6193:4;6188:3;6184:14;6170:12;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6152:47;;6247:4;6240:5;6236:16;6230:23;6262:49;6305:4;6300:3;6296:14;6280;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6262:49;;6359:4;6352:5;6348:16;6342:23;6374:49;6417:4;6412:3;6408:14;6392;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6374:49;;6471:4;6464:5;6460:16;6454:23;6486:49;6529:4;6524:3;6520:14;6504;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6486:49;;6583:4;6576:5;6572:16;6566:23;6598:49;6641:4;6636:3;6632:14;6616;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6598:49;;6695:4;6688:5;6684:16;6678:23;6710:49;6753:4;6748:3;6744:14;6728;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6710:49;;6807:4;6800:5;6796:16;6790:23;6822:49;6865:4;6860:3;6856:14;6840;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6822:49;-1:-1:-1;6890:6:21;6933:14;;;6927:21;5965:6;5954:18;6991:12;;;5942:31;7023:6;7066:14;;;7060:21;375:13;;368:21;7122:12;;;356:34;7090:45;305:91;7146:277;7350:3;7335:19;;7363:54;7339:9;7399:6;7363:54;:::i;7428:118::-;7514:5;7507:13;7500:21;7493:5;7490:32;7480:60;;7536:1;7533;7526:12;7551:128;7616:20;;7645:28;7616:20;7645:28;:::i;7684:669::-;7779:6;7787;7795;7803;7811;7819;7872:3;7860:9;7851:7;7847:23;7843:33;7840:53;;;7889:1;7886;7879:12;7840:53;7928:9;7915:23;7947:31;7972:5;7947:31;:::i;:::-;7997:5;-1:-1:-1;8021:36:21;8053:2;8038:18;;8021:36;:::i;:::-;8011:46;;8076:36;8108:2;8097:9;8093:18;8076:36;:::i;:::-;8066:46;;8131:37;8164:2;8153:9;8149:18;8131:37;:::i;:::-;8121:47;;8187:38;8220:3;8209:9;8205:19;8187:38;:::i;:::-;8177:48;;8277:3;8266:9;8262:19;8249:33;8291:30;8313:7;8291:30;:::i;:::-;8340:7;8330:17;;;7684:669;;;;;;;;:::o;8933:184::-;8991:6;9044:2;9032:9;9023:7;9019:23;9015:32;9012:52;;;9060:1;9057;9050:12;9012:52;9083:28;9101:9;9083:28;:::i;9122:367::-;9185:8;9195:6;9249:3;9242:4;9234:6;9230:17;9226:27;9216:55;;9267:1;9264;9257:12;9216:55;-1:-1:-1;9290:20:21;;9333:18;9322:30;;9319:50;;;9365:1;9362;9355:12;9319:50;9402:4;9394:6;9390:17;9378:29;;9462:3;9455:4;9445:6;9442:1;9438:14;9430:6;9426:27;9422:38;9419:47;9416:67;;;9479:1;9476;9469:12;9416:67;9122:367;;;;;:::o;9494:855::-;9612:6;9620;9628;9636;9644;9652;9705:3;9693:9;9684:7;9680:23;9676:33;9673:53;;;9722:1;9719;9712:12;9673:53;9761:9;9748:23;9780:31;9805:5;9780:31;:::i;:::-;9830:5;-1:-1:-1;9854:36:21;9886:2;9871:18;;9854:36;:::i;:::-;9844:46;;9909:36;9941:2;9930:9;9926:18;9909:36;:::i;:::-;9899:46;;9997:2;9986:9;9982:18;9969:32;10010:33;10035:7;10010:33;:::i;:::-;10062:7;-1:-1:-1;10120:3:21;10105:19;;10092:33;10148:18;10137:30;;10134:50;;;10180:1;10177;10170:12;10134:50;10219:70;10281:7;10272:6;10261:9;10257:22;10219:70;:::i;:::-;9494:855;;;;-1:-1:-1;9494:855:21;;-1:-1:-1;9494:855:21;;10308:8;;9494:855;-1:-1:-1;;;9494:855:21:o;10547:712::-;10655:6;10663;10671;10679;10687;10740:3;10728:9;10719:7;10715:23;10711:33;10708:53;;;10757:1;10754;10747:12;10708:53;10796:9;10783:23;10815:31;10840:5;10815:31;:::i;:::-;10865:5;-1:-1:-1;10889:36:21;10921:2;10906:18;;10889:36;:::i;:::-;10879:46;;10944:36;10976:2;10965:9;10961:18;10944:36;:::i;:::-;10934:46;;11031:2;11020:9;11016:18;11003:32;11058:18;11050:6;11047:30;11044:50;;;11090:1;11087;11080:12;11044:50;11129:70;11191:7;11182:6;11171:9;11167:22;11129:70;:::i;:::-;10547:712;;;;-1:-1:-1;10547:712:21;;-1:-1:-1;11218:8:21;;11103:96;10547:712;-1:-1:-1;;;10547:712:21:o;11264:642::-;11429:2;11481:21;;;11551:13;;11454:18;;;11573:22;;;11400:4;;11429:2;11652:15;;;;11626:2;11611:18;;;11400:4;11695:185;11709:6;11706:1;11703:13;11695:185;;;11784:13;;11777:21;11770:29;11758:42;;11855:15;;;;11820:12;;;;11731:1;11724:9;11695:185;;;-1:-1:-1;11897:3:21;;11264:642;-1:-1:-1;;;;;;11264:642:21:o;12020:1259::-;12426:3;12421;12417:13;12409:6;12405:26;12394:9;12387:45;12368:4;12451:2;12489:3;12484:2;12473:9;12469:18;12462:31;12516:46;12557:3;12546:9;12542:19;12534:6;12516:46;:::i;:::-;12610:9;12602:6;12598:22;12593:2;12582:9;12578:18;12571:50;12644:33;12670:6;12662;12644:33;:::i;:::-;12708:2;12693:18;;12686:34;;;-1:-1:-1;;;;;12757:32:21;;12751:3;12736:19;;12729:61;12777:3;12806:19;;12799:35;;;12871:22;;;12865:3;12850:19;;12843:51;12943:13;;12965:22;;;13041:15;;;;-1:-1:-1;13003:15:21;;;;-1:-1:-1;13084:169:21;13098:6;13095:1;13092:13;13084:169;;;13159:13;;13147:26;;13228:15;;;;13193:12;;;;13120:1;13113:9;13084:169;;;-1:-1:-1;13270:3:21;;12020:1259;-1:-1:-1;;;;;;;;;;;;12020:1259:21:o;13284:127::-;13345:10;13340:3;13336:20;13333:1;13326:31;13376:4;13373:1;13366:15;13400:4;13397:1;13390:15;13416:352;13488:2;13482:9;13530:6;13518:19;;13567:18;13552:34;;13588:22;;;13549:62;13546:185;;;13653:10;13648:3;13644:20;13641:1;13634:31;13688:4;13685:1;13678:15;13716:4;13713:1;13706:15;13546:185;13747:2;13740:22;13416:352;:::o;13773:344::-;13840:2;13834:9;13882:3;13870:16;;13916:18;13901:34;;13937:22;;;13898:62;13895:185;;;14002:10;13997:3;13993:20;13990:1;13983:31;14037:4;14034:1;14027:15;14065:4;14062:1;14055:15;14122:159;14189:20;;14249:6;14238:18;;14228:29;;14218:57;;14271:1;14268;14261:12;14286:914;14350:5;14398:6;14386:9;14381:3;14377:19;14373:32;14370:52;;;14418:1;14415;14408:12;14370:52;14440:22;;:::i;:::-;14431:31;;14485:28;14503:9;14485:28;:::i;:::-;14478:5;14471:43;14546:37;14579:2;14568:9;14564:18;14546:37;:::i;:::-;14541:2;14534:5;14530:14;14523:61;14616:37;14649:2;14638:9;14634:18;14616:37;:::i;:::-;14611:2;14604:5;14600:14;14593:61;14686:37;14719:2;14708:9;14704:18;14686:37;:::i;:::-;14681:2;14674:5;14670:14;14663:61;14757:38;14790:3;14779:9;14775:19;14757:38;:::i;:::-;14751:3;14744:5;14740:15;14733:63;14829:38;14862:3;14851:9;14847:19;14829:38;:::i;:::-;14823:3;14816:5;14812:15;14805:63;14901:38;14934:3;14923:9;14919:19;14901:38;:::i;:::-;14895:3;14888:5;14884:15;14877:63;14973:38;15006:3;14995:9;14991:19;14973:38;:::i;:::-;14967:3;14960:5;14956:15;14949:63;15031:3;15066:37;15099:2;15088:9;15084:18;15066:37;:::i;:::-;15050:14;;;15043:61;15123:3;15158:35;15174:18;;;15158:35;:::i;:::-;15142:14;;;15135:59;15146:5;14286:914;-1:-1:-1;;14286:914:21:o;15205:248::-;15299:6;15352:3;15340:9;15331:7;15327:23;15323:33;15320:53;;;15369:1;15366;15359:12;15320:53;15392:55;15439:7;15428:9;15392:55;:::i;15557:1973::-;15638:12;;-1:-1:-1;;;;;11977:31:21;11965:44;;15702:4;15695:5;15691:16;15685:23;15717:46;15757:4;15752:3;15748:14;15734:12;1641:4;1630:16;1618:29;;1574:75;15717:46;;15811:4;15804:5;15800:16;15794:23;15826:48;15868:4;15863:3;15859:14;15843;1641:4;1630:16;1618:29;;1574:75;15826:48;;15922:4;15915:5;15911:16;15905:23;15937:50;15981:4;15976:3;15972:14;15956;-1:-1:-1;;;;;11977:31:21;11965:44;;11911:104;15937:50;;16035:4;16028:5;16024:16;16018:23;16050:49;16093:4;16088:3;16084:14;16068;-1:-1:-1;;;;;658:38:21;646:51;;593:110;16050:49;;16147:4;16140:5;16136:16;16130:23;16162:49;16205:4;16200:3;16196:14;16180;15534:10;15523:22;15511:35;;15458:94;16162:49;;16259:4;16252:5;16248:16;16242:23;16274:49;16317:4;16312:3;16308:14;16292;15534:10;15523:22;15511:35;;15458:94;16274:49;;16371:4;16364:5;16360:16;16354:23;16386:49;16429:4;16424:3;16420:14;16404;15534:10;15523:22;15511:35;;15458:94;16386:49;-1:-1:-1;16454:6:21;16497:14;;;16491:21;15534:10;15523:22;;;16555:12;;;15511:35;;;;16587:6;16630:14;;;16624:21;15523:22;;;16688:12;;;15511:35;16720:6;16763:14;;;16757:21;5965:6;5954:18;16821:12;;;5942:31;16853:6;16897:14;;;16891:21;1641:4;1630:16;16955:12;;;1618:29;16987:6;17031:14;;;17025:21;375:13;368:21;17088:12;;;356:34;17120:6;17164:14;;;17158:21;375:13;368:21;17221:12;;;356:34;17253:6;17295:14;;;17289:21;17275:12;;;17268:43;17330:6;17372:14;;;17366:21;17352:12;;;17345:43;17407:6;17451:14;;;17445:21;-1:-1:-1;;;;;11977:31:21;;17511:12;;;11965:44;17475:49;11911:104;17535:708;17758:2;17810:21;;;17880:13;;17783:18;;;17902:22;;;17729:4;;17758:2;17981:15;;;;17955:2;17940:18;;;17729:4;18024:193;18038:6;18035:1;18032:13;18024:193;;;18087:46;18129:3;18120:6;18114:13;18087:46;:::i;:::-;18192:15;;;;18162:6;18153:16;;;;;18060:1;18053:9;18024:193;;18248:1140;18337:6;18390:3;18378:9;18369:7;18365:23;18361:33;18358:53;;;18407:1;18404;18397:12;18358:53;18433:17;;:::i;:::-;18473:29;18492:9;18473:29;:::i;:::-;18466:5;18459:44;18535:37;18568:2;18557:9;18553:18;18535:37;:::i;:::-;18530:2;18523:5;18519:14;18512:61;18605:37;18638:2;18627:9;18623:18;18605:37;:::i;:::-;18600:2;18593:5;18589:14;18582:61;18675:37;18708:2;18697:9;18693:18;18675:37;:::i;:::-;18670:2;18663:5;18659:14;18652:61;18746:38;18779:3;18768:9;18764:19;18746:38;:::i;:::-;18740:3;18733:5;18729:15;18722:63;18818:38;18851:3;18840:9;18836:19;18818:38;:::i;:::-;18812:3;18805:5;18801:15;18794:63;18890:38;18923:3;18912:9;18908:19;18890:38;:::i;:::-;18884:3;18877:5;18873:15;18866:63;18990:3;18979:9;18975:19;18962:33;18956:3;18949:5;18945:15;18938:58;19015:3;19050:36;19082:2;19071:9;19067:18;19050:36;:::i;:::-;19034:14;;;19027:60;19106:3;19141:38;19160:18;;;19141:38;:::i;:::-;19125:14;;;19118:62;19199:3;19234:36;19251:18;;;19234:36;:::i;:::-;19218:14;;;19211:60;19290:3;19338:18;;;19325:32;19309:14;;;19302:56;;;;-1:-1:-1;19222:5:21;18248:1140;-1:-1:-1;18248:1140:21:o;19393:596::-;19480:6;19488;19496;19504;19512;19565:3;19553:9;19544:7;19540:23;19536:33;19533:53;;;19582:1;19579;19572:12;19533:53;19621:9;19608:23;19640:31;19665:5;19640:31;:::i;:::-;19690:5;-1:-1:-1;19714:36:21;19746:2;19731:18;;19714:36;:::i;:::-;19704:46;;19769:36;19801:2;19790:9;19786:18;19769:36;:::i;:::-;19759:46;;19824:37;19857:2;19846:9;19842:18;19824:37;:::i;:::-;19814:47;;19913:3;19902:9;19898:19;19885:33;19927:30;19949:7;19927:30;:::i;:::-;19976:7;19966:17;;;19393:596;;;;;;;;:::o;20202:460::-;20283:6;20291;20299;20307;20360:3;20348:9;20339:7;20335:23;20331:33;20328:53;;;20377:1;20374;20367:12;20328:53;20416:9;20403:23;20435:31;20460:5;20435:31;:::i;:::-;20485:5;-1:-1:-1;20509:36:21;20541:2;20526:18;;20509:36;:::i;:::-;20499:46;;20564:36;20596:2;20585:9;20581:18;20564:36;:::i;:::-;20554:46;;20619:37;20652:2;20641:9;20637:18;20619:37;:::i;20667:529::-;20749:6;20757;20765;20773;20826:3;20814:9;20805:7;20801:23;20797:33;20794:53;;;20843:1;20840;20833:12;20794:53;20882:9;20869:23;20901:31;20926:5;20901:31;:::i;:::-;20951:5;-1:-1:-1;20975:36:21;21007:2;20992:18;;20975:36;:::i;:::-;20965:46;;21030:36;21062:2;21051:9;21047:18;21030:36;:::i;:::-;21020:46;;21118:2;21107:9;21103:18;21090:32;21131:33;21156:7;21131:33;:::i;:::-;20667:529;;;;-1:-1:-1;20667:529:21;;-1:-1:-1;;20667:529:21:o;21398:387::-;21471:6;21479;21487;21540:2;21528:9;21519:7;21515:23;21511:32;21508:52;;;21556:1;21553;21546:12;21508:52;21595:9;21582:23;21614:31;21639:5;21614:31;:::i;:::-;21664:5;-1:-1:-1;21688:36:21;21720:2;21705:18;;21688:36;:::i;:::-;21678:46;;21743:36;21775:2;21764:9;21760:18;21743:36;:::i;:::-;21733:46;;21398:387;;;;;:::o;21790:250::-;21976:3;21961:19;;21989:45;21965:9;22016:6;21989:45;:::i;22045:523::-;22124:6;22132;22140;22148;22201:3;22189:9;22180:7;22176:23;22172:33;22169:53;;;22218:1;22215;22208:12;22169:53;22257:9;22244:23;22276:31;22301:5;22276:31;:::i;:::-;22326:5;-1:-1:-1;22350:36:21;22382:2;22367:18;;22350:36;:::i;:::-;22340:46;;22405:36;22437:2;22426:9;22422:18;22405:36;:::i;:::-;22395:46;;22493:2;22482:9;22478:18;22465:32;22506:30;22528:7;22506:30;:::i;22573:395::-;22667:6;22720:2;22708:9;22699:7;22695:23;22691:32;22688:52;;;22736:1;22733;22726:12;22688:52;22776:9;22763:23;22809:18;22801:6;22798:30;22795:50;;;22841:1;22838;22831:12;22795:50;22864:22;;22920:3;22902:16;;;22898:26;22895:46;;;22937:1;22934;22927:12;22973:318;23074:6;23082;23135:3;23123:9;23114:7;23110:23;23106:33;23103:53;;;23152:1;23149;23142:12;23103:53;23175:27;23192:9;23175:27;:::i;:::-;23165:37;;23221:64;23277:7;23272:2;23261:9;23257:18;23221:64;:::i;24809:182::-;24866:6;24919:2;24907:9;24898:7;24894:23;24890:32;24887:52;;;24935:1;24932;24925:12;24887:52;24958:27;24975:9;24958:27;:::i;24996:545::-;25089:4;25095:6;25155:11;25142:25;25249:2;25245:7;25234:8;25218:14;25214:29;25210:43;25190:18;25186:68;25176:96;;25268:1;25265;25258:12;25176:96;25295:33;;25347:20;;;-1:-1:-1;25390:18:21;25379:30;;25376:50;;;25422:1;25419;25412:12;25376:50;25455:4;25443:17;;-1:-1:-1;25506:1:21;25502:14;;;25486;25482:35;25472:46;;25469:66;;;25531:1;25528;25521:12;25546:184;25604:6;25657:2;25645:9;25636:7;25632:23;25628:32;25625:52;;;25673:1;25670;25663:12;25625:52;25696:28;25714:9;25696:28;:::i;26361:184::-;26431:6;26484:2;26472:9;26463:7;26459:23;26455:32;26452:52;;;26500:1;26497;26490:12;26452:52;-1:-1:-1;26523:16:21;;26361:184;-1:-1:-1;26361:184:21:o;26550:1637::-;26837:4;26825:17;;;26807:36;;26879:17;;26874:2;26859:18;;26852:45;26924:13;;15534:10;15523:22;26954:2;26939:18;;15511:35;26794:3;26779:19;;27012:2;27000:15;;26994:22;26989:2;26974:18;;26967:50;27064:2;27052:15;;27046:22;-1:-1:-1;;;;;11977:31:21;;27125:3;27110:19;;11965:44;-1:-1:-1;27179:2:21;27167:15;;27161:22;15534:10;15523:22;;27241:3;27226:19;;15511:35;-1:-1:-1;27295:3:21;27283:16;;27277:23;15534:10;15523:22;;27358:3;27343:19;;15511:35;-1:-1:-1;27412:3:21;27400:16;;27394:23;15534:10;15523:22;;27475:3;27460:19;;15511:35;27426:54;27529:3;27521:6;27517:16;27511:23;27553:3;27565:54;27615:2;27604:9;27600:18;27584:14;-1:-1:-1;;;;;11977:31:21;11965:44;;11911:104;27565:54;27668:3;27660:6;27656:16;27650:23;27628:45;;27692:3;27704:51;27751:2;27740:9;27736:18;27720:14;375:13;368:21;356:34;;305:91;27704:51;27780:15;;;27774:22;27815:3;27834:18;;;27827:30;;;;27882:15;;;27876:22;27917:3;27936:18;;;27929:30;;;;27984:15;;;27978:22;28019:3;28038:18;;;28031:30;;;;28104:15;;;28098:22;28092:3;28077:19;;28070:51;28164:15;;;28158:22;28152:3;28137:19;;;28130:51;;;;26550:1637;;-1:-1:-1;;;26550:1637:21:o;28192:127::-;28253:10;28248:3;28244:20;28241:1;28234:31;28284:4;28281:1;28274:15;28308:4;28305:1;28298:15;28324:1680;28609:4;28597:17;;;28579:36;;28651:17;;28646:2;28631:18;;28624:45;28697:13;;-1:-1:-1;;;;;11977:31:21;28727:2;28712:18;;11965:44;28566:3;28551:19;;28778:2;28766:15;;28760:22;-1:-1:-1;;;;;658:38:21;;28838:2;28823:18;;646:51;-1:-1:-1;28891:2:21;28879:15;;28873:22;15534:10;15523:22;;28953:3;28938:19;;15511:35;-1:-1:-1;29007:2:21;28995:15;;28989:22;15534:10;15523:22;;29069:3;29054:19;;15511:35;-1:-1:-1;29123:3:21;29111:16;;29105:23;15534:10;15523:22;;29186:3;29171:19;;15511:35;-1:-1:-1;29240:3:21;29228:16;;29222:23;15534:10;15523:22;;29303:3;29288:19;;15511:35;29254:54;29357:3;29349:6;29345:16;29339:23;29381:3;29393:53;29442:2;29431:9;29427:18;29411:14;5965:6;5954:18;5942:31;;5889:90;29393:53;29483:3;29471:16;;29465:23;29507:3;29526:18;;;29519:30;;;;29586:15;;;29580:22;;-1:-1:-1;29621:3:21;;29633:52;29666:18;;;29580:22;1641:4;1630:16;1618:29;;1574:75;29633:52;29722:15;;29716:22;;-1:-1:-1;29757:3:21;29769:54;29804:18;;;29716:22;-1:-1:-1;;;;;11977:31:21;11965:44;;11911:104;29769:54;29860:15;;;29854:22;1641:4;1630:16;29933:3;29918:19;;1618:29;29981:15;;;29975:22;29969:3;29954:19;;;29947:51;;;;28324:1680;;-1:-1:-1;;;28324:1680:21:o;32244:522::-;32344:6;32339:3;32332:19;32314:3;32370:4;32399:2;32394:3;32390:12;32383:19;;32425:5;32448:1;32458:283;32472:6;32469:1;32466:13;32458:283;;;32549:6;32536:20;32569:33;32594:7;32569:33;:::i;:::-;-1:-1:-1;;;;;32627:33:21;32615:46;;32681:12;;;;32716:15;;;;32657:1;32487:9;32458:283;;;-1:-1:-1;32757:3:21;;32244:522;-1:-1:-1;;;;;32244:522:21:o;32771:453::-;33023:4;33015:6;33011:17;33000:9;32993:36;33065:2;33060;33049:9;33045:18;33038:30;32974:4;33085:73;33154:2;33143:9;33139:18;33131:6;33123;33085:73;:::i;:::-;33077:81;;33206:10;33198:6;33194:23;33189:2;33178:9;33174:18;33167:51;32771:453;;;;;;;:::o;33229:604::-;33532:4;33524:6;33520:17;33509:9;33502:36;33586:4;33578:6;33574:17;33569:2;33558:9;33554:18;33547:45;33628:3;33623:2;33612:9;33608:18;33601:31;33483:4;33649:74;33718:3;33707:9;33703:19;33695:6;33687;33649:74;:::i;:::-;33771:10;33759:23;;;;33754:2;33739:18;;33732:51;-1:-1:-1;33814:3:21;33799:19;33792:35;33641:82;33229:604;-1:-1:-1;;;;33229:604:21:o;33838:355::-;34109:4;34097:17;;34079:36;;34066:3;34051:19;;34124:63;34183:2;34168:18;;34160:6;34124:63;:::i;34198:620::-;34369:3;34400;34447:6;34369:3;34481:310;34495:6;34492:1;34489:13;34481:310;;;34570:6;34557:20;34590:31;34615:5;34590:31;:::i;:::-;-1:-1:-1;;;;;34648:31:21;34634:46;;34703:4;34729:14;;;;34766:15;;;;;34676:1;34510:9;34481:310;;;-1:-1:-1;34807:5:21;;34198:620;-1:-1:-1;;;;;34198:620:21:o;35597:251::-;35667:6;35720:2;35708:9;35699:7;35695:23;35691:32;35688:52;;;35736:1;35733;35726:12;35688:52;35768:9;35762:16;35787:31;35812:5;35787:31;:::i;36132:245::-;36199:6;36252:2;36240:9;36231:7;36227:23;36223:32;36220:52;;;36268:1;36265;36258:12;36220:52;36300:9;36294:16;36319:28;36341:5;36319:28;:::i;36749:521::-;36826:4;36832:6;36892:11;36879:25;36986:2;36982:7;36971:8;36955:14;36951:29;36947:43;36927:18;36923:68;36913:96;;37005:1;37002;36995:12;36913:96;37032:33;;37084:20;;;-1:-1:-1;37127:18:21;37116:30;;37113:50;;;37159:1;37156;37149:12;37113:50;37192:4;37180:17;;-1:-1:-1;37223:14:21;37219:27;;;37209:38;;37206:58;;;37260:1;37257;37250:12

Swarm Source

ipfs://7ebafb7b76188b79b0bde174d599a0d340478ed83ec0a06d25b34aede9727299

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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