ETH Price: $3,134.79 (-4.96%)
Gas: 3 Gwei

Contract

0x000000000000D58696577347F78259bD376F1BEC
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00
Transaction Hash
Method
Block
From
To
Value
Mint200506942024-06-09 0:28:5925 days ago1717892939IN
0x00000000...D376F1BEC
0.01744 ETH0.00049654.51901131
Mint200501362024-06-08 22:36:3526 days ago1717886195IN
0x00000000...D376F1BEC
0.01054 ETH0.000570065.07593857
Mint200067692024-06-02 21:17:4732 days ago1717363067IN
0x00000000...D376F1BEC
0.01744 ETH0.0013208412.02606439
Mint200067662024-06-02 21:17:1132 days ago1717363031IN
0x00000000...D376F1BEC
0.01744 ETH0.0013914712.66770881
Mint200067642024-06-02 21:16:4732 days ago1717363007IN
0x00000000...D376F1BEC
0.01744 ETH0.0014573413.26740072
Mint200067592024-06-02 21:15:4732 days ago1717362947IN
0x00000000...D376F1BEC
0.01744 ETH0.0016423514.95173552
Mint200067562024-06-02 21:15:1132 days ago1717362911IN
0x00000000...D376F1BEC
0.01744 ETH0.0014803613.477003
Mint200067542024-06-02 21:14:4732 days ago1717362887IN
0x00000000...D376F1BEC
0.01744 ETH0.0014327513.04047855
Mint200067502024-06-02 21:13:5932 days ago1717362839IN
0x00000000...D376F1BEC
0.01744 ETH0.001358112.36392163
Mint200067482024-06-02 21:13:3532 days ago1717362815IN
0x00000000...D376F1BEC
0.01744 ETH0.001358312.36575804
Mint200067432024-06-02 21:12:3532 days ago1717362755IN
0x00000000...D376F1BEC
0.01744 ETH0.0014629113.31493698
Mint200067402024-06-02 21:11:5932 days ago1717362719IN
0x00000000...D376F1BEC
0.01744 ETH0.0015202213.84138056
Mint199994612024-06-01 20:48:4733 days ago1717274927IN
0x00000000...D376F1BEC
0.01744 ETH0.00062134.89475179
Mint198868602024-05-17 2:57:2348 days ago1715914643IN
0x00000000...D376F1BEC
0.00404 ETH0.000394423.51088947
Mint198868552024-05-17 2:56:2348 days ago1715914583IN
0x00000000...D376F1BEC
0.00404 ETH0.000392313.49211569
Mint198847412024-05-16 19:51:5949 days ago1715889119IN
0x00000000...D376F1BEC
0.00404 ETH0.000623364.81472858
Mint198646602024-05-14 0:25:2351 days ago1715646323IN
0x00000000...D376F1BEC
0.01744 ETH0.000483543.73477266
Mint198472482024-05-11 14:00:3554 days ago1715436035IN
0x00000000...D376F1BEC
0.01744 ETH0.00072385.59167655
Mint198054652024-05-05 17:45:2360 days ago1714931123IN
0x00000000...D376F1BEC
0.01744 ETH0.000856757.62702247
Mint197410242024-04-26 17:30:3569 days ago1714152635IN
0x00000000...D376F1BEC
0.01744 ETH0.000648645.77300015
Mint197410182024-04-26 17:29:2369 days ago1714152563IN
0x00000000...D376F1BEC
0.01744 ETH0.000707715.46731816
Mint195210162024-03-26 20:37:23100 days ago1711485443IN
0x00000000...D376F1BEC
0.02054 ETH0.0045854735.41396048
Mint194918332024-03-22 18:04:11104 days ago1711130651IN
0x00000000...D376F1BEC
0.01744 ETH0.0027285224.28723249
Mint193146562024-02-26 22:16:47129 days ago1708985807IN
0x00000000...D376F1BEC
0.00216 ETH0.005518342.16825559
Mint192345132024-02-15 16:26:47140 days ago1708014407IN
0x00000000...D376F1BEC
0.02054 ETH0.0046418235.85637218
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To Value
200506942024-06-09 0:28:5925 days ago1717892939
0x00000000...D376F1BEC
0.00054 ETH
200506942024-06-09 0:28:5925 days ago1717892939
0x00000000...D376F1BEC
0.0169 ETH
200501362024-06-08 22:36:3526 days ago1717886195
0x00000000...D376F1BEC
0.00054 ETH
200501362024-06-08 22:36:3526 days ago1717886195
0x00000000...D376F1BEC
0.01 ETH
200067692024-06-02 21:17:4732 days ago1717363067
0x00000000...D376F1BEC
0.00054 ETH
200067692024-06-02 21:17:4732 days ago1717363067
0x00000000...D376F1BEC
0.0169 ETH
200067662024-06-02 21:17:1132 days ago1717363031
0x00000000...D376F1BEC
0.00054 ETH
200067662024-06-02 21:17:1132 days ago1717363031
0x00000000...D376F1BEC
0.0169 ETH
200067642024-06-02 21:16:4732 days ago1717363007
0x00000000...D376F1BEC
0.00054 ETH
200067642024-06-02 21:16:4732 days ago1717363007
0x00000000...D376F1BEC
0.0169 ETH
200067592024-06-02 21:15:4732 days ago1717362947
0x00000000...D376F1BEC
0.00054 ETH
200067592024-06-02 21:15:4732 days ago1717362947
0x00000000...D376F1BEC
0.0169 ETH
200067562024-06-02 21:15:1132 days ago1717362911
0x00000000...D376F1BEC
0.00054 ETH
200067562024-06-02 21:15:1132 days ago1717362911
0x00000000...D376F1BEC
0.0169 ETH
200067542024-06-02 21:14:4732 days ago1717362887
0x00000000...D376F1BEC
0.00054 ETH
200067542024-06-02 21:14:4732 days ago1717362887
0x00000000...D376F1BEC
0.0169 ETH
200067502024-06-02 21:13:5932 days ago1717362839
0x00000000...D376F1BEC
0.00054 ETH
200067502024-06-02 21:13:5932 days ago1717362839
0x00000000...D376F1BEC
0.0169 ETH
200067482024-06-02 21:13:3532 days ago1717362815
0x00000000...D376F1BEC
0.00054 ETH
200067482024-06-02 21:13:3532 days ago1717362815
0x00000000...D376F1BEC
0.0169 ETH
200067432024-06-02 21:12:3532 days ago1717362755
0x00000000...D376F1BEC
0.00054 ETH
200067432024-06-02 21:12:3532 days ago1717362755
0x00000000...D376F1BEC
0.0169 ETH
200067402024-06-02 21:11:5932 days ago1717362719
0x00000000...D376F1BEC
0.00054 ETH
200067402024-06-02 21:11:5932 days ago1717362719
0x00000000...D376F1BEC
0.0169 ETH
199994612024-06-01 20:48:4733 days ago1717274927
0x00000000...D376F1BEC
0.00054 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
LayerrMinter

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 33333 runs

Other Settings:
default evmVersion, BSL 1.1 license
File 1 of 17 : LayerrMinter.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

import {TOKEN_TYPE_NATIVE, TOKEN_TYPE_ERC20, TOKEN_TYPE_ERC721, TOKEN_TYPE_ERC1155} from "./lib/TokenType.sol";
import {BURN_TYPE_CONTRACT_BURN, BURN_TYPE_SEND_TO_DEAD} from "./lib/BurnType.sol";
import {MintOrder, MintParameters, MintToken, BurnToken, PaymentToken} from "./lib/MinterStructs.sol";
import {ReentrancyGuard} from "./lib/ReentrancyGuard.sol";
import {ILayerrMinter} from "./interfaces/ILayerrMinter.sol";
import {ILayerr20} from "./interfaces/ILayerr20.sol";
import {ILayerr721} from "./interfaces/ILayerr721.sol";
import {ILayerr721A} from "./interfaces/ILayerr721A.sol";
import {ILayerr1155} from "./interfaces/ILayerr1155.sol";
import {IERC20} from "./interfaces/IERC20.sol";
import {IERC721} from "./interfaces/IERC721.sol";
import {IERC1155} from "./interfaces/IERC1155.sol";
import {IDelegationRegistry} from "./interfaces/IDelegationRegistry.sol";
import {MerkleProof} from "./lib/MerkleProof.sol";
import {SignatureVerification} from "./lib/SignatureVerification.sol";

/**
 * @title LayerrMinter
 * @author 0xth0mas (Layerr)
 * @notice LayerrMinter is an unowned immutable primative for ERC20, ERC721 and ERC1155
 *         token minting on EVM-based blockchains. Token contract owners build and sign
 *         MintParameters which are used by minters to create MintOrders to mint tokens.
 *         MintParameters define what to mint and conditions for minting.
 *         Conditions for minting include requiring tokens be burned, payment amounts,
 *         start time, end time, additional oracle signature, maximum supply, max per 
 *         wallet and max signature use.
 *         Mint tokens can be ERC20, ERC721 or ERC1155
 *         Burn tokens can be ERC20, ERC721 or ERC1155
 *         Payment tokens can be the chain native token or ERC20
 *         Payment tokens can specify a referral BPS to pay a referral fee at time of mint
 *         LayerrMinter has native support for delegate.cash delegation on allowlist mints
 */
contract LayerrMinter is ILayerrMinter, ReentrancyGuard, SignatureVerification {

    /// @dev mapping of signature digests that have been marked as invalid for a token contract
    mapping(address => mapping(bytes32 => bool)) public signatureInvalid;

    /// @dev counter for number of times a signature has been used, only incremented if signatureMaxUses > 0
    mapping(bytes32 => uint256) public signatureUseCount;

    /// @dev mapping of addresses that are allowed signers for token contracts
    mapping(address => mapping(address => bool)) public contractAllowedSigner;

    /// @dev mapping of addresses that are allowed oracle signers for token contracts
    mapping(address => mapping(address => bool)) public contractAllowedOracle;

    /// @dev mapping of nonces for signers, used to invalidate all previously signed MintParameters
    mapping(address => uint256) public signerNonce;

    /// @dev address to send tokens when burn type is SEND_TO_DEAD
    address private constant DEAD_ADDRESS =
        0x000000000000000000000000000000000000dEaD;

    /// @dev delegate.cash registry for users that want to use a hot wallet for minting an allowlist mint
    IDelegationRegistry delegateCash = IDelegationRegistry(0x00000000000076A84feF008CDAbe6409d2FE638B);

    /**
     * @inheritdoc ILayerrMinter
     */
    function setContractAllowedSigner(address _signer, bool _allowed) external {
        contractAllowedSigner[msg.sender][_signer] = _allowed;

        emit ContractAllowedSignerUpdate(msg.sender, _signer, _allowed);
    }

    /**
     * @inheritdoc ILayerrMinter
     */
    function setContractAllowedOracle(address _oracle, bool _allowed) external {
        contractAllowedOracle[msg.sender][_oracle] = _allowed;

        emit ContractOracleUpdated(msg.sender, _oracle, _allowed);
    }

    /**
     * @inheritdoc ILayerrMinter
     */
    function incrementSignerNonce() external {
        unchecked {
            signerNonce[msg.sender] += uint256(
                keccak256(abi.encodePacked(block.timestamp))
            );
        }

        emit SignerNonceIncremented(msg.sender, signerNonce[msg.sender]);
    }

    /**
     * @inheritdoc ILayerrMinter
     */
    function incrementNonceFor(address signer, bytes calldata signature) external {
        if(!_validateIncrementNonceSigner(signer, signerNonce[signer], signature)) revert InvalidSignatureToIncrementNonce();
        unchecked {
            signerNonce[signer] += uint256(
                keccak256(abi.encodePacked(block.timestamp))
            );
        }

        emit SignerNonceIncremented(signer, signerNonce[signer]);
    }

    /**
     * @inheritdoc ILayerrMinter
     */
    function setSignatureValidity(
        bytes32[] calldata signatureDigests,
        bool invalid
    ) external {
        for (uint256 i; i < signatureDigests.length; ) {
            signatureInvalid[msg.sender][signatureDigests[i]] = invalid;
            emit SignatureValidityUpdated(msg.sender, invalid, signatureDigests[i]);
            unchecked {
                ++i;
            }
        }
    }

    /**
     * @inheritdoc ILayerrMinter
     */
    function mint(
        MintOrder calldata mintOrder
    ) external payable NonReentrant {
        _processMintOrder(msg.sender, mintOrder, 0);

        uint256 remainingBalance = address(this).balance;
        if (remainingBalance > 0) {
            _transferNative(msg.sender, remainingBalance);
        }
    }

    /**
     * @inheritdoc ILayerrMinter
     */
    function mintBatch(
        MintOrder[] calldata mintOrders
    ) external payable NonReentrant {
        uint256 suppliedBurnTokenIdIndex = 0;

        for (uint256 orderIndex; orderIndex < mintOrders.length; ) {
            MintOrder calldata mintOrder = mintOrders[orderIndex];

            suppliedBurnTokenIdIndex = _processMintOrder(msg.sender, mintOrder, suppliedBurnTokenIdIndex);

            unchecked {
                ++orderIndex;
            }
        }

        uint256 remainingBalance = address(this).balance;
        if (remainingBalance > 0) {
            _transferNative(msg.sender, remainingBalance);
        }
    }

    /**
     * @inheritdoc ILayerrMinter
     */
    function mintTo(
        address mintToWallet,
        MintOrder calldata mintOrder,
        uint256 paymentContext
    ) external payable NonReentrant {
        _processMintOrder(mintToWallet, mintOrder, 0);

        uint256 remainingBalance = address(this).balance;
        if (remainingBalance > 0) {
            _transferNative(msg.sender, remainingBalance);
        }
    }

    /**
     * @inheritdoc ILayerrMinter
     */
    function mintBatchTo(
        address mintToWallet,
        MintOrder[] calldata mintOrders,
        uint256 paymentContext
    ) external payable NonReentrant {
        uint256 suppliedBurnTokenIdIndex = 0;

        for (uint256 orderIndex; orderIndex < mintOrders.length; ) {
            MintOrder calldata mintOrder = mintOrders[orderIndex];

            suppliedBurnTokenIdIndex = _processMintOrder(mintToWallet, mintOrder, suppliedBurnTokenIdIndex);

            unchecked {
                ++orderIndex;
            }
        }

        uint256 remainingBalance = address(this).balance;
        if (remainingBalance > 0) {
            _transferNative(msg.sender, remainingBalance);
        }
    }

    /**
     * @notice Validates mint parameters, processes payments and burns, mint tokens
     * @param mintToWallet address that tokens will be minted to
     * @param mintOrder struct containing the mint order details
     * @param suppliedBurnTokenIdIndex the current burn token index before processing the mint order
     * @return suppliedBurnTokenIdIndex the current burn token index after processing the mint order
     */
    function _processMintOrder(
        address mintToWallet, 
        MintOrder calldata mintOrder, 
        uint256 suppliedBurnTokenIdIndex
    ) internal returns (uint256) {
        MintParameters calldata mintParameters = mintOrder.mintParameters;
        bytes calldata mintParametersSignature = mintOrder.mintParametersSignature;
        uint256 quantity = mintOrder.quantity;

        (address mintParametersSigner, bytes32 mintParametersDigest) = _recoverMintParametersSigner(
            mintParameters,
            mintParametersSignature
        );

        (bool useDelegate, address oracleSigner) = _validateMintParameters(mintToWallet, mintOrder, mintParametersSignature, mintParametersSigner, mintParametersDigest);

        _processPayments(
            quantity,
            mintParameters.paymentTokens,
            mintOrder.referrer
        );
        if(mintParameters.burnTokens.length > 0) {
            suppliedBurnTokenIdIndex = _processBurns(
                quantity,
                suppliedBurnTokenIdIndex,
                mintParameters.burnTokens,
                mintOrder.suppliedBurnTokenIds
            );
        }

        address mintCountWallet;
        if(useDelegate) {
            mintCountWallet = mintOrder.vaultWallet;
        } else {
            mintCountWallet = mintToWallet;
        }
        
        _processMints(
            mintParameters.mintTokens,
            mintParametersSigner,
            mintParametersDigest,
            oracleSigner,
            quantity,
            mintCountWallet,
            mintToWallet
        );

        emit MintOrderFulfilled(mintParametersDigest, mintToWallet, quantity);

        return suppliedBurnTokenIdIndex;
    }

    /**
     * @notice Checks the MintParameters for start/end time compliance, signer nonce, allowlist, signature max uses and oracle signature
     * @param mintToWallet address tokens will be minted to
     * @param mintOrder struct containing the mint order details 
     * @param mintParametersSignature EIP712 signature of the MintParameters
     * @param mintParametersSigner recovered signer of the mintParametersSignature
     * @param mintParametersDigest hash digest of the MintParameters
     * @return useDelegate true for allowlist mint that mintToWallet 
     * @return oracleSigner recovered address of the oracle signer if oracle signature is required or address(0) if oracle signature is not required
     */
    function _validateMintParameters(
        address mintToWallet, 
        MintOrder calldata mintOrder, 
        bytes calldata mintParametersSignature, 
        address mintParametersSigner, 
        bytes32 mintParametersDigest
    ) internal returns(bool useDelegate, address oracleSigner) {
        MintParameters calldata mintParameters = mintOrder.mintParameters;
        if (mintParameters.startTime > block.timestamp) {
            revert MintHasNotStarted();
        }
        if (mintParameters.endTime < block.timestamp) {
            revert MintHasEnded();
        }
        if (signerNonce[mintParametersSigner] != mintParameters.nonce) {
            revert SignerNonceInvalid();
        }
        if (mintParameters.merkleRoot != bytes32(0)) {
            if (
                !MerkleProof.verifyCalldata(
                    mintOrder.merkleProof,
                    mintParameters.merkleRoot,
                    keccak256(abi.encodePacked(mintToWallet))
                )
            ) {
                address vaultWallet = mintOrder.vaultWallet;
                if(vaultWallet == address(0)) {
                    revert InvalidMerkleProof();
                } else {
                    // check delegate for all first as it's more likely than delegate for contract, saves 3200 gas
                    if(!delegateCash.checkDelegateForAll(mintToWallet, vaultWallet)) {
                        if(!delegateCash.checkDelegateForContract(mintToWallet, vaultWallet, address(this))) {
                            revert InvalidMerkleProof();
                        }
                    }
                    if (
                        MerkleProof.verifyCalldata(
                            mintOrder.merkleProof,
                            mintParameters.merkleRoot,
                            keccak256(abi.encodePacked(vaultWallet))
                        )
                    ) {
                        useDelegate = true;
                    } else {
                        revert InvalidMerkleProof();
                    }
                }
            }
        }
        
        if (mintParameters.signatureMaxUses != 0) {
            signatureUseCount[mintParametersDigest] += mintOrder.quantity;
            if (signatureUseCount[mintParametersDigest] > mintParameters.signatureMaxUses) {
                revert ExceedsMaxSignatureUsage();
            }
        }

        if(mintParameters.oracleSignatureRequired) {
            oracleSigner = _recoverOracleSigner(mintToWallet, mintParametersSignature, mintOrder.oracleSignature);
            if(oracleSigner == address(0)) {
                revert InvalidOracleSignature();
            }
        }
    }

    /**
     * @notice Iterates over payment tokens and sends payment amounts to recipients. 
     *         If there is a referrer and a payment token has a referralBPS the referral amount is split and sent to the referrer
     *         Payment token types can be native token or ERC20.
     * @param mintOrderQuantity multipier for each payment token
     * @param paymentTokens array of payment tokens for a mint order
     * @param referrer wallet address of user that made the referral for this sale
     */
    function _processPayments(
        uint256 mintOrderQuantity,
        PaymentToken[] calldata paymentTokens,
        address referrer
    ) internal {
        for (uint256 paymentTokenIndex = 0; paymentTokenIndex < paymentTokens.length; ) {
            PaymentToken calldata paymentToken = paymentTokens[paymentTokenIndex];
            uint256 paymentAmount = paymentToken.paymentAmount * mintOrderQuantity;
            uint256 tokenType = paymentToken.tokenType;

            if (tokenType == TOKEN_TYPE_NATIVE) {
                if(referrer == address(0) || paymentToken.referralBPS == 0) {
                    _transferNative(paymentToken.payTo, paymentAmount);
                } else {
                    uint256 referrerPayment = paymentAmount * paymentToken.referralBPS / 10000;
                    _transferNative(referrer, referrerPayment);
                    paymentAmount -= referrerPayment;
                    _transferNative(paymentToken.payTo, paymentAmount);
                }
            } else if (tokenType == TOKEN_TYPE_ERC20) {
                if(referrer == address(0) || paymentToken.referralBPS == 0) {
                    _transferERC20(
                        paymentToken.contractAddress,
                        msg.sender,
                        paymentToken.payTo,
                        paymentAmount
                    );
                } else {
                    uint256 referrerPayment = paymentAmount * paymentToken.referralBPS / 10000;
                    _transferERC20(
                        paymentToken.contractAddress,
                        msg.sender,
                        referrer,
                        referrerPayment
                    );
                    paymentAmount -= referrerPayment;
                    _transferERC20(
                        paymentToken.contractAddress,
                        msg.sender,
                        paymentToken.payTo,
                        paymentAmount
                    );
                }
            } else {
                revert InvalidPaymentTokenType();
            }
            unchecked {
                ++paymentTokenIndex;
            }
        }
    }

    /**
     * @notice Processes burns for a mint order. Burn tokens can be ERC20, ERC721, or ERC1155. Burn types can be
     *         contract burns or send to dead address.
     * @param mintOrderQuantity multiplier for each burn token
     * @param suppliedBurnTokenIdIndex current index for the supplied burn token ids before processing burns
     * @param burnTokens array of burn tokens for a mint order
     * @param suppliedBurnTokenIds array of burn token ids supplied by minter
     * @return suppliedBurnTokenIdIndex current index for the supplied burn token ids after processing burns
     */
    function _processBurns(
        uint256 mintOrderQuantity,
        uint256 suppliedBurnTokenIdIndex,
        BurnToken[] calldata burnTokens,
        uint256[] calldata suppliedBurnTokenIds
    ) internal returns (uint256) {
        for (uint256 burnTokenIndex = 0; burnTokenIndex < burnTokens.length; ) {
            BurnToken calldata burnToken = burnTokens[burnTokenIndex];

            address contractAddress = burnToken.contractAddress;
            uint256 tokenId = burnToken.tokenId;
            bool specificTokenId = burnToken.specificTokenId;
            uint256 burnType = burnToken.burnType;
            uint256 tokenType = burnToken.tokenType;
            uint256 burnAmount = burnToken.burnAmount * mintOrderQuantity;

            if (tokenType == TOKEN_TYPE_ERC1155) {
                uint256 burnTokenEnd = burnTokenIndex;
                for (; burnTokenEnd < burnTokens.length; ) {
                    if (burnTokens[burnTokenEnd].contractAddress != contractAddress) {
                        break;
                    }
                    unchecked {
                        ++burnTokenEnd;
                    }
                }
                unchecked { --burnTokenEnd; }
                if (burnTokenEnd == burnTokenIndex) {
                    if (specificTokenId) {
                        if (tokenId != suppliedBurnTokenIds[suppliedBurnTokenIdIndex]) {
                            revert InvalidBurnTokenId();
                        }
                    }
                    if (burnType == BURN_TYPE_CONTRACT_BURN) {
                        ILayerr1155(contractAddress).burnTokenId(
                            msg.sender,
                            suppliedBurnTokenIds[suppliedBurnTokenIdIndex],
                            burnAmount
                        );
                    } else if (burnType == BURN_TYPE_SEND_TO_DEAD) {
                        IERC1155(contractAddress).safeTransferFrom(
                            msg.sender,
                            DEAD_ADDRESS,
                            suppliedBurnTokenIds[suppliedBurnTokenIdIndex],
                            burnAmount,
                            ""
                        );
                    } else {
                        revert InvalidBurnType();
                    }
                    unchecked {
                        ++suppliedBurnTokenIdIndex;
                    }
                } else {
                    unchecked {
                        ++burnTokenEnd;
                    }
                    uint256[] memory burnTokenIds = new uint256[]((burnTokenEnd - burnTokenIndex));
                    uint256[] memory burnTokenAmounts = new uint256[]((burnTokenEnd - burnTokenIndex));
                    for (uint256 arrayIndex = 0; burnTokenIndex < burnTokenEnd; ) {
                        burnToken = burnTokens[burnTokenIndex];
                        specificTokenId = burnToken.specificTokenId;
                        tokenId = burnToken.tokenId;
                        burnAmount = burnToken.burnAmount * mintOrderQuantity;

                        if (specificTokenId) {
                            if (tokenId != suppliedBurnTokenIds[suppliedBurnTokenIdIndex]) {
                                revert InvalidBurnTokenId();
                            }
                        }

                        burnTokenIds[arrayIndex] = suppliedBurnTokenIds[suppliedBurnTokenIdIndex];
                        burnTokenAmounts[arrayIndex] = burnAmount;
                        unchecked {
                            ++burnTokenIndex;
                            ++arrayIndex;
                            ++suppliedBurnTokenIdIndex;
                        }
                    }
                    unchecked {
                        --burnTokenIndex;
                    }
                    if (burnType == BURN_TYPE_CONTRACT_BURN) {
                        ILayerr1155(contractAddress).burnBatchTokenIds(
                            msg.sender,
                            burnTokenIds,
                            burnTokenAmounts
                        );
                    } else if (burnType == BURN_TYPE_SEND_TO_DEAD) {
                        IERC1155(contractAddress).safeBatchTransferFrom(
                            msg.sender,
                            DEAD_ADDRESS,
                            burnTokenIds,
                            burnTokenAmounts,
                            ""
                        );
                    } else {
                        revert InvalidBurnType();
                    }
                }
            } else if (tokenType == TOKEN_TYPE_ERC721) {
                if (burnType == BURN_TYPE_SEND_TO_DEAD) {
                    if (burnAmount > 1) {
                        if (specificTokenId) {
                            revert CannotBurnMultipleERC721WithSameId();
                        }
                        for (uint256 burnCounter = 0; burnCounter < burnAmount; ) {
                            IERC721(contractAddress).transferFrom(
                                msg.sender,
                                DEAD_ADDRESS,
                                suppliedBurnTokenIds[suppliedBurnTokenIdIndex]
                            );
                            unchecked {
                                ++burnCounter;
                                ++suppliedBurnTokenIdIndex;
                            }
                        }
                    } else {
                        if (specificTokenId) {
                            if (tokenId != suppliedBurnTokenIds[suppliedBurnTokenIdIndex]) {
                                revert InvalidBurnTokenId();
                            }
                        }
                        IERC721(contractAddress).transferFrom(
                            msg.sender,
                            DEAD_ADDRESS,
                            suppliedBurnTokenIds[suppliedBurnTokenIdIndex]
                        );
                        unchecked {
                            ++suppliedBurnTokenIdIndex;
                        }
                    }
                } else if (burnType == BURN_TYPE_CONTRACT_BURN) {
                    if (burnAmount > 1) {
                        if (specificTokenId) {
                            revert CannotBurnMultipleERC721WithSameId();
                        }
                        uint256[] memory burnTokenIds = new uint256[](burnAmount);
                        for (uint256 arrayIndex = 0; arrayIndex < burnAmount;) {
                            burnTokenIds[arrayIndex] = suppliedBurnTokenIds[suppliedBurnTokenIdIndex];
                            unchecked {
                                ++arrayIndex;
                                ++suppliedBurnTokenIdIndex;
                            }
                        }
                        ILayerr721(contractAddress).burnBatchTokenIds(msg.sender, burnTokenIds);
                    } else {
                        if (specificTokenId) {
                            if (tokenId != suppliedBurnTokenIds[suppliedBurnTokenIdIndex]) {
                                revert InvalidBurnTokenId();
                            }
                        }
                        ILayerr721(contractAddress).burnTokenId(
                            msg.sender,
                            suppliedBurnTokenIds[suppliedBurnTokenIdIndex]
                        );
                        unchecked {
                            ++suppliedBurnTokenIdIndex;
                        }
                    }
                } else {
                    revert InvalidBurnType();
                }
            } else if (tokenType == TOKEN_TYPE_ERC20) {
                if (burnType == BURN_TYPE_SEND_TO_DEAD) {
                    _transferERC20(
                        contractAddress,
                        msg.sender,
                        DEAD_ADDRESS,
                        burnAmount
                    );
                } else if (burnType == BURN_TYPE_CONTRACT_BURN) {
                    ILayerr20(contractAddress).burn(msg.sender, burnAmount);
                } else {
                    revert InvalidBurnType();
                }
            } else {
                revert InvalidBurnTokenType();
            }
            unchecked {
                ++burnTokenIndex;
            }
        }

        return suppliedBurnTokenIdIndex;
    }

    /**
     * @notice Processes mints for a mint order. Token types can be ERC20, ERC721, or ERC1155. 
     * @param mintTokens array of mint tokens from the mint order
     * @param mintParametersSigner recovered address from the mint parameters signature
     * @param mintParametersDigest hash digest of the supplied mint parameters
     * @param oracleSigner recovered address of the oracle signer if oracle signature required was true, address(0) otherwise
     * @param mintOrderQuantity multiplier for each mint token
     * @param mintCountWallet wallet address that will be used for checking max per wallet mint conditions
     * @param mintToWallet wallet address that tokens will be minted to
     */
    function _processMints(
        MintToken[] calldata mintTokens,
        address mintParametersSigner,
        bytes32 mintParametersDigest,
        address oracleSigner,
        uint256 mintOrderQuantity,
        address mintCountWallet,
        address mintToWallet
    ) internal {
        uint256 mintTokenIndex;
        uint256 mintTokensLength = mintTokens.length;
        for ( ; mintTokenIndex < mintTokensLength; ) {
            MintToken calldata mintToken = mintTokens[mintTokenIndex];

            address contractAddress = mintToken.contractAddress;
            _checkContractSigners(contractAddress, mintParametersSigner, mintParametersDigest, oracleSigner);

            uint256 tokenId = mintToken.tokenId;
            uint256 maxSupply = mintToken.maxSupply;
            uint256 maxMintPerWallet = mintToken.maxMintPerWallet;
            bool specificTokenId = mintToken.specificTokenId;
            uint256 mintAmount = mintToken.mintAmount * mintOrderQuantity;
            uint256 tokenType = mintToken.tokenType;

            if (tokenType == TOKEN_TYPE_ERC1155) {
                uint256 mintTokenEnd = mintTokenIndex;
                for (; mintTokenEnd < mintTokensLength; ) {
                    if (mintTokens[mintTokenEnd].contractAddress != contractAddress) {
                        break;
                    }
                    unchecked {
                        ++mintTokenEnd;
                    }
                }
                unchecked { --mintTokenEnd; }
                if (mintTokenEnd == mintTokenIndex) {
                    _checkERC1155MintQuantities(contractAddress, tokenId, maxSupply, maxMintPerWallet, mintCountWallet, mintAmount);

                    ILayerr1155(contractAddress).mintTokenId(
                        mintCountWallet,
                        mintToWallet,
                        tokenId,
                        mintAmount
                    );
                } else {
                    unchecked {
                        ++mintTokenEnd;
                    }
                    uint256[] memory mintTokenIds = new uint256[]((mintTokenEnd - mintTokenIndex));
                    uint256[] memory mintTokenAmounts = new uint256[]((mintTokenEnd - mintTokenIndex));
                    for (uint256 arrayIndex = 0; mintTokenIndex < mintTokenEnd; ) {
                        mintToken = mintTokens[mintTokenIndex];
                        maxSupply = mintToken.maxSupply;
                        maxMintPerWallet = mintToken.maxMintPerWallet;
                        tokenId = mintToken.tokenId;
                        mintAmount = mintToken.mintAmount * mintOrderQuantity;

                        _checkERC1155MintQuantities(contractAddress, tokenId, maxSupply, maxMintPerWallet, mintCountWallet, mintAmount);

                        mintTokenIds[arrayIndex] = tokenId;
                        mintTokenAmounts[arrayIndex] = mintAmount;
                        unchecked {
                            ++mintTokenIndex;
                            ++arrayIndex;
                        }
                    }
                    unchecked {
                        --mintTokenIndex;
                    }
                    ILayerr1155(contractAddress)
                        .mintBatchTokenIds(
                            mintCountWallet,
                            mintToWallet,
                            mintTokenIds,
                            mintTokenAmounts
                        );
                }
            } else if (tokenType == TOKEN_TYPE_ERC721) {
                _checkERC721MintQuantities(contractAddress, maxSupply, maxMintPerWallet, mintCountWallet, mintAmount);

                if (!specificTokenId || mintAmount > 1) {
                    if (specificTokenId) {
                        revert CannotMintMultipleERC721WithSameId();
                    }
                    ILayerr721A(contractAddress).mintSequential(mintCountWallet, mintToWallet, mintAmount);
                } else {
                    ILayerr721(contractAddress).mintTokenId(mintCountWallet, mintToWallet, tokenId);
                }
            } else if (tokenType == TOKEN_TYPE_ERC20) {
                _checkERC20MintQuantities(contractAddress, maxSupply, maxMintPerWallet, mintCountWallet, mintAmount);
                ILayerr20(contractAddress).mint(mintCountWallet, mintToWallet, mintAmount);
            } else {
                revert InvalidMintTokenType();
            }
            unchecked {
                ++mintTokenIndex;
            }
        }
    }

    /**
     * @notice Checks the mint parameters and oracle signers to ensure they are authorized for the token contract.
     *         Checks that the mint parameters signature digest has not been marked as invalid.
     * @param contractAddress token contract to check signers for
     * @param mintParametersSigner recovered signer for the mint parameters
     * @param mintParametersDigest hash digest of the supplied mint parameters 
     * @param oracleSigner recovered oracle signer if oracle signature is required by mint parameters
     */
    function _checkContractSigners(address contractAddress, address mintParametersSigner, bytes32 mintParametersDigest, address oracleSigner) internal view {
        if (!contractAllowedSigner[contractAddress][mintParametersSigner]) {
            revert NotAllowedSigner();
        }
        if (signatureInvalid[contractAddress][mintParametersDigest]) {
            revert SignatureInvalid();
        }
        if(oracleSigner != address(0)) {
            if(!contractAllowedOracle[contractAddress][oracleSigner]) {
                revert InvalidOracleSignature();
            }
        }
    }

    /**
     * @notice Calls the token contract to get total minted and minted by wallet, checks against mint parameters max supply and max per wallet
     * @param contractAddress token contract to check mint counts for
     * @param tokenId id of the token to check
     * @param maxSupply maximum supply for a token defined in mint parameters
     * @param maxMintPerWallet maximum per wallet for a token defined in mint parameters
     * @param mintCountWallet wallet to check for minted amount
     * @param mintAmount the amount that will be minted
     */
    function _checkERC1155MintQuantities(address contractAddress, uint256 tokenId, uint256 maxSupply, uint256 maxMintPerWallet, address mintCountWallet, uint256 mintAmount) internal view {
        if(maxSupply != 0 || maxMintPerWallet != 0) {
            (uint256 totalMinted, uint256 minterMinted) = ILayerr1155(contractAddress).totalMintedCollectionAndMinter(mintCountWallet, tokenId);
            if (maxSupply != 0) {
                if (totalMinted + mintAmount > maxSupply) {
                    revert MintExceedsMaxSupply();
                }
            }
            if (maxMintPerWallet != 0) {
                if (minterMinted + mintAmount > maxMintPerWallet) {
                    revert MintExceedsMaxPerWallet();
                }
            }
        }
    }


    /**
     * @notice Calls the token contract to get total minted and minted by wallet, checks against mint parameters max supply and max per wallet
     * @param contractAddress token contract to check mint counts for
     * @param maxSupply maximum supply for a token defined in mint parameters
     * @param maxMintPerWallet maximum per wallet for a token defined in mint parameters
     * @param mintCountWallet wallet to check for minted amount
     * @param mintAmount the amount that will be minted
     */
    function _checkERC721MintQuantities(address contractAddress, uint256 maxSupply, uint256 maxMintPerWallet, address mintCountWallet, uint256 mintAmount) internal view {
        if(maxSupply != 0 || maxMintPerWallet != 0) {
            (uint256 totalMinted, uint256 minterMinted) = ILayerr721(contractAddress).totalMintedCollectionAndMinter(mintCountWallet);
            if (maxSupply != 0) {
                if (totalMinted + mintAmount > maxSupply) {
                    revert MintExceedsMaxSupply();
                }
            }
            if (maxMintPerWallet != 0) {
                if (minterMinted + mintAmount > maxMintPerWallet) {
                    revert MintExceedsMaxPerWallet();
                }
            }
        }
    }


    /**
     * @notice Calls the token contract to get total minted and minted by wallet, checks against mint parameters max supply and max per wallet
     * @param contractAddress token contract to check mint counts for
     * @param maxSupply maximum supply for a token defined in mint parameters
     * @param maxMintPerWallet maximum per wallet for a token defined in mint parameters
     * @param mintCountWallet wallet to check for minted amount
     * @param mintAmount the amount that will be minted
     */
    function _checkERC20MintQuantities(address contractAddress, uint256 maxSupply, uint256 maxMintPerWallet, address mintCountWallet, uint256 mintAmount) internal view {
        if(maxSupply != 0 || maxMintPerWallet != 0) {
            (uint256 totalMinted, uint256 minterMinted) = ILayerr20(contractAddress).totalMintedTokenAndMinter(mintCountWallet);
            if (maxSupply != 0) {
                if (totalMinted + mintAmount > maxSupply) {
                    revert MintExceedsMaxSupply();
                }
            }
            if (maxMintPerWallet != 0) {
                if (minterMinted + mintAmount > maxMintPerWallet) {
                    revert MintExceedsMaxPerWallet();
                }
            }
        }
    }

    /**
     * @notice Transfers `amount` of native token to `to` address. Reverts if the transfer fails.
     * @param to address to send native token to
     * @param amount amount of native token to send
     */
    function _transferNative(address to, uint256 amount) internal {
        (bool sent, ) = payable(to).call{value: amount}("");
        if (!sent) {
            if(address(this).balance < amount) {
                revert InsufficientPayment();
            } else {
                revert PaymentFailed();
            }
        }
    }

    /**
     * @notice Transfers `amount` of ERC20 token from `from` address to `to` address.
     * @param contractAddress ERC20 token address
     * @param from address to transfer ERC20 tokens from
     * @param to address to send ERC20 tokens to
     * @param amount amount of ERC20 tokens to send
     */
    function _transferERC20(
        address contractAddress,
        address from,
        address to,
        uint256 amount
    ) internal {
        IERC20(contractAddress).transferFrom(from, to, amount);
    }
}

File 2 of 17 : IDelegationRegistry.sol
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.17;

/**
 * @title An immutable registry contract to be deployed as a standalone primitive
 * @dev See EIP-5639, new project launches can read previous cold wallet -> hot wallet delegations
 * from here and integrate those permissions into their flow
 */
interface IDelegationRegistry {
    /// @notice Delegation type
    enum DelegationType {
        NONE,
        ALL,
        CONTRACT,
        TOKEN
    }

    /// @notice Info about a single delegation, used for onchain enumeration
    struct DelegationInfo {
        DelegationType type_;
        address vault;
        address delegate;
        address contract_;
        uint256 tokenId;
    }

    /// @notice Info about a single contract-level delegation
    struct ContractDelegation {
        address contract_;
        address delegate;
    }

    /// @notice Info about a single token-level delegation
    struct TokenDelegation {
        address contract_;
        uint256 tokenId;
        address delegate;
    }

    /// @notice Emitted when a user delegates their entire wallet
    event DelegateForAll(address vault, address delegate, bool value);

    /// @notice Emitted when a user delegates a specific contract
    event DelegateForContract(address vault, address delegate, address contract_, bool value);

    /// @notice Emitted when a user delegates a specific token
    event DelegateForToken(address vault, address delegate, address contract_, uint256 tokenId, bool value);

    /// @notice Emitted when a user revokes all delegations
    event RevokeAllDelegates(address vault);

    /// @notice Emitted when a user revoes all delegations for a given delegate
    event RevokeDelegate(address vault, address delegate);

    /**
     * -----------  WRITE -----------
     */

    /**
     * @notice Allow the delegate to act on your behalf for all contracts
     * @param delegate The hotwallet to act on your behalf
     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
     */
    function delegateForAll(address delegate, bool value) external;

    /**
     * @notice Allow the delegate to act on your behalf for a specific contract
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you're delegating
     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
     */
    function delegateForContract(address delegate, address contract_, bool value) external;

    /**
     * @notice Allow the delegate to act on your behalf for a specific token
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you're delegating
     * @param tokenId The token id for the token you're delegating
     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
     */
    function delegateForToken(address delegate, address contract_, uint256 tokenId, bool value) external;

    /**
     * @notice Revoke all delegates
     */
    function revokeAllDelegates() external;

    /**
     * @notice Revoke a specific delegate for all their permissions
     * @param delegate The hotwallet to revoke
     */
    function revokeDelegate(address delegate) external;

    /**
     * @notice Remove yourself as a delegate for a specific vault
     * @param vault The vault which delegated to the msg.sender, and should be removed
     */
    function revokeSelf(address vault) external;

    /**
     * -----------  READ -----------
     */

    /**
     * @notice Returns all active delegations a given delegate is able to claim on behalf of
     * @param delegate The delegate that you would like to retrieve delegations for
     * @return info Array of DelegationInfo structs
     */
    function getDelegationsByDelegate(address delegate) external view returns (DelegationInfo[] memory);

    /**
     * @notice Returns an array of wallet-level delegates for a given vault
     * @param vault The cold wallet who issued the delegation
     * @return addresses Array of wallet-level delegates for a given vault
     */
    function getDelegatesForAll(address vault) external view returns (address[] memory);

    /**
     * @notice Returns an array of contract-level delegates for a given vault and contract
     * @param vault The cold wallet who issued the delegation
     * @param contract_ The address for the contract you're delegating
     * @return addresses Array of contract-level delegates for a given vault and contract
     */
    function getDelegatesForContract(address vault, address contract_) external view returns (address[] memory);

    /**
     * @notice Returns an array of contract-level delegates for a given vault's token
     * @param vault The cold wallet who issued the delegation
     * @param contract_ The address for the contract holding the token
     * @param tokenId The token id for the token you're delegating
     * @return addresses Array of contract-level delegates for a given vault's token
     */
    function getDelegatesForToken(address vault, address contract_, uint256 tokenId)
        external
        view
        returns (address[] memory);

    /**
     * @notice Returns all contract-level delegations for a given vault
     * @param vault The cold wallet who issued the delegations
     * @return delegations Array of ContractDelegation structs
     */
    function getContractLevelDelegations(address vault)
        external
        view
        returns (ContractDelegation[] memory delegations);

    /**
     * @notice Returns all token-level delegations for a given vault
     * @param vault The cold wallet who issued the delegations
     * @return delegations Array of TokenDelegation structs
     */
    function getTokenLevelDelegations(address vault) external view returns (TokenDelegation[] memory delegations);

    /**
     * @notice Returns true if the address is delegated to act on the entire vault
     * @param delegate The hotwallet to act on your behalf
     * @param vault The cold wallet who issued the delegation
     */
    function checkDelegateForAll(address delegate, address vault) external view returns (bool);

    /**
     * @notice Returns true if the address is delegated to act on your behalf for a token contract or an entire vault
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you're delegating
     * @param vault The cold wallet who issued the delegation
     */
    function checkDelegateForContract(address delegate, address vault, address contract_)
        external
        view
        returns (bool);

    /**
     * @notice Returns true if the address is delegated to act on your behalf for a specific token, the token's contract or an entire vault
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you're delegating
     * @param tokenId The token id for the token you're delegating
     * @param vault The cold wallet who issued the delegation
     */
    function checkDelegateForToken(address delegate, address vault, address contract_, uint256 tokenId)
        external
        view
        returns (bool);
}

File 3 of 17 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.0;

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155 {
    /**
     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 id,
        uint256 value
    );

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(
        address indexed account,
        address indexed operator,
        bool approved
    );

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the amount of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(
        address account,
        uint256 id
    ) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(
        address[] calldata accounts,
        uint256[] calldata ids
    ) external view returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(
        address account,
        address operator
    ) external view returns (bool);

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external;
}

File 4 of 17 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(
        address owner,
        address spender
    ) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 5 of 17 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

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

    /**
     * @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 have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

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

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

File 6 of 17 : ILayerr1155.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title ILayerr1155
 * @author 0xth0mas (Layerr)
 * @notice ILayerr1155 interface defines functions required in an ERC1155 token contract to callable by the LayerrMinter contract.
 */
interface ILayerr1155 {

    /**
     * @notice Mints tokens to the recipients, each recipient gets the corresponding tokenId in the `tokenIds` array
     * @dev This function should be protected by a role so that it is not callable by any address
     * @dev `recipients`, `tokenIds` and `amounts` arrays must be equal length, each recipient will receive the corresponding 
     *      tokenId and amount from the `tokenIds` and `amounts` arrays
     * @param recipients addresses to airdrop tokens to
     * @param tokenIds ids of tokens to be airdropped to recipients
     * @param amounts amounts of tokens to be airdropped to recipients
     */
    function airdrop(address[] calldata recipients, uint256[] calldata tokenIds, uint256[] calldata amounts) external;

    /**
     * @notice Mints `amount` of `tokenId` to `to`.
     * @dev `minter` and `to` may be the same address but are passed as two separate parameters to properly account for
     *      allowlist mints where a minter is using a delegated wallet to mint
     * @param minter address that the mint count will be credited to
     * @param to address that will receive the tokens
     * @param tokenId id of the token to mint
     * @param amount amount of token to mint
     */
    function mintTokenId(address minter, address to, uint256 tokenId, uint256 amount) external;

    /**
     * @notice Mints `amount` of `tokenId` to `to`.
     * @dev `minter` and `to` may be the same address but are passed as two separate parameters to properly account for
     *      allowlist mints where a minter is using a delegated wallet to mint
     * @param minter address that the mint count will be credited to
     * @param to address that will receive the tokens
     * @param tokenIds array of ids to mint
     * @param amounts array of amounts to mint
     */
    function mintBatchTokenIds(
        address minter,
        address to,
        uint256[] calldata tokenIds,
        uint256[] calldata amounts
    ) external;

    /**
     * @notice Burns `tokenId` from `from` address
     * @dev This function should check that the caller has permission to burn tokens on behalf of `from`
     * @param from address to burn the tokenId from
     * @param tokenId id of token to be burned
     * @param amount amount of `tokenId` to burn from `from`
     */
    function burnTokenId(
        address from,
        uint256 tokenId,
        uint256 amount
    ) external;

    /**
     * @notice Burns `tokenId` from `from` address
     * @dev This function should check that the caller has permission to burn tokens on behalf of `from`
     * @param from address to burn the tokenId from
     * @param tokenIds array of token ids to be burned
     * @param amounts array of amounts to burn from `from`
     */
    function burnBatchTokenIds(
        address from,
        uint256[] calldata tokenIds,
        uint256[] calldata amounts
    ) external;

    /**
     * @notice Emits URI event for tokens provided
     * @param tokenIds array of token ids to emit MetadataUpdate event for
     */
    function updateMetadataSpecificTokens(uint256[] calldata tokenIds) external;

    /**
     * @notice Returns the total supply of ERC1155 tokens in circulation for given `id`.
     * @param id the token id to check total supply of
     */
    function totalSupply(uint256 id) external view returns (uint256);

    /**
     * @notice Returns the total number of tokens minted for the contract and the number of tokens minted by the `minter`
     * @param minter address to check for number of tokens minted
     * @param id the token id to check number of tokens minted for
     * @return totalMinted total number of ERC1155 tokens for given `id` minted since token launch
     * @return minterMinted total number of ERC1155 tokens for given `id` minted by the `minter`
     */
    function totalMintedCollectionAndMinter(address minter, uint256 id) external view returns(uint256 totalMinted, uint256 minterMinted);
}

File 7 of 17 : ILayerr20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title ILayerr20
 * @author 0xth0mas (Layerr)
 * @notice ILayerr20 interface defines functions required in an ERC20 token contract to callable by the LayerrMinter contract.
 */
interface ILayerr20 {
    /// @dev Thrown when two or more sets of arrays are supplied that require equal lengths but differ in length.
    error ArrayLengthMismatch();

    /**
     * @notice Mints tokens to the recipients in amounts specified
     * @dev This function should be protected by a role so that it is not callable by any address
     * @param recipients addresses to airdrop tokens to
     * @param amounts amount of tokens to airdrop to recipients
     */
    function airdrop(address[] calldata recipients, uint256[] calldata amounts) external;

    /**
     * @notice Mints `amount` of ERC20 tokens to the `to` address
     * @dev `minter` and `to` may be the same address but are passed as two separate parameters to properly account for
     *      allowlist mints where a minter is using a delegated wallet to mint
     * @param minter address that the minted amount will be credited to
     * @param to address that will receive the tokens being minted
     * @param amount amount of tokens being minted
     */
    function mint(address minter, address to, uint256 amount) external;

    /**
     * @notice Burns `amount` of ERC20 tokens from the `from` address
     * @dev This function should check that the caller has a sufficient spend allowance to burn these tokens
     * @param from address that the tokens will be burned from
     * @param amount amount of tokens to be burned
     */
    function burn(address from, uint256 amount) external;

    /**
     * @notice Returns the total supply of ERC20 tokens in circulation.
     */
    function totalSupply() external view returns(uint256);

    /**
     * @notice Returns the total number of tokens minted for the contract and the number of tokens minted by the `minter`
     * @param minter address to check for number of tokens minted
     * @return totalMinted total number of ERC20 tokens minted since token launch
     * @return minterMinted total number of ERC20 tokens minted by the `minter`
     */
    function totalMintedTokenAndMinter(address minter) external view returns(uint256 totalMinted, uint256 minterMinted);
}

File 8 of 17 : ILayerr721.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title ILayerr721
 * @author 0xth0mas (Layerr)
 * @notice ILayerr721 interface defines functions required in an ERC721 token contract to callable by the LayerrMinter contract.
 * @dev ILayerr721 should be used for non-sequential token minting.
 */
interface ILayerr721 {
    /// @dev Thrown when two or more sets of arrays are supplied that require equal lengths but differ in length.
    error ArrayLengthMismatch();

    /**
     * @notice Mints tokens to the recipients, each recipient gets the corresponding tokenId in the `tokenIds` array
     * @dev This function should be protected by a role so that it is not callable by any address
     * @param recipients addresses to airdrop tokens to
     * @param tokenIds ids of tokens to be airdropped to recipients
     */
    function airdrop(address[] calldata recipients, uint256[] calldata tokenIds) external;

    /**
     * @notice Mints `tokenId` to `to`.
     * @dev `minter` and `to` may be the same address but are passed as two separate parameters to properly account for
     *      allowlist mints where a minter is using a delegated wallet to mint
     * @param minter address that the mint count will be credited to
     * @param to address that will receive the token
     * @param tokenId the id of the token to mint
     */
    function mintTokenId(address minter, address to, uint256 tokenId) external;

    /**
     * @notice Mints `tokenIds` to `to`.
     * @dev `minter` and `to` may be the same address but are passed as two separate parameters to properly account for
     *      allowlist mints where a minter is using a delegated wallet to mint
     * @param minter address that the mint count will be credited to
     * @param to address that will receive the tokens
     * @param tokenIds the ids of tokens to mint
     */
    function mintBatchTokenIds(
        address minter,
        address to,
        uint256[] calldata tokenIds
    ) external;

    /**
     * @notice Burns `tokenId` from `from` address
     * @dev This function should check that the caller has permission to burn tokens on behalf of `from`
     * @param from address to burn the tokenId from
     * @param tokenId id of token to be burned
     */
    function burnTokenId(address from, uint256 tokenId) external;

    /**
     * @notice Burns `tokenIds` from `from` address
     * @dev This function should check that the caller has permission to burn tokens on behalf of `from`
     * @param from address to burn the tokenIds from
     * @param tokenIds ids of tokens to be burned
     */
    function burnBatchTokenIds(
        address from,
        uint256[] calldata tokenIds
    ) external;

    /**
     * @notice Emits ERC-4906 BatchMetadataUpdate event for all tokens
     */
    function updateMetadataAllTokens() external;

    /**
     * @notice Emits ERC-4906 MetadataUpdate event for tokens provided
     * @param tokenIds array of token ids to emit MetadataUpdate event for
     */
    function updateMetadataSpecificTokens(uint256[] calldata tokenIds) external;

    /**
     * @notice Returns the total supply of ERC721 tokens in circulation.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @notice Returns the total number of tokens minted for the contract and the number of tokens minted by the `minter`
     * @param minter address to check for number of tokens minted
     * @return totalMinted total number of ERC721 tokens minted since token launch
     * @return minterMinted total number of ERC721 tokens minted by the `minter`
     */
    function totalMintedCollectionAndMinter(address minter) external view returns(uint256 totalMinted, uint256 minterMinted);
}

File 9 of 17 : ILayerr721A.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title ILayerr721A
 * @author 0xth0mas (Layerr)
 * @notice ILayerr721A interface defines functions required in an ERC721A token contract to callable by the LayerrMinter contract.
 * @dev ILayerr721A should be used for sequential token minting.
 */
interface ILayerr721A {
    /// @dev Thrown when two or more sets of arrays are supplied that require equal lengths but differ in length.
    error ArrayLengthMismatch();


    /**
     * @notice Mints tokens to the recipients, each recipient receives the corresponding amount of tokens in the `amounts` array
     * @dev This function should be protected by a role so that it is not callable by any address
     * @param recipients addresses to airdrop tokens to
     * @param amounts amount of tokens that should be airdropped to each recipient
     */
    function airdrop(address[] calldata recipients, uint256[] calldata amounts) external;


    /**
     * @notice Sequentially mints `quantity` of tokens to `to`
     * @dev `minter` and `to` may be the same address but are passed as two separate parameters to properly account for
     *      allowlist mints where a minter is using a delegated wallet to mint
     * @param minter address that the mint count will be credited to
     * @param to address that will receive the tokens
     * @param quantity the number of tokens to sequentially mint to `to`
     */
    function mintSequential(address minter, address to, uint256 quantity) external;

    /**
     * @notice Burns `tokenId` from `from` address
     * @dev This function should check that the caller has permission to burn tokens on behalf of `from`
     * @param from address to burn the tokenId from
     * @param tokenId id of token to be burned
     */
    function burnTokenId(address from, uint256 tokenId) external;

    /**
     * @notice Burns `tokenIds` from `from` address
     * @dev This function should check that the caller has permission to burn tokens on behalf of `from`
     * @param from address to burn the tokenIds from
     * @param tokenIds ids of tokens to be burned
     */
    function burnBatchTokenIds(
        address from,
        uint256[] calldata tokenIds
    ) external;

    /**
     * @notice Emits ERC-4906 BatchMetadataUpdate event for all tokens
     */
    function updateMetadataAllTokens() external;

    /**
     * @notice Emits ERC-4906 MetadataUpdate event for tokens provided
     * @param tokenIds array of token ids to emit MetadataUpdate event for
     */
    function updateMetadataSpecificTokens(uint256[] calldata tokenIds) external;

    /**
     * @notice Returns the total supply of ERC721 tokens in circulation.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @notice Returns the total number of tokens minted for the contract and the number of tokens minted by the `minter`
     * @param minter address to check for number of tokens minted
     * @return totalMinted total number of ERC721 tokens minted since token launch
     * @return minterMinted total number of ERC721 tokens minted by the `minter`
     */
    function totalMintedCollectionAndMinter(address minter) external view returns(uint256 totalMinted, uint256 minterMinted);
}

File 10 of 17 : ILayerrMinter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {MintOrder, MintParameters, MintToken, BurnToken, PaymentToken} from "../lib/MinterStructs.sol";

/**
 * @title ILayerrMinter
 * @author 0xth0mas (Layerr)
 * @notice ILayerrMinter interface defines functions required in the LayerrMinter to be callable by token contracts
 */
interface ILayerrMinter {

    /// @dev Event emitted when a mint order is fulfilled
    event MintOrderFulfilled(
        bytes32 indexed mintParametersDigest,
        address indexed minter,
        uint256 indexed quantity
    );

    /// @dev Event emitted when a token contract updates an allowed signer for EIP712 signatures
    event ContractAllowedSignerUpdate(
        address indexed _contract,
        address indexed _signer,
        bool indexed _allowed
    );

    /// @dev Event emitted when a token contract updates an allowed oracle signer for offchain authorization of a wallet to use a signature
    event ContractOracleUpdated(
        address indexed _contract,
        address indexed _oracle,
        bool indexed _allowed
    );

    /// @dev Event emitted when a signer updates their nonce with LayerrMinter. Updating a nonce invalidates all previously signed EIP712 signatures.
    event SignerNonceIncremented(
        address indexed _signer,
        uint256 indexed _nonce
    );

    /// @dev Event emitted when a specific signature's validity is updated with the LayerrMinter contract.
    event SignatureValidityUpdated(
        address indexed _contract,
        bool indexed invalid,
        bytes32 mintParametersDigests
    );

    /// @dev Thrown when the amount of native tokens supplied in msg.value is insufficient for the mint order
    error InsufficientPayment();

    /// @dev Thrown when a payment fails to be forwarded to the intended recipient
    error PaymentFailed();

    /// @dev Thrown when a MintParameters payment token uses a token type value other than native or ERC20
    error InvalidPaymentTokenType();

    /// @dev Thrown when a MintParameters burn token uses a token type value other than ERC20, ERC721 or ERC1155
    error InvalidBurnTokenType();

    /// @dev Thrown when a MintParameters mint token uses a token type value other than ERC20, ERC721 or ERC1155
    error InvalidMintTokenType();

    /// @dev Thrown when a MintParameters burn token uses a burn type value other than contract burn or send to dead
    error InvalidBurnType();

    /// @dev Thrown when a MintParameters burn token requires a specific burn token id and the tokenId supplied does not match
    error InvalidBurnTokenId();

    /// @dev Thrown when a MintParameters burn token requires a specific ERC721 token and the burn amount is greater than 1
    error CannotBurnMultipleERC721WithSameId();

    /// @dev Thrown when attempting to mint with MintParameters that have a start time greater than the current block time
    error MintHasNotStarted();

    /// @dev Thrown when attempting to mint with MintParameters that have an end time less than the current block time
    error MintHasEnded();

    /// @dev Thrown when a MintParameters has a merkleroot set but the supplied merkle proof is invalid
    error InvalidMerkleProof();

    /// @dev Thrown when a MintOrder will cause a token's minted supply to exceed the defined maximum supply in MintParameters
    error MintExceedsMaxSupply();

    /// @dev Thrown when a MintOrder will cause a minter's minted amount to exceed the defined max per wallet in MintParameters
    error MintExceedsMaxPerWallet();

    /// @dev Thrown when a MintParameters mint token has a specific ERC721 token and the mint amount is greater than 1
    error CannotMintMultipleERC721WithSameId();

    /// @dev Thrown when the recovered signer for the MintParameters is not an allowed signer for the mint token
    error NotAllowedSigner();

    /// @dev Thrown when the recovered signer's nonce does not match the current nonce in LayerrMinter
    error SignerNonceInvalid();

    /// @dev Thrown when a signature has been marked as invalid for a mint token contract
    error SignatureInvalid();

    /// @dev Thrown when MintParameters requires an oracle signature and the recovered signer is not an allowed oracle for the contract
    error InvalidOracleSignature();

    /// @dev Thrown when MintParameters has a max signature use set and the MintOrder will exceed the maximum uses
    error ExceedsMaxSignatureUsage();

    /// @dev Thrown when attempting to increment nonce on behalf of another account and the signature is invalid
    error InvalidSignatureToIncrementNonce();

    /**
     * @notice This function is called by token contracts to update allowed signers for minting
     * @param _signer address of the EIP712 signer
     * @param _allowed if the `_signer` is allowed to sign for minting
     */
    function setContractAllowedSigner(address _signer, bool _allowed) external;

    /**
     * @notice This function is called by token contracts to update allowed oracles for offchain authorizations
     * @param _oracle address of the oracle
     * @param _allowed if the `_oracle` is allowed to sign offchain authorizations
     */
    function setContractAllowedOracle(address _oracle, bool _allowed) external;

    /**
     * @notice This function is called by token contracts to update validity of signatures for the LayerrMinter contract
     * @dev `invalid` should be true to invalidate signatures, the default state of `invalid` being false means 
     *      a signature is valid for a contract assuming all other conditions are met
     * @param mintParametersDigests an array of message digests for MintParameters to update validity of
     * @param invalid if the supplied digests will be marked as valid or invalid
     */
    function setSignatureValidity(
        bytes32[] calldata mintParametersDigests,
        bool invalid
    ) external;

    /**
     * @notice Increments the nonce for a signer to invalidate all previous signed MintParameters
     */
    function incrementSignerNonce() external;

    /**
     * @notice Increments the nonce on behalf of another account by validating a signature from that account
     * @dev The signature is an eth personal sign message of the current signer nonce plus the chain id
     *      ex. current nonce 0 on chain 5 would be a signature of \x19Ethereum Signed Message:\n15
     *          current nonce 50 on chain 1 would be a signature of \x19Ethereum Signed Message:\n251
     * @param signer account to increment nonce for
     * @param signature signature proof that the request is coming from the account
     */
    function incrementNonceFor(address signer, bytes calldata signature) external;

    /**
     * @notice Validates and processes a single MintOrder, tokens are minted to msg.sender
     * @param mintOrder struct containing the details of the mint order
     */
    function mint(
        MintOrder calldata mintOrder
    ) external payable;

    /**
     * @notice Validates and processes an array of MintOrders, tokens are minted to msg.sender
     * @param mintOrders array of structs containing the details of the mint orders
     */
    function mintBatch(
        MintOrder[] calldata mintOrders
    ) external payable;

    /**
     * @notice Validates and processes a single MintOrder, tokens are minted to `mintToWallet`
     * @param mintToWallet the address tokens will be minted to
     * @param mintOrder struct containing the details of the mint order
     * @param paymentContext Contextual information related to the payment process
     *                     (Note: This parameter is required for integration with 
     *                     the payment processor and does not impact the behavior 
     *                     of the function)
     */
    function mintTo(
        address mintToWallet,
        MintOrder calldata mintOrder,
        uint256 paymentContext
    ) external payable;

    /**
     * @notice Validates and processes an array of MintOrders, tokens are minted to `mintToWallet`
     * @param mintToWallet the address tokens will be minted to
     * @param mintOrders array of structs containing the details of the mint orders
     * @param paymentContext Contextual information related to the payment process
     *                     (Note: This parameter is required for integration with 
     *                     the payment processor and does not impact the behavior 
     *                     of the function)
     */
    function mintBatchTo(
        address mintToWallet,
        MintOrder[] calldata mintOrders,
        uint256 paymentContext
    ) external payable;
}

File 11 of 17 : BurnType.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

/// @dev Burn type that specifies the token will be burned with a contract call that reduces supply
uint256 constant BURN_TYPE_CONTRACT_BURN = 0;
/// @dev Burn type that specifies the token will be transferred to the 0x000...dead address without reducing supply
uint256 constant BURN_TYPE_SEND_TO_DEAD = 1;

File 12 of 17 : MerkleProof.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 MerkleProof {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*            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`.
    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 := mul(iszero(iszero(flagsLength)), 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 (i.e. `proofEnd != 0`).
                        or(iszero(proofEnd), eq(proofEnd, proof))
                    )
                break
            }
        }
    }

    /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
    /// given `proof` and `flags`.
    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 :=
                    mul(iszero(iszero(flags.length)), 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 (i.e. `proofEnd != 0`).
                        or(iszero(proofEnd), 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 13 of 17 : MinterStructs.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

/**
 * @dev EIP712 Domain for signature verification
 */
struct EIP712Domain {
    string name;
    string version;
    uint256 chainId;
    address verifyingContract;
}

/**
 * @dev MintOrders contain MintParameters as defined by a token creator
 *      along with proofs required to validate the MintParameters and 
 *      parameters specific to the mint being performed.
 * 
 *      `mintParameters` are the parameters signed by the token creator
 *      `quantity` is a multiplier for mintTokens, burnTokens and paymentTokens
 *          defined in mintParameters
 *      `mintParametersSignature` is the signature from the token creator
 *      `oracleSignature` is a signature of the hash of the mintParameters digest 
 *          and msg.sender. The recovered signer must be an allowed oracle for 
 *          the token contract if oracleSignatureRequired is true for mintParameters.
 *      `merkleProof` is the proof that is checked if merkleRoot is not bytes(0) in
 *          mintParameters
 *      `suppliedBurnTokenIds` is an array of tokenIds to be used when processing
 *          burnTokens. There must be one item in the array for each ERC1155 burnToken
 *          regardless of `quantity` and `quantity` items in the array for each ERC721
 *          burnToken.
 *      `referrer` is the address that will receive a portion of a paymentToken if
 *          not address(0) and paymentToken's referralBPS is greater than 0
 *      `vaultWallet` is used for allowlist mints if the msg.sender address it not on
 *          the allowlist but their delegate.cash vault wallet is.
 *      
 */
struct MintOrder {
    MintParameters mintParameters;
    uint256 quantity;
    bytes mintParametersSignature;
    bytes oracleSignature;
    bytes32[] merkleProof;
    uint256[] suppliedBurnTokenIds;
    address referrer;
    address vaultWallet;
}

/**
 * @dev MintParameters define the tokens to be minted and conditions that must be met
 *      for the mint to be successfully processed.
 * 
 *      `mintTokens` is an array of tokens that will be minted
 *      `burnTokens` is an array of tokens required to be burned
 *      `paymentTokens` is an array of tokens required as payment
 *      `startTime` is the UTC timestamp of when the mint will start
 *      `endTime` is the UTC timestamp of when the mint will end
 *      `signatureMaxUses` limits the number of mints that can be performed with the
 *          specific mintParameters/signature
 *      `merkleRoot` is the root of the merkletree for allowlist minting
 *      `nonce` is the signer nonce that can be incremented on the LayerrMinter 
 *          contract to invalidate all previous signatures
 *      `oracleSignatureRequired` if true requires a secondary signature to process the mint
 */
struct MintParameters {
    MintToken[] mintTokens;
    BurnToken[] burnTokens;
    PaymentToken[] paymentTokens;
    uint256 startTime;
    uint256 endTime;
    uint256 signatureMaxUses;
    bytes32 merkleRoot;
    uint256 nonce;
    bool oracleSignatureRequired;
}

/**
 * @dev Defines the token that will be minted
 *      
 *      `contractAddress` address of contract to mint tokens from
 *      `specificTokenId` used for ERC721 - 
 *          if true, mint is non-sequential ERC721
 *          if false, mint is sequential ERC721A
 *      `tokenType` is the type of token being minted defined in TokenTypes.sol
 *      `tokenId` the tokenId to mint if specificTokenId is true
 *      `mintAmount` is the quantity to be minted
 *      `maxSupply` is checked against the total minted amount at time of mint
 *          minting reverts if `mintAmount` * `quantity` will cause total minted to 
 *          exceed `maxSupply`
 *      `maxMintPerWallet` is checked against the number minted for the wallet
 *          minting reverts if `mintAmount` * `quantity` will cause wallet minted to 
 *          exceed `maxMintPerWallet`
 */
struct MintToken {
    address contractAddress;
    bool specificTokenId;
    uint256 tokenType;
    uint256 tokenId;
    uint256 mintAmount;
    uint256 maxSupply;
    uint256 maxMintPerWallet;
}

/**
 * @dev Defines the token that will be burned
 *      
 *      `contractAddress` address of contract to burn tokens from
 *      `specificTokenId` specifies if the user has the option of choosing any token
 *          from the contract or if they must burn a specific token
 *      `tokenType` is the type of token being burned, defined in TokenTypes.sol
 *      `burnType` is the type of burn to perform, burn function call or transfer to 
 *          dead address, defined in BurnType.sol
 *      `tokenId` the tokenId to burn if specificTokenId is true
 *      `burnAmount` is the quantity to be burned
 */
struct BurnToken {
    address contractAddress;
    bool specificTokenId;
    uint256 tokenType;
    uint256 burnType;
    uint256 tokenId;
    uint256 burnAmount;
}

/**
 * @dev Defines the token that will be used for payment
 *      
 *      `contractAddress` address of contract to for payment if ERC20
 *          if tokenType is native token then this should be set to 0x000...000
 *          to save calldata gas units
 *      `tokenType` is the type of token being used for payment, defined in TokenTypes.sol
 *      `payTo` the address that will receive the payment
 *      `paymentAmount` the amount for the payment in base units for the token
 *          ex. a native payment on Ethereum for 1 ETH would be specified in wei
 *          which would be 1**18 wei
 *      `referralBPS` is the percentage of the payment in BPS that will be sent to the 
 *          `referrer` on the MintOrder if `referralBPS` is greater than 0 and `referrer`
 *          is not address(0)
 */
struct PaymentToken {
    address contractAddress;
    uint256 tokenType;
    address payTo;
    uint256 paymentAmount;
    uint256 referralBPS;
}

File 14 of 17 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title ReentrancyGuard
 * @author 0xth0mas (Layerr)
 * @notice Simple reentrancy guard to prevent callers from re-entering the LayerrMinter mint functions
 */
contract ReentrancyGuard {
    uint256 private _reentrancyGuard = 1;
    error ReentrancyProhibited();

    modifier NonReentrant() {
        if (_reentrancyGuard > 1) {
            revert ReentrancyProhibited();
        }
        _reentrancyGuard = 2;
        _;
        _reentrancyGuard = 1;
    }
}

File 15 of 17 : SignatureVerification.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

import {EIP712Domain, MintOrder, MintParameters, MintToken, BurnToken, PaymentToken} from "./MinterStructs.sol";
import {EIP712_DOMAIN_TYPEHASH, MINTPARAMETERS_TYPEHASH, MINTTOKEN_TYPEHASH, BURNTOKEN_TYPEHASH, PAYMENTTOKEN_TYPEHASH} from "./TypeHashes.sol";

/**
 * @title SignatureVerification
 * @author 0xth0mas (Layerr)
 * @author Modified from 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)
 * @notice Recovers the EIP712 signer for MintParameters and oracle signers
 *         for the LayerrMinter contract.
 */
contract SignatureVerification {
    bytes32 private immutable _cachedDomainSeparator;
    uint256 private immutable _cachedChainId;
    address private immutable _cachedThis;

    string private constant _name = "LayerrMinter";
    string private constant _version = "1.0";

    bytes32 private immutable _hashedName;
    bytes32 private immutable _hashedVersion;

    constructor() {
        _hashedName = keccak256(bytes(_name));
        _hashedVersion = keccak256(bytes(_version));

        _cachedChainId = block.chainid;
        _cachedDomainSeparator = _buildDomainSeparator();
        _cachedThis = address(this);
    }
    
    /**
     * @notice Recovers the signer address for the supplied mint parameters and signature
     * @param input MintParameters to recover the signer for
     * @param signature Signature for the MintParameters `_input` to recover signer
     * @return signer recovered signer of `signature` and `_input`
     * @return digest hash digest of `_input`
     */
    function _recoverMintParametersSigner(
        MintParameters calldata input,
        bytes calldata signature
    ) internal view returns (address signer, bytes32 digest) {
        bytes32 hash = _getMintParametersHash(input);
        digest = keccak256(
            abi.encodePacked("\x19\x01", _domainSeparator(), hash)
        );
        signer = _recover(digest, signature);
    }

    /**
     * @notice Recovers the signer address for the supplied oracle signature
     * @param minter address of wallet performing the mint
     * @param mintParametersSignature signature of MintParameters to check oracle signature of
     * @param oracleSignature supplied oracle signature
     * @return signer recovered oracle signer address
     */
    function _recoverOracleSigner(
        address minter, 
        bytes calldata mintParametersSignature, 
        bytes calldata oracleSignature
    ) internal pure returns(address signer) {
        bytes32 digest = keccak256(abi.encodePacked(minter, mintParametersSignature));
        signer = _recover(digest, oracleSignature);
    }

    /**
     * @notice Recovers the signer address for the increment nonce transaction
     * @param signer address of the account to increment nonce
     * @param currentNonce current nonce for the signer account
     * @param signature signature of message to validate
     * @return valid if the signature came from the signer
     */
    function _validateIncrementNonceSigner(
        address signer, 
        uint256 currentNonce,
        bytes calldata signature
    ) internal view returns(bool valid) {
        unchecked {
            // add chain id to current nonce to guard against replay on other chains
            currentNonce += block.chainid;
        }
        bytes memory nonceString = bytes(_toString(currentNonce));
        bytes32 digest = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", _toString(nonceString.length), nonceString));
        valid = signer == _recover(digest, signature) && signer != address(0);
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparator() private view returns (bytes32 separator) {
        separator = _cachedDomainSeparator;
        if (_cachedDomainSeparatorInvalidated()) {
            separator = _buildDomainSeparator();
        }
    }

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

    function _buildDomainSeparator() private view returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    EIP712_DOMAIN_TYPEHASH,
                    _hashedName,
                    _hashedVersion,
                    block.chainid,
                    address(this)
                )
            );
    }

    /**
     * @dev Recover signer address from a message by using their signature
     * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
     * @param sig bytes signature, the signature is generated using web3.eth.sign()
     */
    function _recover(
        bytes32 hash,
        bytes calldata sig
    ) internal pure returns (address) {
        bytes32 r;
        bytes32 s;
        uint8 v;

        // Check the signature length
        if (sig.length != 65) {
            return (address(0));
        }

        // Divide the signature in r, s and v variables
        /// @solidity memory-safe-assembly
        assembly {
            r := calldataload(sig.offset)
            s := calldataload(add(sig.offset, 32))
            v := byte(0, calldataload(add(sig.offset, 64)))
        }

        // If the version is correct return the signer address
        if (v != 27 && v != 28) {
            return (address(0));
        } else {
            return ecrecover(hash, v, r, s);
        }
    }

    function _toString(uint256 value) internal pure virtual returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := add(mload(0x40), 0xa0)
            mstore(0x40, m)
            str := sub(m, 0x20)
            mstore(str, 0)
            let end := str

            for { let temp := value } 1 {} {
                str := sub(str, 1)
                mstore8(str, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }

            let length := sub(end, str)
            str := sub(str, 0x20)
            mstore(str, length)
        }
    }

    function _getMintTokenArrayHash(
        MintToken[] calldata mintTokens
    ) internal pure returns (bytes32 hash) {
        bytes memory encoded;
        for (uint256 i = 0; i < mintTokens.length; ) {
            encoded = abi.encodePacked(encoded, _getMintTokenHash(mintTokens[i]));
            unchecked {
                ++i;
            }
        }
        hash = keccak256(encoded);
    }

    function _getBurnTokenArrayHash(
        BurnToken[] calldata burnTokens
    ) internal pure returns (bytes32 hash) {
        bytes memory encoded;
        for (uint256 i = 0; i < burnTokens.length; ) {
            encoded = abi.encodePacked(encoded, _getBurnTokenHash(burnTokens[i]));
            unchecked {
                ++i;
            }
        }
        hash = keccak256(encoded);
    }

    function _getPaymentTokenArrayHash(
        PaymentToken[] calldata paymentTokens
    ) internal pure returns (bytes32 hash) {
        bytes memory encoded;
        for (uint256 i = 0; i < paymentTokens.length; ) {
            encoded = abi.encodePacked(encoded, _getPaymentTokenHash(paymentTokens[i]));
            unchecked {
                ++i;
            }
        }
        hash = keccak256(encoded);
    }

    function _getMintTokenHash(
        MintToken calldata mintToken
    ) internal pure returns (bytes32 hash) {
        hash = keccak256(
            abi.encode(
                MINTTOKEN_TYPEHASH,
                mintToken.contractAddress,
                mintToken.specificTokenId,
                mintToken.tokenType,
                mintToken.tokenId,
                mintToken.mintAmount,
                mintToken.maxSupply,
                mintToken.maxMintPerWallet
            )
        );
    }

    function _getBurnTokenHash(
        BurnToken calldata burnToken
    ) internal pure returns (bytes32 hash) {
        hash = keccak256(
            abi.encode(
                BURNTOKEN_TYPEHASH,
                burnToken.contractAddress,
                burnToken.specificTokenId,
                burnToken.tokenType,
                burnToken.burnType,
                burnToken.tokenId,
                burnToken.burnAmount
            )
        );
    }

    function _getPaymentTokenHash(
        PaymentToken calldata paymentToken
    ) internal pure returns (bytes32 hash) {
        hash = keccak256(
            abi.encode(
                PAYMENTTOKEN_TYPEHASH,
                paymentToken.contractAddress,
                paymentToken.tokenType,
                paymentToken.payTo,
                paymentToken.paymentAmount,
                paymentToken.referralBPS
            )
        );
    }

    function _getMintParametersHash(
        MintParameters calldata mintParameters
    ) internal pure returns (bytes32 hash) {
        bytes memory encoded = abi.encode(
            MINTPARAMETERS_TYPEHASH,
            _getMintTokenArrayHash(mintParameters.mintTokens),
            _getBurnTokenArrayHash(mintParameters.burnTokens),
            _getPaymentTokenArrayHash(mintParameters.paymentTokens),
            mintParameters.startTime,
            mintParameters.endTime,
            mintParameters.signatureMaxUses,
            mintParameters.merkleRoot,
            mintParameters.nonce,
            mintParameters.oracleSignatureRequired
        );
        hash = keccak256(encoded);
    }

    function getMintParametersSignatureDigest(
        MintParameters calldata mintParameters
    ) external view returns (bytes32 digest) {
        bytes32 hash = _getMintParametersHash(mintParameters);
        digest = keccak256(
            abi.encodePacked("\x19\x01", _domainSeparator(), hash)
        );
    }
}

File 16 of 17 : TokenType.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

/// @dev Token type used for payment tokens to specify payment is in the blockchain native token
uint256 constant TOKEN_TYPE_NATIVE  = 0;
/// @dev Token type used for payments, mints and burns to specify the token is an ERC20
uint256 constant TOKEN_TYPE_ERC20 = 1;
/// @dev Token type used for mints and burns to specify the token is an ERC721
uint256 constant TOKEN_TYPE_ERC721 = 2;
/// @dev Token type used for mints and burns to specify the token is an ERC1155
uint256 constant TOKEN_TYPE_ERC1155 = 3;

File 17 of 17 : TypeHashes.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

bytes32 constant EIP712_DOMAIN_TYPEHASH = keccak256(
    "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);

bytes32 constant MINTPARAMETERS_TYPEHASH = keccak256(
    "MintParameters(MintToken[] mintTokens,"
    "BurnToken[] burnTokens,"
    "PaymentToken[] paymentTokens,"
    "uint256 startTime,"
    "uint256 endTime,"
    "uint256 signatureMaxUses,"
    "bytes32 merkleRoot,"
    "uint256 nonce,"
    "bool oracleSignatureRequired)"
    "BurnToken(address contractAddress,"
    "bool specificTokenId,"
    "uint8 tokenType,"
    "uint8 burnType,"
    "uint256 tokenId,"
    "uint256 burnAmount)"
    "MintToken(address contractAddress,"
    "bool specificTokenId,"
    "uint8 tokenType,"
    "uint256 tokenId,"
    "uint256 mintAmount,"
    "uint256 maxSupply,"
    "uint256 maxMintPerWallet)"
    "PaymentToken(address contractAddress,"
    "uint8 tokenType,"
    "address payTo,"
    "uint256 paymentAmount,"
    "uint256 referralBPS)"
);

bytes32 constant MINTTOKEN_TYPEHASH = keccak256(
    "MintToken(address contractAddress,bool specificTokenId,uint8 tokenType,uint256 tokenId,uint256 mintAmount,uint256 maxSupply,uint256 maxMintPerWallet)"
);

bytes32 constant BURNTOKEN_TYPEHASH = keccak256(
    "BurnToken(address contractAddress,bool specificTokenId,uint8 tokenType,uint8 burnType,uint256 tokenId,uint256 burnAmount)"
);

bytes32 constant PAYMENTTOKEN_TYPEHASH = keccak256(
    "PaymentToken(address contractAddress,uint8 tokenType,address payTo,uint256 paymentAmount,uint256 referralBPS)"
);

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 33333
  },
  "evmVersion": "paris",
  "viaIR": true,
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"name":"CannotBurnMultipleERC721WithSameId","type":"error"},{"inputs":[],"name":"CannotMintMultipleERC721WithSameId","type":"error"},{"inputs":[],"name":"ExceedsMaxSignatureUsage","type":"error"},{"inputs":[],"name":"InsufficientPayment","type":"error"},{"inputs":[],"name":"InvalidBurnTokenId","type":"error"},{"inputs":[],"name":"InvalidBurnTokenType","type":"error"},{"inputs":[],"name":"InvalidBurnType","type":"error"},{"inputs":[],"name":"InvalidMerkleProof","type":"error"},{"inputs":[],"name":"InvalidMintTokenType","type":"error"},{"inputs":[],"name":"InvalidOracleSignature","type":"error"},{"inputs":[],"name":"InvalidPaymentTokenType","type":"error"},{"inputs":[],"name":"InvalidSignatureToIncrementNonce","type":"error"},{"inputs":[],"name":"MintExceedsMaxPerWallet","type":"error"},{"inputs":[],"name":"MintExceedsMaxSupply","type":"error"},{"inputs":[],"name":"MintHasEnded","type":"error"},{"inputs":[],"name":"MintHasNotStarted","type":"error"},{"inputs":[],"name":"NotAllowedSigner","type":"error"},{"inputs":[],"name":"PaymentFailed","type":"error"},{"inputs":[],"name":"ReentrancyProhibited","type":"error"},{"inputs":[],"name":"SignatureInvalid","type":"error"},{"inputs":[],"name":"SignerNonceInvalid","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_contract","type":"address"},{"indexed":true,"internalType":"address","name":"_signer","type":"address"},{"indexed":true,"internalType":"bool","name":"_allowed","type":"bool"}],"name":"ContractAllowedSignerUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_contract","type":"address"},{"indexed":true,"internalType":"address","name":"_oracle","type":"address"},{"indexed":true,"internalType":"bool","name":"_allowed","type":"bool"}],"name":"ContractOracleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mintParametersDigest","type":"bytes32"},{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":true,"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"MintOrderFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_contract","type":"address"},{"indexed":true,"internalType":"bool","name":"invalid","type":"bool"},{"indexed":false,"internalType":"bytes32","name":"mintParametersDigests","type":"bytes32"}],"name":"SignatureValidityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_signer","type":"address"},{"indexed":true,"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"SignerNonceIncremented","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"contractAllowedOracle","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"contractAllowedSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"bool","name":"specificTokenId","type":"bool"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"mintAmount","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"maxMintPerWallet","type":"uint256"}],"internalType":"struct MintToken[]","name":"mintTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"bool","name":"specificTokenId","type":"bool"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"uint256","name":"burnType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"burnAmount","type":"uint256"}],"internalType":"struct BurnToken[]","name":"burnTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"address","name":"payTo","type":"address"},{"internalType":"uint256","name":"paymentAmount","type":"uint256"},{"internalType":"uint256","name":"referralBPS","type":"uint256"}],"internalType":"struct PaymentToken[]","name":"paymentTokens","type":"tuple[]"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"signatureMaxUses","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bool","name":"oracleSignatureRequired","type":"bool"}],"internalType":"struct MintParameters","name":"mintParameters","type":"tuple"}],"name":"getMintParametersSignatureDigest","outputs":[{"internalType":"bytes32","name":"digest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"incrementNonceFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"incrementSignerNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"bool","name":"specificTokenId","type":"bool"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"mintAmount","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"maxMintPerWallet","type":"uint256"}],"internalType":"struct MintToken[]","name":"mintTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"bool","name":"specificTokenId","type":"bool"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"uint256","name":"burnType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"burnAmount","type":"uint256"}],"internalType":"struct BurnToken[]","name":"burnTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"address","name":"payTo","type":"address"},{"internalType":"uint256","name":"paymentAmount","type":"uint256"},{"internalType":"uint256","name":"referralBPS","type":"uint256"}],"internalType":"struct PaymentToken[]","name":"paymentTokens","type":"tuple[]"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"signatureMaxUses","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bool","name":"oracleSignatureRequired","type":"bool"}],"internalType":"struct MintParameters","name":"mintParameters","type":"tuple"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes","name":"mintParametersSignature","type":"bytes"},{"internalType":"bytes","name":"oracleSignature","type":"bytes"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint256[]","name":"suppliedBurnTokenIds","type":"uint256[]"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"vaultWallet","type":"address"}],"internalType":"struct MintOrder","name":"mintOrder","type":"tuple"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"bool","name":"specificTokenId","type":"bool"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"mintAmount","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"maxMintPerWallet","type":"uint256"}],"internalType":"struct MintToken[]","name":"mintTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"bool","name":"specificTokenId","type":"bool"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"uint256","name":"burnType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"burnAmount","type":"uint256"}],"internalType":"struct BurnToken[]","name":"burnTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"address","name":"payTo","type":"address"},{"internalType":"uint256","name":"paymentAmount","type":"uint256"},{"internalType":"uint256","name":"referralBPS","type":"uint256"}],"internalType":"struct PaymentToken[]","name":"paymentTokens","type":"tuple[]"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"signatureMaxUses","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bool","name":"oracleSignatureRequired","type":"bool"}],"internalType":"struct MintParameters","name":"mintParameters","type":"tuple"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes","name":"mintParametersSignature","type":"bytes"},{"internalType":"bytes","name":"oracleSignature","type":"bytes"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint256[]","name":"suppliedBurnTokenIds","type":"uint256[]"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"vaultWallet","type":"address"}],"internalType":"struct MintOrder[]","name":"mintOrders","type":"tuple[]"}],"name":"mintBatch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"mintToWallet","type":"address"},{"components":[{"components":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"bool","name":"specificTokenId","type":"bool"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"mintAmount","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"maxMintPerWallet","type":"uint256"}],"internalType":"struct MintToken[]","name":"mintTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"bool","name":"specificTokenId","type":"bool"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"uint256","name":"burnType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"burnAmount","type":"uint256"}],"internalType":"struct BurnToken[]","name":"burnTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"address","name":"payTo","type":"address"},{"internalType":"uint256","name":"paymentAmount","type":"uint256"},{"internalType":"uint256","name":"referralBPS","type":"uint256"}],"internalType":"struct PaymentToken[]","name":"paymentTokens","type":"tuple[]"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"signatureMaxUses","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bool","name":"oracleSignatureRequired","type":"bool"}],"internalType":"struct MintParameters","name":"mintParameters","type":"tuple"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes","name":"mintParametersSignature","type":"bytes"},{"internalType":"bytes","name":"oracleSignature","type":"bytes"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint256[]","name":"suppliedBurnTokenIds","type":"uint256[]"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"vaultWallet","type":"address"}],"internalType":"struct MintOrder[]","name":"mintOrders","type":"tuple[]"},{"internalType":"uint256","name":"paymentContext","type":"uint256"}],"name":"mintBatchTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"mintToWallet","type":"address"},{"components":[{"components":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"bool","name":"specificTokenId","type":"bool"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"mintAmount","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"maxMintPerWallet","type":"uint256"}],"internalType":"struct MintToken[]","name":"mintTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"bool","name":"specificTokenId","type":"bool"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"uint256","name":"burnType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"burnAmount","type":"uint256"}],"internalType":"struct BurnToken[]","name":"burnTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenType","type":"uint256"},{"internalType":"address","name":"payTo","type":"address"},{"internalType":"uint256","name":"paymentAmount","type":"uint256"},{"internalType":"uint256","name":"referralBPS","type":"uint256"}],"internalType":"struct PaymentToken[]","name":"paymentTokens","type":"tuple[]"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"signatureMaxUses","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bool","name":"oracleSignatureRequired","type":"bool"}],"internalType":"struct MintParameters","name":"mintParameters","type":"tuple"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes","name":"mintParametersSignature","type":"bytes"},{"internalType":"bytes","name":"oracleSignature","type":"bytes"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint256[]","name":"suppliedBurnTokenIds","type":"uint256[]"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"vaultWallet","type":"address"}],"internalType":"struct MintOrder","name":"mintOrder","type":"tuple"},{"internalType":"uint256","name":"paymentContext","type":"uint256"}],"name":"mintTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setContractAllowedOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"},{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setContractAllowedSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"signatureDigests","type":"bytes32[]"},{"internalType":"bool","name":"invalid","type":"bool"}],"name":"setSignatureValidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"signatureInvalid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"signatureUseCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"signerNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

610120806040523462000143576020600c916001600055620000218162000148565b828152016b2630bcb2b93926b4b73a32b960a11b81522060e052600360206040516200004d8162000148565b82815201620312e360ec1b815220610100908082524660a05260e0516040519160208301917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8352604084015260608301524660808301523060a083015260a0825260c082019180831060018060401b038411176200012d5760408390525190206080523060c052600680546001600160a01b0319166d76a84fef008cdabe6409d2fe638b179055615678918262000165833960805182615045015260a0518261508a015260c05182615067015260e051826150e2015251816151080152f35b634e487b7160e01b600052604160045260246000fd5b600080fd5b604081019081106001600160401b038211176200012d5760405256fe608080604052600436101561001357600080fd5b60003560e01c90816303714b6c14612026575080630b5220cf14611fd9578063119f56e014611e4957806322f0e36f14611e0f57806325c09a3d14611db85780632c09294a146105db57806338c09cc5146105645780636825fbe01461053857806380ce83c31461047c57806391b245b31461041357806393b670ea1461036e578063942943f91461028c578063b2b7ad92146101c5578063dadea50c1461016e5763fd0f4a4a146100c457600080fd5b34610169576040600319360112610169576100dd61343d565b6100e561349a565b3360005260046020526001600160a01b0360406000209216918260005260205261013e8160406000209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b151590337ff3e08db8f80606a00ef8635b0c80c615721eca7f1c250353231ebdd0f768dff7600080a4005b600080fd5b346101695760406003193601126101695761018761343d565b61018f613453565b906001600160a01b03809116600052600460205260406000209116600052602052602060ff604060002054166040519015158152f35b3461016957600319602081360112610169576004359067ffffffffffffffff82116101695761012090823603011261016957610205602091600401615278565b610255610281610213615043565b92604051928391868301958690916042927f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201520190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282613508565b519020604051908152f35b346101695760406003193601126101695760043567ffffffffffffffff8111610169576102bd903690600401613469565b6102c561349a565b8015159060005b8381106102d557005b3360005260019083602083815260406000206102f284898b613549565b3560005281526103318560406000209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b7fb0aa5effc586eb20f130429a2f29677698e9f92786a6bef6a3ad0cbc14b0b52d61035d84898b613549565b35916040519283523392a3016102cc565b346101695760406003193601126101695761038761343d565b61038f61349a565b3360005260036020526001600160a01b036040600020921691826000526020526103e88160406000209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b151590337f6a0dc189effd165f709551bb21684c2b4595fde0a2d4bc71eac5fe81379f0a62600080a4005b346101695760006003193601126101695760405160208101904282526020815261043c816134ec565b519020336000526005602052604060002090815401809155337f8ca15a4665cc6fff23311db04eee49bb4a10bd9e962e0b5865f4dd17aac03477600080a3005b60606003193601126101695761049061343d565b60243567ffffffffffffffff8111610169576104b0903690600401613469565b90600192836000541161050e576002600055600090846000925b8584106104ef575047806104df575b50600055005b6104e99033614df3565b816104d9565b610504906104fe858888613588565b846137b0565b92019185906104ca565b60046040517f0db255a6000000000000000000000000000000000000000000000000000000008152fd5b346101695760206003193601126101695760043560005260026020526020604060002054604051908152f35b60206003193601126101695760043567ffffffffffffffff811161016957610590903690600401613469565b600191826000541161050e5760026000556000836000915b8483106105bc575047806104df5750600055005b6105d1906105cb848787613588565b336137b0565b91019084906105a8565b60206003193601126101695767ffffffffffffffff6004351161016957610100600319600435360301126101695760016000541161050e5760026000556106266004803501806135c8565b61063a6044600435016004356004016135fb565b909161064581615278565b610255610696610653615043565b9260405192839160208301958690916042927f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201520190565b519020926106a583828661515c565b600093909184916106ba6004803501806135c8565b42606082013511611d8e5742608082013510611d64576001600160a01b038516600052600560205260406000205460e082013503611d3a5760c0810135611ad3575b60a081013580611a6e575b506101006107159101614b86565b6119e0575b5050610729604084018461364c565b9061073860c4600435016136a0565b9160005b81811061188b575050505061075460208401846136b4565b9050610fd3575b15610fc95761077961077160e4600435016136a0565b925b8061375c565b9060005b8281106107d0576004356024013533887f9d45e8614d63fdcb7d8e231afe42fcd0366c2c2d3792a5df9954be4fd5d61e3c600080a447806107c0575b6001600055005b6107ca9033614df3565b806107b9565b6107db818484614c82565b906107e5826136a0565b6001600160a01b038116600052600360205260406000206001600160a01b03871660005260205260ff6040600020541615610f9f576001600160a01b038116600052600160205260406000208960005260205260ff60406000205416610f75576001600160a01b03881680610f19575b5061086260208401614b86565b610876602460043501356080860135614ba3565b90604085013560038103610b0c575050825b868110610ad4575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101840361096f57506108d4818960c087013560a0880135606089013587614ca8565b6001600160a01b0382163b156101695760848860006001600160a01b038195819560606040519a8b9889977fcb4ef4e4000000000000000000000000000000000000000000000000000000008952166004880152336024880152013560448601526064850152165af191821561096357600192610954575b505b0161077d565b61095d906134a9565b8861094c565b6040513d6000823e3d90fd5b92919350506109866109818284614bb6565b614beb565b916109946109818383614bb6565b916000915b808210610a7057507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff915001916001600160a01b0384163b1561016957610a35936001600160a01b036000818b610a4783976040519a8b98899788957f613ce049000000000000000000000000000000000000000000000000000000008752166004860152336024860152608060448601526084850190614c4e565b90600319848303016064850152614c4e565b0393165af191821561096357600192610a61575b5061094e565b610a6a906134a9565b88610a5b565b906001818b610a8183948c8c614c82565b610ab2606082013591610a9e602460043501356080830135614ba3565b93849160c08101359060a00135858f614ca8565b610abc878a614c3a565b52610ac78688614c3a565b5201920190919091610999565b6001600160a01b0383166001600160a01b03610af9610af4848b8b614c82565b6136a0565b1603610b0757600101610888565b610890565b9194909160028103610d94575060a08101351580158091610d87575b610c5c575b5081158015610c52575b15610bd35750610ba9576001600160a01b0381163b15610169576040517f82b1c4230000000000000000000000000000000000000000000000000000000081526001600160a01b0380891660048301523360248301526044820194909452926000918491829084908260648101610a47565b60046040517f5505f367000000000000000000000000000000000000000000000000000000008152fd5b9350506001600160a01b0381163b15610169576040517f5598d9670000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015233602483015260609490940135604482015292600091849160649183918591165af191821561096357600192610a61575061094e565b5060018511610b37565b6040517fc035f9b50000000000000000000000000000000000000000000000000000000081526001600160a01b038b1660048201526040816024816001600160a01b0389165afa91821561096357600091600093610d54575b50610d10575b5060c0820135908682610cd0575b5050610b2d565b610cd991614b4a565b11610ce6578b8086610cc9565b60046040517f94d7a276000000000000000000000000000000000000000000000000000000008152fd5b610d1f8760a085013592614b4a565b11610d2a578c610cbb565b60046040517f3e0866c7000000000000000000000000000000000000000000000000000000008152fd5b909250610d79915060403d604011610d80575b610d718183613508565b810190614c92565b918e610cb5565b503d610d67565b5060c08201351515610b28565b909150600103610eef5760a0810135159081158092610ee2575b610e1d575b50506001600160a01b0381163b15610169576040517fc6c3bbe60000000000000000000000000000000000000000000000000000000081526001600160a01b0380891660048301523360248301526044820194909452926000918491829084908260648101610a47565b6040517fe158dfdc0000000000000000000000000000000000000000000000000000000081526001600160a01b038a1660048201526040816024816001600160a01b0388165afa92831561096357600091600094610ebf575b50610ea5575b5060c00135908482610e8f575b50610db3565b610e9891614b4a565b11610ce657898084610e89565b610eb48660a084013592614b4a565b11610d2a578b610e7c565b909350610edb915060403d604011610d8057610d718183613508565b928d610e76565b5060c08101351515610dae565b60046040517f71e36489000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b038216600052600460205260406000209060005260205260ff6040600020541615610f4b5789610855565b60046040517f2f58c7cd000000000000000000000000000000000000000000000000000000008152fd5b60046040517f37e8456b000000000000000000000000000000000000000000000000000000008152fd5b60046040517fa48ee854000000000000000000000000000000000000000000000000000000008152fd5b6107793392610773565b610fe060208401846136b4565b90610ff560a460043501600435600401613708565b91600091825b85841061100d5750505050505061075b565b611018848785614bc3565b90611022826136a0565b9161102f60208201614b86565b9060408101359161104a6024600435013560a0840135614ba3565b92600381036114b95750875b8a811061148c575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810189036112475750611205575b606081013561112c57506110a2828886613549565b35906001600160a01b0384163b15610169576064600092836001600160a01b0360405197889586947f1227fe8600000000000000000000000000000000000000000000000000000000865233600487015260248601526044850152165af190811561096357600192839261111d575b505b01935b0192610ffb565b611126906134a9565b8d611111565b606001356001036111db57611142828886613549565b35906001600160a01b0384163b156101695760c4600092836001600160a01b0360405197889586947ff242432a00000000000000000000000000000000000000000000000000000000865233600487015261dead60248701526044860152606485015260a060848501528260a4850152165af19081156109635760019283926111cc575b50611113565b6111d5906134a9565b8d6111c6565b60046040517f89248e16000000000000000000000000000000000000000000000000000000008152fd5b611210838987613549565b356080820135031561108d575b60046040517f4d9c9be5000000000000000000000000000000000000000000000000000000008152fd5b91939792505061125a6109818383614bb6565b916112686109818284614bb6565b9160005b8183106113fd5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192606081013561134457506001600160a01b0384163b156101695761131b9361130960006001600160a01b038195604051988996879586937f092c8aa5000000000000000000000000000000000000000000000000000000008552336004860152606060248601526064850190614c4e565b90600319848303016044850152614c4e565b0393165af191821561096357600192611335575b50611116565b61133e906134a9565b8c61132f565b90939190606001356001036111db576001600160a01b0382163b15610169576000916113c291836001600160a01b0360206113d4604051998a9788967f2eb2c2d600000000000000000000000000000000000000000000000000000000885233600489015261dead602489015260a0604489015260a4880190614c4e565b90600319878303016064880152614c4e565b838582039160031983016084880152520193165af1918215610963576001926113355750611116565b9161140c818d8b9c949c614bc3565b90828c8a61141c60208601614b86565b946114316024600435013560a0830135614ba3565b9561146d575b509361144a600195938695938695613549565b35611455888b614c3a565b526114608789614c3a565b520193019101989061126c565b9260809261147a92613549565b359101350361121d57828c8a38611437565b8a6001600160a01b036114a6610af484838b16948d614bc3565b16036114b457600101611056565b61105e565b93979493909190600281036117d3575060608101356001036116735760018311156115b7575061158d5760005b8181106114f9575050506001905b611116565b611504878987613549565b35906001600160a01b0384163b1561016957604051917f23b872dd00000000000000000000000000000000000000000000000000000000835233600484015261dead60248401526044830152600082606481836001600160a01b0389165af190811561096357600192839261157e575b50019601956114e6565b611587906134a9565b38611574565b60046040517ff143a830000000000000000000000000000000000000000000000000000000008152fd5b915095919295611657575b506115ce818785613549565b356001600160a01b0383163b15610169576001600160a01b039260646000928360405196879485937f23b872dd00000000000000000000000000000000000000000000000000000000855233600486015261dead60248601526044850152165af1908115610963576001928392611648575b500193611116565b611651906134a9565b8d611640565b6080611664838987613549565b359101350361121d578c6115c2565b9193929160608101356111db57600185111561172b575061158d5761169783614beb565b9260005b8181106117075750506001600160a01b0381163b156101695761131b6000916001600160a01b0394836040519687809581947f7d3c5ebe000000000000000000000000000000000000000000000000000000008352336004840152604060248401526044830190614c4e565b600180916117168a8c8a613549565b356117218289614c3a565b520197019661169b565b9193509591956117b7575b50611742818785613549565b35916001600160a01b0381163b15610169576040517f6621a02500000000000000000000000000000000000000000000000000000000815233600482015260248101939093526000908390604490829084906001600160a01b03165af190811561096357600192839261164857500193611116565b60806117c4838987613549565b359101350361121d578c611736565b929493929091506001036118615760608101356001036117fc57506001926114f4913390614ef6565b606001356111db576001600160a01b0381163b15610169576040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810193909352600090839081836001600160a01b03826044810161131b565b60046040517fb6166382000000000000000000000000000000000000000000000000000000008152fd5b611896818385614b93565b906118ab602460043501356060840135614ba3565b60208301358061193157506001926001600160a01b038716158015611925575b156118eb57906118e060406118e593016136a0565b614df3565b0161073c565b6118e0604061191961192094612710611908608087013583614ba3565b0490611914828d614df3565b614bb6565b92016136a0565b6118e5565b506080810135156118cb565b6001036119b6576001926001600160a01b0387161580156119aa575b1561196d5790816119656040611919611920956136a0565b903390614f70565b61199b61192092612710611985608085013583614ba3565b0490611914828b33611996886136a0565b614f70565b906119656040611919836136a0565b5060808101351561194d565b60046040517f2a807f24000000000000000000000000000000000000000000000000000000008152fd5b611a579295506119fa6064600435016004356004016135fb565b929091611a4f603460405183819460208301967fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b168852848401378101600083820152036014810184520182613508565b51902061515c565b926001600160a01b03841615610f4b57858061071a565b8860005260026020526040600020611a8d602460043501358254614b4a565b905588600052600260205260406000205411611aa95788610707565b60046040517ff3c02f73000000000000000000000000000000000000000000000000000000008152fd5b611b37611aea608460043501600435600401613708565b9060405160208101907fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16825260148152611b28816134ec565b5190209160c085013591614fd5565b6106fc579250611b4b60e4600435016136a0565b6001600160a01b038116611b835760046040517fb05e92fa000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b03600654166040517f9c395bc20000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0383166024820152602081604481855afa90811561096357600091611d1b575b5015611c85575b50611c4e90611c02608460043501600435600401613708565b916040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602082019260601b16825260148152611c3f816134ec565b5190209160c087013591614fd5565b15611c5b576001926106fc565b60046040517fb05e92fa000000000000000000000000000000000000000000000000000000008152fd5b6020606491604051928380927f90c9a2d00000000000000000000000000000000000000000000000000000000082523360048301526001600160a01b03871660248301523060448301525afa90811561096357600091611cec575b5015611c5b5788611be9565b611d0e915060203d602011611d14575b611d068183613508565b810190614b32565b89611ce0565b503d611cfc565b611d34915060203d602011611d1457611d068183613508565b8a611be2565b60046040517f172529af000000000000000000000000000000000000000000000000000000008152fd5b60046040517fc0226372000000000000000000000000000000000000000000000000000000008152fd5b60046040517fc10ebb06000000000000000000000000000000000000000000000000000000008152fd5b3461016957604060031936011261016957611dd161343d565b611dd9613453565b906001600160a01b03809116600052600360205260406000209116600052602052602060ff604060002054166040519015158152f35b34610169576020600319360112610169576001600160a01b03611e3061343d565b1660005260056020526020604060002054604051908152f35b3461016957604060031936011261016957611e6261343d565b6024359067ffffffffffffffff90818311610169573660238401121561016957826004013591821161016957366024838501011161016957611f446001600160a01b03809216928360005260209460058652611ec460406000205446016151d5565b906024611ed183516151d5565b91611f3a603a60405180968c611f2b818401987f19457468657265756d205369676e6564204d6573736167653a0a0000000000008a52611f1981518092858989019101615020565b84019183519384918785019101615020565b0103601a810187520185613508565b019151902061515c565b16811480611fd0575b15611fa657600560405183810190428252848152611f6a816134ec565b5190209282600052526040600020918254018092557f8ca15a4665cc6fff23311db04eee49bb4a10bd9e962e0b5865f4dd17aac03477600080a3005b60046040517fd8aa2541000000000000000000000000000000000000000000000000000000008152fd5b50801515611f4d565b34610169576040600319360112610169576001600160a01b03611ffa61343d565b1660005260016020526040600020602435600052602052602060ff604060002054166040519015158152f35b60606003193601126101695761203a61343d565b9067ffffffffffffffff602435116101695761010060031960243536030112610169576001600054116134155750600260005561207c600460243501806135c8565b6120906044602435016024356004016135fb565b9161209a81615278565b6102556120a8610653615043565b519020916120b784828561515c565b600094909185916120cd600460243501806135c8565b9042606083013511611d8e5742608083013510611d64576001600160a01b038516600052600560205260406000205460e083013503611d3a578160c08a93013561322d575b60a0810135806131ee575b5061010061212b9101614b86565b613164575b505050612140604084018461364c565b9061214f60c4602435016136a0565b9160005b81811061306d575050505061216b60208401846136b4565b9050612868575b1561285e5761218861077160e4602435016136a0565b929060005b8481106121d7576024803501356001600160a01b038916877f9d45e8614d63fdcb7d8e231afe42fcd0366c2c2d3792a5df9954be4fd5d61e3c600080a447806107c0576001600055005b6121e2818684614c82565b906121ec826136a0565b6001600160a01b038116600052600360205260406000206001600160a01b03871660005260205260ff6040600020541615610f9f576001600160a01b038116600052600160205260406000208860005260205260ff60406000205416610f75576001600160a01b0389168061282c575b5060608301359260c081013560a082013561227960208401614b86565b604061228e6024803501356080870135614ba3565b940135600381036124ec575050908791855b888c828181106124ba575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018914159150612376905057509183916122e7938887614ca8565b6001600160a01b0382163b156101695760848660006001600160a01b0381958f98958296836040519b8c998a987fcb4ef4e4000000000000000000000000000000000000000000000000000000008a5216600489015216602487015260448601526064850152165af191821561096357600192612367575b505b0161218d565b612370906134a9565b8961235f565b9496505050505061238a6109818383614bb6565b906123986109818483614bb6565b926000915b878a82841061246a575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff915001916001600160a01b0384163b15610169576001600160a01b039384600081898f9561244190610a3585996040519c8d9a8b998a977f613ce049000000000000000000000000000000000000000000000000000000008952166004880152166024860152608060448601526084850190614c4e565b0393165af19182156109635760019261245b575b50612361565b612464906134a9565b89612455565b92600192939161247c8285948c614c82565b612498606082013591610a9e6024803501356080830135614ba3565b6124a28789614c3a565b526124ad8689614c3a565b520192019091909161239d565b610af46124d3916001600160a01b0393848c1695614c82565b16036124e4578993506001016122a0565b888c826122ab565b600281989493929598146000146126dc5750801590811580926126d3575b612616575b5050508115801561260c575b1561258f5750610ba9576001600160a01b0381163b15610169576040517f82b1c4230000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152808c1660248301526044820194909452926000918491829084908260648101612441565b9350506001600160a01b0381163b15610169576040517f5598d9670000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301528b81166024830152604482019490945292600091849160649183918591165af19182156109635760019261245b5750612361565b506001851161251b565b6040517fc035f9b50000000000000000000000000000000000000000000000000000000081526001600160a01b038b1660048201526040816024816001600160a01b038b165afa9283156109635789906000926000956126ac575b50612696575b915050821561250f5761268991614b4a565b11610ce6578c808661250f565b61269f91614b4a565b11610d2a578e8088612677565b9094506126c991925060403d604011610d8057610d718183613508565b9190919338612671565b5082151561250a565b9193509150600103610eef5780159081158092612823575b612766575b5050506001600160a01b0381163b15610169576040517fc6c3bbe60000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152808c1660248301526044820194909452926000918491829084908260648101612441565b6040517fe158dfdc0000000000000000000000000000000000000000000000000000000081526001600160a01b03891660048201526040816024816001600160a01b0389165afa9283156109635787906000926000956127fc575b506127e6575b91505082156126f9576127d991614b4a565b11610ce6578a80846126f9565b6127ef91614b4a565b11610d2a578c80866127c7565b90945061281991925060403d604011610d8057610d718183613508565b91909193386127c1565b508215156126f4565b6001600160a01b038216600052600460205260406000209060005260205260ff6040600020541615610f4b578a61225c565b6121888592610773565b61287560208401846136b4565b9061288a60a460243501602435600401613708565b9091600091825b8584106128a357505050505050612172565b6128ae848785614bc3565b906128b8826136a0565b916128c560208201614b86565b906040810135916128df60248035013560a0840135614ba3565b9260038103612cf65750875b8a8110612cc9575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018903612aad5750612a6c575b60600135806129c15750612937828589613549565b35906001600160a01b0384163b15610169576064600092836001600160a01b0360405197889586947f1227fe8600000000000000000000000000000000000000000000000000000000865233600487015260248601526044850152165af19081156109635760019283926129b2575b505b01935b0192612891565b6129bb906134a9565b8e6129a6565b6001036111db576129d3828589613549565b35906001600160a01b0384163b156101695760c4600092836001600160a01b0360405197889586947ff242432a00000000000000000000000000000000000000000000000000000000865233600487015261dead60248701526044860152606485015260a060848501528260a4850152165af1908115610963576001928392612a5d575b506129a8565b612a66906134a9565b8e612a57565b612a7783868a613549565b35608082013503156129225760046040517f4d9c9be5000000000000000000000000000000000000000000000000000000008152fd5b919397925050612ac06109818383614bb6565b91612ace6109818284614bb6565b9160005b818310612c3b5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01926060013580612b9857506001600160a01b0384163b1561016957612b6f9361130960006001600160a01b038195604051988996879586937f092c8aa5000000000000000000000000000000000000000000000000000000008552336004860152606060248601526064850190614c4e565b0393165af191821561096357600192612b89575b506129ab565b612b92906134a9565b8d612b83565b909391906001036111db576001600160a01b0382163b15610169576000916113c291836001600160a01b036020612c12604051998a9788967f2eb2c2d600000000000000000000000000000000000000000000000000000000885233600489015261dead602489015260a0604489015260a4880190614c4e565b838582039160031983016084880152520193165af191821561096357600192612b8957506129ab565b91612c4a818d8b9c949c614bc3565b9082898d612c5a60208601614b86565b94612c6e60248035013560a0830135614ba3565b95612caa575b5093612c87600195938695938695613549565b35612c92888b614c3a565b52612c9d8789614c3a565b5201930191019890612ad2565b92608092612cb792613549565b359101350361121d5782898d38612c74565b8a6001600160a01b03612ce3610af484838b16948d614bc3565b1603612cf1576001016128eb565b6128f3565b9397949390919060028103612fe35750606081013560018103612e8857506001831115612dcc575061158d5760005b818110612d38575050506001905b6129ab565b612d4387868a613549565b35906001600160a01b0384163b1561016957604051917f23b872dd00000000000000000000000000000000000000000000000000000000835233600484015261dead60248401526044830152600082606481836001600160a01b0389165af1908115610963576001928392612dbd575b5001960195612d25565b612dc6906134a9565b38612db3565b915095919295612e6c575b50612de3818488613549565b356001600160a01b0383163b15610169576001600160a01b039260646000928360405196879485937f23b872dd00000000000000000000000000000000000000000000000000000000855233600486015261dead60248601526044850152165af1908115610963576001928392612e5d575b5001936129ab565b612e66906134a9565b8e612e55565b6080612e7983868a613549565b359101350361121d578d612dd7565b929493926111db576001851115612f3b575061158d57612ea783614beb565b9260005b818110612f175750506001600160a01b0381163b1561016957612b6f6000916001600160a01b0394836040519687809581947f7d3c5ebe000000000000000000000000000000000000000000000000000000008352336004840152604060248401526044830190614c4e565b60018091612f268a898d613549565b35612f318289614c3a565b5201970196612eab565b919350959195612fc7575b50612f52818488613549565b35916001600160a01b0381163b15610169576040517f6621a02500000000000000000000000000000000000000000000000000000000815233600482015260248101939093526000908390604490829084906001600160a01b03165af1908115610963576001928392612e5d575001936129ab565b6080612fd483868a613549565b359101350361121d578d612f46565b9294939290915060010361186157606001356001810361300c5750600192612d33913390614ef6565b6111db576001600160a01b0381163b15610169576040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810193909352600090839081836001600160a01b038260448101612b6f565b613078818385614b93565b9061308c6024803501356060840135614ba3565b6020830135806130f557506001926001600160a01b0387161580156130e9575b156130c757906118e060406130c193016136a0565b01612153565b6118e060406119196130e494612710611908608087013583614ba3565b6130c1565b506080810135156130ac565b6001036119b6576001926001600160a01b038716158015613158575b1561312957908161196560406119196130e4956136a0565b61199b6130e492612710613141608085013583614ba3565b0490611914828b613151876136a0565b3390614f70565b50608081013515613111565b6131d69397509060349291611a4f6131866064602435016024356004016135fb565b959094836040519485927fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602085019860601b168852848401378101600083820152036014810184520182613508565b936001600160a01b03851615610f4b57868681612130565b909250876000526002602052604060002061320f6024803501358254614b4a565b905587600052600260205260406000205411611aa95788918a61211d565b613282613244608460243501602435600401613708565b9060405160208101907fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b16825260148152611b28816134ec565b612112579350905061329860e4602435016136a0565b6001600160a01b0381166132d05760046040517fb05e92fa000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b03600654166040517f9c395bc20000000000000000000000000000000000000000000000000000000081526001600160a01b038b1660048201526001600160a01b0383166024820152602081604481855afa908115610963576000916133f6575b5015613367575b5061335890611c02608460243501602435600401613708565b15611c5b578790600193612112565b60206001600160a01b0360648c60405194859384927f90c9a2d00000000000000000000000000000000000000000000000000000000084521660048301526001600160a01b03871660248301523060448301525afa908115610963576000916133d7575b5015611c5b578961333f565b6133f0915060203d602011611d1457611d068183613508565b8a6133cb565b61340f915060203d602011611d1457611d068183613508565b8b613338565b807f0db255a60000000000000000000000000000000000000000000000000000000060049252fd5b600435906001600160a01b038216820361016957565b602435906001600160a01b038216820361016957565b9181601f840112156101695782359167ffffffffffffffff8311610169576020808501948460051b01011161016957565b60243590811515820361016957565b67ffffffffffffffff81116134bd57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff8211176134bd57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176134bd57604052565b91908110156135595760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b91908110156135595760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0181360301821215610169570190565b9035907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee181360301821215610169570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610169570180359067ffffffffffffffff82116101695760200191813603831361016957565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610169570180359067ffffffffffffffff8211610169576020019160a082023603831361016957565b356001600160a01b03811681036101695790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610169570180359067ffffffffffffffff8211610169576020019160c082023603831361016957565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610169570180359067ffffffffffffffff821161016957602001918160051b3603831361016957565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610169570180359067ffffffffffffffff8211610169576020019160e082023603831361016957565b906137bb81806135c8565b906137c960408201826135fb565b906137d384615278565b6102556137e1610653615043565b519020936137f083838761515c565b9160009060009461380187806135c8565b9042606083013511611d8e5742608083013510611d64576001600160a01b03861687526005602052604087205460e083013503611d3a578160c08b930135614984575b60a08101358061494a575b5061010061385d9101614b86565b6148ca575b505050613872604083018361364c565b9061387f60c088016136a0565b9160005b8181106147eb57505050506020820161389c81846136b4565b9050613fdd575b5015613fd3576138bf6138b860e086016136a0565b918061375c565b60009391935b81811061390a5750505050505060206001600160a01b039101359216907f9d45e8614d63fdcb7d8e231afe42fcd0366c2c2d3792a5df9954be4fd5d61e3c600080a490565b613915818387614c82565b9061391f826136a0565b916001600160a01b038316600052600360205260406000206001600160a01b03861660005260205260ff6040600020541615610f9f576001600160a01b038316600052600160205260406000208a60005260205260ff60406000205416610f75576001600160a01b03881680613f7e575b5060608101359260c082013560a08301358b60406139c160206139b4818901614b86565b9301356080880135614ba3565b95013560038103613c2a575050908891855b888110613bfa575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018703613aa157508392613a1c928692896001600160a01b0397614ca8565b1692833b156101695760848760008e9681956001600160a01b0395866040519a8b9889977fcb4ef4e4000000000000000000000000000000000000000000000000000000008952166004880152166024860152604485015260648401525af191821561096357600192613a92575b505b016138c5565b613a9b906134a9565b38613a8a565b9450505050919250613ab66109818483614bb6565b92613ac46109818284614bb6565b916000905b888c888c848710613b99575050505050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b039101921692833b15610169576001600160a01b0393846000898f948296610a35613b71926040519b8c998a9889977f613ce049000000000000000000000000000000000000000000000000000000008952166004880152166024860152608060448601526084850190614c4e565b03925af191821561096357600192613b8a575b50613a8c565b613b93906134a9565b38613b84565b91613bdb613bb08860019798999594889795614c82565b613bc7602060608301359401356080830135614ba3565b93849160c08101359060a00135858e614ca8565b613be5878b614c3a565b52613bf08688614c3a565b5201920190613ac9565b8b6001600160a01b03613c14610af4848d848b1695614c82565b1603613c25578a93506001016139d3565b6139db565b6002819894939295969814600014613e2f575080159081158092613e26575b613d6a575b50505081158015613d60575b15613ce35750610ba9576001600160a01b0381163b15610169576040517f82b1c4230000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152808d16602483015260448201949094529260009184918290849082606481015b0393165af191821561096357600192613b8a5750613a8c565b9350506001600160a01b0381163b15610169576040517f5598d9670000000000000000000000000000000000000000000000000000000081526001600160a01b0387811660048301528c81166024830152604482019490945292600091849160649183918591165af191821561096357600192613b8a5750613a8c565b5060018511613c5a565b6040517fc035f9b50000000000000000000000000000000000000000000000000000000081526001600160a01b038c1660048201526040816024816001600160a01b038b165afa9283156109635789906000928395613dff575b50613de9575b9150508215613c4e57613ddc91614b4a565b11610ce657388086613c4e565b613df291614b4a565b11610d2a57388088613dca565b909450613e1c91925060403d604011610d8057610d718183613508565b9190919338613dc4565b50821515613c49565b9193509150600103610eef5780159081158092613f75575b613eb9575b5050506001600160a01b0381163b15610169576040517fc6c3bbe60000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152808d1660248301526044820194909452926000918491829084908260648101613cca565b6040517fe158dfdc0000000000000000000000000000000000000000000000000000000081526001600160a01b038a1660048201526040816024816001600160a01b0389165afa9283156109635787906000928395613f4e575b50613f38575b9150508215613e4c57613f2b91614b4a565b11610ce657388084613e4c565b613f4191614b4a565b11610d2a57388086613f19565b909450613f6b91925060403d604011610d8057610d718183613508565b9190919338613f13565b50821515613e47565b6001600160a01b0384166000526004908160205260406000209060005260205260ff60406000205416613990576040517f2f58c7cd000000000000000000000000000000000000000000000000000000008152fd5b6138bf8691610773565b613fea90839992996136b4565b613ffa60a0889493940188613708565b939092936000935b83851061401557505050505096386138a3565b9091929394614025868686614bc3565b908a614030836136a0565b9261403d60208201614b86565b6140546020604084013594013560a0840135614ba3565b926003810361447e5750895b888a8281811061444f575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018d1415915061422c905057506141eb575b606001358061414057506140b3828686613549565b35906001600160a01b0384163b15610169576064600092836001600160a01b0360405197889586947f1227fe8600000000000000000000000000000000000000000000000000000000865233600487015260248601526044850152165af1908115610963576001928392614131575b505b01955b0193929190614002565b61413a906134a9565b38614122565b6001036111db57614152828686613549565b35906001600160a01b0384163b156101695760c4600092836001600160a01b0360405197889586947ff242432a00000000000000000000000000000000000000000000000000000000865233600487015261dead60248701526044860152606485015260a060848501528260a4850152165af19081156109635760019283926141dc575b50614124565b6141e5906134a9565b386141d6565b6141f6838787613549565b356080820135031561409e5760046040517f4d9c9be5000000000000000000000000000000000000000000000000000000008152fd5b9250509197806142406109818f9385614bb6565b9261424e6109818383614bb6565b926000905b8284106143ca575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192606001358061431a57506001600160a01b0384163b15610169576142f19361130960006001600160a01b038195604051988996879586937f092c8aa5000000000000000000000000000000000000000000000000000000008552336004860152606060248601526064850190614c4e565b0393165af19182156109635760019261430b575b50614127565b614314906134a9565b38614305565b6001036111db576001600160a01b0384163b15610169576143a593600092836001600160a01b03602061439295836040519a8b9889977f2eb2c2d60000000000000000000000000000000000000000000000000000000089523360048a015261dead60248a015260a060448a015260a4890190614c4e565b60031993848983030160648a0152614c4e565b8681039283016084880152520193165af19182156109635760019261430b5750614127565b6143db848d949e948d969496614bc3565b6143f860206143eb818401614b86565b93013560a0830135614ba3565b91614433575b5061440a838b8b613549565b356144158588614c3a565b526144208486614c3a565b52600180809201930191019a908f614253565b6080614440858d8d613549565b359101350361121d57386143fe565b610af4614468916001600160a01b0393848c1695614bc3565b160361447657600101614060565b888a8261406b565b939994939091906002810361476a575060608101356001810361460757506001831115614554575061158d5760005b8181106144c0575050506001905b614127565b6144cb898787613549565b35906001600160a01b0384163b1561016957604051917f23b872dd00000000000000000000000000000000000000000000000000000000835233600484015261dead60248401526044830152600082606481836001600160a01b0389165af1908115610963576001928392614545575b50019801976144ad565b61454e906134a9565b3861453b565b91509792976145eb575b506001600160a01b031690614574818585613549565b35823b15610169576000926064849260405195869384927f23b872dd00000000000000000000000000000000000000000000000000000000845233600485015261dead602485015260448401525af19081156109635760019283926145dc575b500195614127565b6145e5906134a9565b386145d4565b60806145f8848787613549565b359101350361121d573861455e565b929493926111db5760018511156146cb575061158d5761462683614beb565b9260005b8181106146a75750506001600160a01b0316803b156101695761468f6000939184926040519586809481937f7d3c5ebe000000000000000000000000000000000000000000000000000000008352336004840152604060248401526044830190614c4e565b03925af19182156109635760019261430b5750614127565b600180916146b68c8a8a613549565b356146c18289614c3a565b520199019861462a565b919298935061474e575b506001600160a01b0316906146eb818585613549565b3591803b15610169576040517f6621a02500000000000000000000000000000000000000000000000000000000815233600482015260248101939093526000908390604490829084905af19081156109635760019283926145dc57500195614127565b608061475b848787613549565b359101350361121d57386146d5565b92949392600192508203611861576060013590810361479257506001926144bb913390614ef6565b6111db576001600160a01b0316803b15610169576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481019390935260009083908183816044810161468f565b6147f6818385614b93565b9061480960208b01356060840135614ba3565b60208301358061487257506001926001600160a01b038716158015614866575b1561484457906118e0604061483e93016136a0565b01613883565b6118e0604061191961486194612710611908608087013583614ba3565b61483e565b50608081013515614829565b6001036119b6576001926001600160a01b0387161580156148be575b156148a65790816119656040611919614861956136a0565b61199b61486192612710613141608085013583614ba3565b5060808101351561488e565b90614932939691611a4f60346148e360608c018c6135fb565b969095846040519586937fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602086019960601b1689528585013782019083820152036014810184520182613508565b926001600160a01b03841615610f4b57388781613862565b90925089885260026020526040882061496860208b01358254614b4a565b90558988526002602052604088205411611aa95789913861384f565b61499461324460808b018b613708565b61384457935090506149a860e088016136a0565b6001600160a01b0381166149e05760046040517fb05e92fa000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b03600654166040517f9c395bc20000000000000000000000000000000000000000000000000000000081526001600160a01b038c1660048201526001600160a01b0383166024820152602081604481855afa908115614b27578991614b08575b5015614a6f575b50614a6090611c0260808a018a613708565b15611c5b578890600193613844565b60206001600160a01b0360648d60405194859384927f90c9a2d00000000000000000000000000000000000000000000000000000000084521660048301526001600160a01b03871660248301523060448301525afa908115614afd578891614ade575b5015611c5b5738614a4e565b614af7915060203d602011611d1457611d068183613508565b38614ad2565b6040513d8a823e3d90fd5b614b21915060203d602011611d1457611d068183613508565b38614a47565b6040513d8b823e3d90fd5b90816020910312610169575180151581036101695790565b91908201809211614b5757565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b3580151581036101695790565b91908110156135595760a0020190565b81810292918115918404141715614b5757565b91908203918211614b5757565b91908110156135595760c0020190565b67ffffffffffffffff81116134bd5760051b60200190565b90614bf582614bd3565b614c026040519182613508565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0614c308294614bd3565b0190602036910137565b80518210156135595760209160051b010190565b90815180825260208080930193019160005b828110614c6e575050505090565b835185529381019392810192600101614c60565b91908110156135595760e0020190565b9190826040910312610169576020825192015190565b94919093929381159384158095614dea575b614cc8575b50505050505050565b604080517f399297250000000000000000000000000000000000000000000000000000000081526001600160a01b039283166004820152602481019390935296879183916044918391165afa938415614ddf576000918295614dbc575b508390614d7d575b50505082614d3e575b808080614cbf565b614d4791614b4a565b11614d5457808080614d36565b600490517f94d7a276000000000000000000000000000000000000000000000000000000008152fd5b614d8691614b4a565b11614d9357388082614d2d565b600484517f3e0866c7000000000000000000000000000000000000000000000000000000008152fd5b614dd7919550849250873d8911610d8057610d718183613508565b949091614d25565b86513d6000823e3d90fd5b50851515614cba565b6001600160a01b038291600080809481948294165af1903d15614ef0573d9067ffffffffffffffff8211614ec35760405191614e5760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184613508565b825260203d92013e5b15614e685750565b471015614e995760046040517fcd1c8867000000000000000000000000000000000000000000000000000000008152fd5b60046040517ff499da20000000000000000000000000000000000000000000000000000000008152fd5b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526041600452fd5b50614e60565b606460209293600060405195869485937f23b872dd0000000000000000000000000000000000000000000000000000000085526001600160a01b03809316600486015261dead60248601526044850152165af1801561096357614f565750565b614f6d9060203d8111611d1457611d068183613508565b50565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b03928316600482015292821660248401526044830193909352909160209183916064918391600091165af1801561096357614f565750565b81939293614fe4575b50501490565b60059291831b8101915b8135808211851b918252602080921852604060002091019282841015615015579290614fee565b509150503880614fde565b60005b8381106150335750506000910152565b8181015183820152602001615023565b7f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000030147f0000000000000000000000000000000000000000000000000000000000000000461416156150b357565b905060405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176134bd5760405251902090565b90916041036151ce57600082604082940135821a92601b841415806151c3575b15615188575050505090565b6020608092819560405193845282840152803560408401520135606082015282805260015afa156151b7575190565b604051903d90823e3d90fd5b50601c84141561517c565b5050600090565b9060405160a081016040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608082019360008552935b0192600a90818106603001855304928315615248577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9061520c565b92506080837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09203019201918252565b615282818061375c565b6060916000915b808310615550575050508051602080920120916152a8828201826136b4565b6060916000915b808310615468575050508281519101206040916152ce8382018261364c565b6060916000915b80831061538a5750505090818560e09351910120610100906152f8828401614b86565b948651978801987f352afb97db53d33e87be729b9d4e587ca2de5d80c540a656d64ac4ab3d244c5f8a528789015260608801526080870152606082013560a0870152608082013560c087015260a08201358387015260c082013590860152013561012084015261014090151581840152825261016082019082821067ffffffffffffffff8311176134bd575251902090565b909192615398848385614b93565b906153a2826136a0565b6153ad8984016136a0565b928951938b8501927fc4cb1148475c5cce4dc4ac1da9b1e88f0c270c5e7279b915db40949117e8c31784526001600160a01b038091168c8701528c83013560608701526080911681860152606082013560a086015260c091013581850152835260e083019183831067ffffffffffffffff8411176134bd576001938b8b9261545f94868552835190209061544c81518092610100958688019101615020565b830191820152038b810184520182613508565b930191906152d5565b909192615476848385614bc3565b61547f816136a0565b9161548b888301614b86565b916040908151936001600160a01b038b8601967f6123f3e52d7d4c81d116bd2cc2f3037b6bf3584638afdff0e0abd37a007463d888521683860152151560608501526080828201358186015260a09060608301358287015282013560c086015260e091013581850152835261010083019280841067ffffffffffffffff8511176134bd578961554793600196868552835190209061553481518092610120958688019101615020565b8301918201520389810184520182613508565b930191906152af565b90919261555e848385614c82565b615567816136a0565b602091615575838201614b86565b926040918251946001600160a01b03838701957fc566908c5227968aab2e8cab737a01e51d99317b10b3d5e2ae287e2ebff502f387521684870152151560608601526080838201358187015260a060608301358188015260c0918301358288015282013560e087015261010091013581860152845261012084019380851067ffffffffffffffff8611176134bd57600195615639948685528251902081516156268161014094878688019101615020565b8301918201520390810184520182613508565b9301919061528956fea26469706673582212209800c7c36427b365258d82fa3295222ea58e922efa24ba7e6b17182b8baae45e64736f6c63430008140033

Deployed Bytecode

0x608080604052600436101561001357600080fd5b60003560e01c90816303714b6c14612026575080630b5220cf14611fd9578063119f56e014611e4957806322f0e36f14611e0f57806325c09a3d14611db85780632c09294a146105db57806338c09cc5146105645780636825fbe01461053857806380ce83c31461047c57806391b245b31461041357806393b670ea1461036e578063942943f91461028c578063b2b7ad92146101c5578063dadea50c1461016e5763fd0f4a4a146100c457600080fd5b34610169576040600319360112610169576100dd61343d565b6100e561349a565b3360005260046020526001600160a01b0360406000209216918260005260205261013e8160406000209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b151590337ff3e08db8f80606a00ef8635b0c80c615721eca7f1c250353231ebdd0f768dff7600080a4005b600080fd5b346101695760406003193601126101695761018761343d565b61018f613453565b906001600160a01b03809116600052600460205260406000209116600052602052602060ff604060002054166040519015158152f35b3461016957600319602081360112610169576004359067ffffffffffffffff82116101695761012090823603011261016957610205602091600401615278565b610255610281610213615043565b92604051928391868301958690916042927f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201520190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282613508565b519020604051908152f35b346101695760406003193601126101695760043567ffffffffffffffff8111610169576102bd903690600401613469565b6102c561349a565b8015159060005b8381106102d557005b3360005260019083602083815260406000206102f284898b613549565b3560005281526103318560406000209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b7fb0aa5effc586eb20f130429a2f29677698e9f92786a6bef6a3ad0cbc14b0b52d61035d84898b613549565b35916040519283523392a3016102cc565b346101695760406003193601126101695761038761343d565b61038f61349a565b3360005260036020526001600160a01b036040600020921691826000526020526103e88160406000209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b151590337f6a0dc189effd165f709551bb21684c2b4595fde0a2d4bc71eac5fe81379f0a62600080a4005b346101695760006003193601126101695760405160208101904282526020815261043c816134ec565b519020336000526005602052604060002090815401809155337f8ca15a4665cc6fff23311db04eee49bb4a10bd9e962e0b5865f4dd17aac03477600080a3005b60606003193601126101695761049061343d565b60243567ffffffffffffffff8111610169576104b0903690600401613469565b90600192836000541161050e576002600055600090846000925b8584106104ef575047806104df575b50600055005b6104e99033614df3565b816104d9565b610504906104fe858888613588565b846137b0565b92019185906104ca565b60046040517f0db255a6000000000000000000000000000000000000000000000000000000008152fd5b346101695760206003193601126101695760043560005260026020526020604060002054604051908152f35b60206003193601126101695760043567ffffffffffffffff811161016957610590903690600401613469565b600191826000541161050e5760026000556000836000915b8483106105bc575047806104df5750600055005b6105d1906105cb848787613588565b336137b0565b91019084906105a8565b60206003193601126101695767ffffffffffffffff6004351161016957610100600319600435360301126101695760016000541161050e5760026000556106266004803501806135c8565b61063a6044600435016004356004016135fb565b909161064581615278565b610255610696610653615043565b9260405192839160208301958690916042927f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201520190565b519020926106a583828661515c565b600093909184916106ba6004803501806135c8565b42606082013511611d8e5742608082013510611d64576001600160a01b038516600052600560205260406000205460e082013503611d3a5760c0810135611ad3575b60a081013580611a6e575b506101006107159101614b86565b6119e0575b5050610729604084018461364c565b9061073860c4600435016136a0565b9160005b81811061188b575050505061075460208401846136b4565b9050610fd3575b15610fc95761077961077160e4600435016136a0565b925b8061375c565b9060005b8281106107d0576004356024013533887f9d45e8614d63fdcb7d8e231afe42fcd0366c2c2d3792a5df9954be4fd5d61e3c600080a447806107c0575b6001600055005b6107ca9033614df3565b806107b9565b6107db818484614c82565b906107e5826136a0565b6001600160a01b038116600052600360205260406000206001600160a01b03871660005260205260ff6040600020541615610f9f576001600160a01b038116600052600160205260406000208960005260205260ff60406000205416610f75576001600160a01b03881680610f19575b5061086260208401614b86565b610876602460043501356080860135614ba3565b90604085013560038103610b0c575050825b868110610ad4575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101840361096f57506108d4818960c087013560a0880135606089013587614ca8565b6001600160a01b0382163b156101695760848860006001600160a01b038195819560606040519a8b9889977fcb4ef4e4000000000000000000000000000000000000000000000000000000008952166004880152336024880152013560448601526064850152165af191821561096357600192610954575b505b0161077d565b61095d906134a9565b8861094c565b6040513d6000823e3d90fd5b92919350506109866109818284614bb6565b614beb565b916109946109818383614bb6565b916000915b808210610a7057507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff915001916001600160a01b0384163b1561016957610a35936001600160a01b036000818b610a4783976040519a8b98899788957f613ce049000000000000000000000000000000000000000000000000000000008752166004860152336024860152608060448601526084850190614c4e565b90600319848303016064850152614c4e565b0393165af191821561096357600192610a61575b5061094e565b610a6a906134a9565b88610a5b565b906001818b610a8183948c8c614c82565b610ab2606082013591610a9e602460043501356080830135614ba3565b93849160c08101359060a00135858f614ca8565b610abc878a614c3a565b52610ac78688614c3a565b5201920190919091610999565b6001600160a01b0383166001600160a01b03610af9610af4848b8b614c82565b6136a0565b1603610b0757600101610888565b610890565b9194909160028103610d94575060a08101351580158091610d87575b610c5c575b5081158015610c52575b15610bd35750610ba9576001600160a01b0381163b15610169576040517f82b1c4230000000000000000000000000000000000000000000000000000000081526001600160a01b0380891660048301523360248301526044820194909452926000918491829084908260648101610a47565b60046040517f5505f367000000000000000000000000000000000000000000000000000000008152fd5b9350506001600160a01b0381163b15610169576040517f5598d9670000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015233602483015260609490940135604482015292600091849160649183918591165af191821561096357600192610a61575061094e565b5060018511610b37565b6040517fc035f9b50000000000000000000000000000000000000000000000000000000081526001600160a01b038b1660048201526040816024816001600160a01b0389165afa91821561096357600091600093610d54575b50610d10575b5060c0820135908682610cd0575b5050610b2d565b610cd991614b4a565b11610ce6578b8086610cc9565b60046040517f94d7a276000000000000000000000000000000000000000000000000000000008152fd5b610d1f8760a085013592614b4a565b11610d2a578c610cbb565b60046040517f3e0866c7000000000000000000000000000000000000000000000000000000008152fd5b909250610d79915060403d604011610d80575b610d718183613508565b810190614c92565b918e610cb5565b503d610d67565b5060c08201351515610b28565b909150600103610eef5760a0810135159081158092610ee2575b610e1d575b50506001600160a01b0381163b15610169576040517fc6c3bbe60000000000000000000000000000000000000000000000000000000081526001600160a01b0380891660048301523360248301526044820194909452926000918491829084908260648101610a47565b6040517fe158dfdc0000000000000000000000000000000000000000000000000000000081526001600160a01b038a1660048201526040816024816001600160a01b0388165afa92831561096357600091600094610ebf575b50610ea5575b5060c00135908482610e8f575b50610db3565b610e9891614b4a565b11610ce657898084610e89565b610eb48660a084013592614b4a565b11610d2a578b610e7c565b909350610edb915060403d604011610d8057610d718183613508565b928d610e76565b5060c08101351515610dae565b60046040517f71e36489000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b038216600052600460205260406000209060005260205260ff6040600020541615610f4b5789610855565b60046040517f2f58c7cd000000000000000000000000000000000000000000000000000000008152fd5b60046040517f37e8456b000000000000000000000000000000000000000000000000000000008152fd5b60046040517fa48ee854000000000000000000000000000000000000000000000000000000008152fd5b6107793392610773565b610fe060208401846136b4565b90610ff560a460043501600435600401613708565b91600091825b85841061100d5750505050505061075b565b611018848785614bc3565b90611022826136a0565b9161102f60208201614b86565b9060408101359161104a6024600435013560a0840135614ba3565b92600381036114b95750875b8a811061148c575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810189036112475750611205575b606081013561112c57506110a2828886613549565b35906001600160a01b0384163b15610169576064600092836001600160a01b0360405197889586947f1227fe8600000000000000000000000000000000000000000000000000000000865233600487015260248601526044850152165af190811561096357600192839261111d575b505b01935b0192610ffb565b611126906134a9565b8d611111565b606001356001036111db57611142828886613549565b35906001600160a01b0384163b156101695760c4600092836001600160a01b0360405197889586947ff242432a00000000000000000000000000000000000000000000000000000000865233600487015261dead60248701526044860152606485015260a060848501528260a4850152165af19081156109635760019283926111cc575b50611113565b6111d5906134a9565b8d6111c6565b60046040517f89248e16000000000000000000000000000000000000000000000000000000008152fd5b611210838987613549565b356080820135031561108d575b60046040517f4d9c9be5000000000000000000000000000000000000000000000000000000008152fd5b91939792505061125a6109818383614bb6565b916112686109818284614bb6565b9160005b8183106113fd5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192606081013561134457506001600160a01b0384163b156101695761131b9361130960006001600160a01b038195604051988996879586937f092c8aa5000000000000000000000000000000000000000000000000000000008552336004860152606060248601526064850190614c4e565b90600319848303016044850152614c4e565b0393165af191821561096357600192611335575b50611116565b61133e906134a9565b8c61132f565b90939190606001356001036111db576001600160a01b0382163b15610169576000916113c291836001600160a01b0360206113d4604051998a9788967f2eb2c2d600000000000000000000000000000000000000000000000000000000885233600489015261dead602489015260a0604489015260a4880190614c4e565b90600319878303016064880152614c4e565b838582039160031983016084880152520193165af1918215610963576001926113355750611116565b9161140c818d8b9c949c614bc3565b90828c8a61141c60208601614b86565b946114316024600435013560a0830135614ba3565b9561146d575b509361144a600195938695938695613549565b35611455888b614c3a565b526114608789614c3a565b520193019101989061126c565b9260809261147a92613549565b359101350361121d57828c8a38611437565b8a6001600160a01b036114a6610af484838b16948d614bc3565b16036114b457600101611056565b61105e565b93979493909190600281036117d3575060608101356001036116735760018311156115b7575061158d5760005b8181106114f9575050506001905b611116565b611504878987613549565b35906001600160a01b0384163b1561016957604051917f23b872dd00000000000000000000000000000000000000000000000000000000835233600484015261dead60248401526044830152600082606481836001600160a01b0389165af190811561096357600192839261157e575b50019601956114e6565b611587906134a9565b38611574565b60046040517ff143a830000000000000000000000000000000000000000000000000000000008152fd5b915095919295611657575b506115ce818785613549565b356001600160a01b0383163b15610169576001600160a01b039260646000928360405196879485937f23b872dd00000000000000000000000000000000000000000000000000000000855233600486015261dead60248601526044850152165af1908115610963576001928392611648575b500193611116565b611651906134a9565b8d611640565b6080611664838987613549565b359101350361121d578c6115c2565b9193929160608101356111db57600185111561172b575061158d5761169783614beb565b9260005b8181106117075750506001600160a01b0381163b156101695761131b6000916001600160a01b0394836040519687809581947f7d3c5ebe000000000000000000000000000000000000000000000000000000008352336004840152604060248401526044830190614c4e565b600180916117168a8c8a613549565b356117218289614c3a565b520197019661169b565b9193509591956117b7575b50611742818785613549565b35916001600160a01b0381163b15610169576040517f6621a02500000000000000000000000000000000000000000000000000000000815233600482015260248101939093526000908390604490829084906001600160a01b03165af190811561096357600192839261164857500193611116565b60806117c4838987613549565b359101350361121d578c611736565b929493929091506001036118615760608101356001036117fc57506001926114f4913390614ef6565b606001356111db576001600160a01b0381163b15610169576040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810193909352600090839081836001600160a01b03826044810161131b565b60046040517fb6166382000000000000000000000000000000000000000000000000000000008152fd5b611896818385614b93565b906118ab602460043501356060840135614ba3565b60208301358061193157506001926001600160a01b038716158015611925575b156118eb57906118e060406118e593016136a0565b614df3565b0161073c565b6118e0604061191961192094612710611908608087013583614ba3565b0490611914828d614df3565b614bb6565b92016136a0565b6118e5565b506080810135156118cb565b6001036119b6576001926001600160a01b0387161580156119aa575b1561196d5790816119656040611919611920956136a0565b903390614f70565b61199b61192092612710611985608085013583614ba3565b0490611914828b33611996886136a0565b614f70565b906119656040611919836136a0565b5060808101351561194d565b60046040517f2a807f24000000000000000000000000000000000000000000000000000000008152fd5b611a579295506119fa6064600435016004356004016135fb565b929091611a4f603460405183819460208301967fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b168852848401378101600083820152036014810184520182613508565b51902061515c565b926001600160a01b03841615610f4b57858061071a565b8860005260026020526040600020611a8d602460043501358254614b4a565b905588600052600260205260406000205411611aa95788610707565b60046040517ff3c02f73000000000000000000000000000000000000000000000000000000008152fd5b611b37611aea608460043501600435600401613708565b9060405160208101907fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16825260148152611b28816134ec565b5190209160c085013591614fd5565b6106fc579250611b4b60e4600435016136a0565b6001600160a01b038116611b835760046040517fb05e92fa000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b03600654166040517f9c395bc20000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0383166024820152602081604481855afa90811561096357600091611d1b575b5015611c85575b50611c4e90611c02608460043501600435600401613708565b916040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602082019260601b16825260148152611c3f816134ec565b5190209160c087013591614fd5565b15611c5b576001926106fc565b60046040517fb05e92fa000000000000000000000000000000000000000000000000000000008152fd5b6020606491604051928380927f90c9a2d00000000000000000000000000000000000000000000000000000000082523360048301526001600160a01b03871660248301523060448301525afa90811561096357600091611cec575b5015611c5b5788611be9565b611d0e915060203d602011611d14575b611d068183613508565b810190614b32565b89611ce0565b503d611cfc565b611d34915060203d602011611d1457611d068183613508565b8a611be2565b60046040517f172529af000000000000000000000000000000000000000000000000000000008152fd5b60046040517fc0226372000000000000000000000000000000000000000000000000000000008152fd5b60046040517fc10ebb06000000000000000000000000000000000000000000000000000000008152fd5b3461016957604060031936011261016957611dd161343d565b611dd9613453565b906001600160a01b03809116600052600360205260406000209116600052602052602060ff604060002054166040519015158152f35b34610169576020600319360112610169576001600160a01b03611e3061343d565b1660005260056020526020604060002054604051908152f35b3461016957604060031936011261016957611e6261343d565b6024359067ffffffffffffffff90818311610169573660238401121561016957826004013591821161016957366024838501011161016957611f446001600160a01b03809216928360005260209460058652611ec460406000205446016151d5565b906024611ed183516151d5565b91611f3a603a60405180968c611f2b818401987f19457468657265756d205369676e6564204d6573736167653a0a0000000000008a52611f1981518092858989019101615020565b84019183519384918785019101615020565b0103601a810187520185613508565b019151902061515c565b16811480611fd0575b15611fa657600560405183810190428252848152611f6a816134ec565b5190209282600052526040600020918254018092557f8ca15a4665cc6fff23311db04eee49bb4a10bd9e962e0b5865f4dd17aac03477600080a3005b60046040517fd8aa2541000000000000000000000000000000000000000000000000000000008152fd5b50801515611f4d565b34610169576040600319360112610169576001600160a01b03611ffa61343d565b1660005260016020526040600020602435600052602052602060ff604060002054166040519015158152f35b60606003193601126101695761203a61343d565b9067ffffffffffffffff602435116101695761010060031960243536030112610169576001600054116134155750600260005561207c600460243501806135c8565b6120906044602435016024356004016135fb565b9161209a81615278565b6102556120a8610653615043565b519020916120b784828561515c565b600094909185916120cd600460243501806135c8565b9042606083013511611d8e5742608083013510611d64576001600160a01b038516600052600560205260406000205460e083013503611d3a578160c08a93013561322d575b60a0810135806131ee575b5061010061212b9101614b86565b613164575b505050612140604084018461364c565b9061214f60c4602435016136a0565b9160005b81811061306d575050505061216b60208401846136b4565b9050612868575b1561285e5761218861077160e4602435016136a0565b929060005b8481106121d7576024803501356001600160a01b038916877f9d45e8614d63fdcb7d8e231afe42fcd0366c2c2d3792a5df9954be4fd5d61e3c600080a447806107c0576001600055005b6121e2818684614c82565b906121ec826136a0565b6001600160a01b038116600052600360205260406000206001600160a01b03871660005260205260ff6040600020541615610f9f576001600160a01b038116600052600160205260406000208860005260205260ff60406000205416610f75576001600160a01b0389168061282c575b5060608301359260c081013560a082013561227960208401614b86565b604061228e6024803501356080870135614ba3565b940135600381036124ec575050908791855b888c828181106124ba575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018914159150612376905057509183916122e7938887614ca8565b6001600160a01b0382163b156101695760848660006001600160a01b0381958f98958296836040519b8c998a987fcb4ef4e4000000000000000000000000000000000000000000000000000000008a5216600489015216602487015260448601526064850152165af191821561096357600192612367575b505b0161218d565b612370906134a9565b8961235f565b9496505050505061238a6109818383614bb6565b906123986109818483614bb6565b926000915b878a82841061246a575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff915001916001600160a01b0384163b15610169576001600160a01b039384600081898f9561244190610a3585996040519c8d9a8b998a977f613ce049000000000000000000000000000000000000000000000000000000008952166004880152166024860152608060448601526084850190614c4e565b0393165af19182156109635760019261245b575b50612361565b612464906134a9565b89612455565b92600192939161247c8285948c614c82565b612498606082013591610a9e6024803501356080830135614ba3565b6124a28789614c3a565b526124ad8689614c3a565b520192019091909161239d565b610af46124d3916001600160a01b0393848c1695614c82565b16036124e4578993506001016122a0565b888c826122ab565b600281989493929598146000146126dc5750801590811580926126d3575b612616575b5050508115801561260c575b1561258f5750610ba9576001600160a01b0381163b15610169576040517f82b1c4230000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152808c1660248301526044820194909452926000918491829084908260648101612441565b9350506001600160a01b0381163b15610169576040517f5598d9670000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301528b81166024830152604482019490945292600091849160649183918591165af19182156109635760019261245b5750612361565b506001851161251b565b6040517fc035f9b50000000000000000000000000000000000000000000000000000000081526001600160a01b038b1660048201526040816024816001600160a01b038b165afa9283156109635789906000926000956126ac575b50612696575b915050821561250f5761268991614b4a565b11610ce6578c808661250f565b61269f91614b4a565b11610d2a578e8088612677565b9094506126c991925060403d604011610d8057610d718183613508565b9190919338612671565b5082151561250a565b9193509150600103610eef5780159081158092612823575b612766575b5050506001600160a01b0381163b15610169576040517fc6c3bbe60000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152808c1660248301526044820194909452926000918491829084908260648101612441565b6040517fe158dfdc0000000000000000000000000000000000000000000000000000000081526001600160a01b03891660048201526040816024816001600160a01b0389165afa9283156109635787906000926000956127fc575b506127e6575b91505082156126f9576127d991614b4a565b11610ce6578a80846126f9565b6127ef91614b4a565b11610d2a578c80866127c7565b90945061281991925060403d604011610d8057610d718183613508565b91909193386127c1565b508215156126f4565b6001600160a01b038216600052600460205260406000209060005260205260ff6040600020541615610f4b578a61225c565b6121888592610773565b61287560208401846136b4565b9061288a60a460243501602435600401613708565b9091600091825b8584106128a357505050505050612172565b6128ae848785614bc3565b906128b8826136a0565b916128c560208201614b86565b906040810135916128df60248035013560a0840135614ba3565b9260038103612cf65750875b8a8110612cc9575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018903612aad5750612a6c575b60600135806129c15750612937828589613549565b35906001600160a01b0384163b15610169576064600092836001600160a01b0360405197889586947f1227fe8600000000000000000000000000000000000000000000000000000000865233600487015260248601526044850152165af19081156109635760019283926129b2575b505b01935b0192612891565b6129bb906134a9565b8e6129a6565b6001036111db576129d3828589613549565b35906001600160a01b0384163b156101695760c4600092836001600160a01b0360405197889586947ff242432a00000000000000000000000000000000000000000000000000000000865233600487015261dead60248701526044860152606485015260a060848501528260a4850152165af1908115610963576001928392612a5d575b506129a8565b612a66906134a9565b8e612a57565b612a7783868a613549565b35608082013503156129225760046040517f4d9c9be5000000000000000000000000000000000000000000000000000000008152fd5b919397925050612ac06109818383614bb6565b91612ace6109818284614bb6565b9160005b818310612c3b5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01926060013580612b9857506001600160a01b0384163b1561016957612b6f9361130960006001600160a01b038195604051988996879586937f092c8aa5000000000000000000000000000000000000000000000000000000008552336004860152606060248601526064850190614c4e565b0393165af191821561096357600192612b89575b506129ab565b612b92906134a9565b8d612b83565b909391906001036111db576001600160a01b0382163b15610169576000916113c291836001600160a01b036020612c12604051998a9788967f2eb2c2d600000000000000000000000000000000000000000000000000000000885233600489015261dead602489015260a0604489015260a4880190614c4e565b838582039160031983016084880152520193165af191821561096357600192612b8957506129ab565b91612c4a818d8b9c949c614bc3565b9082898d612c5a60208601614b86565b94612c6e60248035013560a0830135614ba3565b95612caa575b5093612c87600195938695938695613549565b35612c92888b614c3a565b52612c9d8789614c3a565b5201930191019890612ad2565b92608092612cb792613549565b359101350361121d5782898d38612c74565b8a6001600160a01b03612ce3610af484838b16948d614bc3565b1603612cf1576001016128eb565b6128f3565b9397949390919060028103612fe35750606081013560018103612e8857506001831115612dcc575061158d5760005b818110612d38575050506001905b6129ab565b612d4387868a613549565b35906001600160a01b0384163b1561016957604051917f23b872dd00000000000000000000000000000000000000000000000000000000835233600484015261dead60248401526044830152600082606481836001600160a01b0389165af1908115610963576001928392612dbd575b5001960195612d25565b612dc6906134a9565b38612db3565b915095919295612e6c575b50612de3818488613549565b356001600160a01b0383163b15610169576001600160a01b039260646000928360405196879485937f23b872dd00000000000000000000000000000000000000000000000000000000855233600486015261dead60248601526044850152165af1908115610963576001928392612e5d575b5001936129ab565b612e66906134a9565b8e612e55565b6080612e7983868a613549565b359101350361121d578d612dd7565b929493926111db576001851115612f3b575061158d57612ea783614beb565b9260005b818110612f175750506001600160a01b0381163b1561016957612b6f6000916001600160a01b0394836040519687809581947f7d3c5ebe000000000000000000000000000000000000000000000000000000008352336004840152604060248401526044830190614c4e565b60018091612f268a898d613549565b35612f318289614c3a565b5201970196612eab565b919350959195612fc7575b50612f52818488613549565b35916001600160a01b0381163b15610169576040517f6621a02500000000000000000000000000000000000000000000000000000000815233600482015260248101939093526000908390604490829084906001600160a01b03165af1908115610963576001928392612e5d575001936129ab565b6080612fd483868a613549565b359101350361121d578d612f46565b9294939290915060010361186157606001356001810361300c5750600192612d33913390614ef6565b6111db576001600160a01b0381163b15610169576040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810193909352600090839081836001600160a01b038260448101612b6f565b613078818385614b93565b9061308c6024803501356060840135614ba3565b6020830135806130f557506001926001600160a01b0387161580156130e9575b156130c757906118e060406130c193016136a0565b01612153565b6118e060406119196130e494612710611908608087013583614ba3565b6130c1565b506080810135156130ac565b6001036119b6576001926001600160a01b038716158015613158575b1561312957908161196560406119196130e4956136a0565b61199b6130e492612710613141608085013583614ba3565b0490611914828b613151876136a0565b3390614f70565b50608081013515613111565b6131d69397509060349291611a4f6131866064602435016024356004016135fb565b959094836040519485927fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602085019860601b168852848401378101600083820152036014810184520182613508565b936001600160a01b03851615610f4b57868681612130565b909250876000526002602052604060002061320f6024803501358254614b4a565b905587600052600260205260406000205411611aa95788918a61211d565b613282613244608460243501602435600401613708565b9060405160208101907fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b16825260148152611b28816134ec565b612112579350905061329860e4602435016136a0565b6001600160a01b0381166132d05760046040517fb05e92fa000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b03600654166040517f9c395bc20000000000000000000000000000000000000000000000000000000081526001600160a01b038b1660048201526001600160a01b0383166024820152602081604481855afa908115610963576000916133f6575b5015613367575b5061335890611c02608460243501602435600401613708565b15611c5b578790600193612112565b60206001600160a01b0360648c60405194859384927f90c9a2d00000000000000000000000000000000000000000000000000000000084521660048301526001600160a01b03871660248301523060448301525afa908115610963576000916133d7575b5015611c5b578961333f565b6133f0915060203d602011611d1457611d068183613508565b8a6133cb565b61340f915060203d602011611d1457611d068183613508565b8b613338565b807f0db255a60000000000000000000000000000000000000000000000000000000060049252fd5b600435906001600160a01b038216820361016957565b602435906001600160a01b038216820361016957565b9181601f840112156101695782359167ffffffffffffffff8311610169576020808501948460051b01011161016957565b60243590811515820361016957565b67ffffffffffffffff81116134bd57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff8211176134bd57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176134bd57604052565b91908110156135595760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b91908110156135595760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0181360301821215610169570190565b9035907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee181360301821215610169570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610169570180359067ffffffffffffffff82116101695760200191813603831361016957565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610169570180359067ffffffffffffffff8211610169576020019160a082023603831361016957565b356001600160a01b03811681036101695790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610169570180359067ffffffffffffffff8211610169576020019160c082023603831361016957565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610169570180359067ffffffffffffffff821161016957602001918160051b3603831361016957565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610169570180359067ffffffffffffffff8211610169576020019160e082023603831361016957565b906137bb81806135c8565b906137c960408201826135fb565b906137d384615278565b6102556137e1610653615043565b519020936137f083838761515c565b9160009060009461380187806135c8565b9042606083013511611d8e5742608083013510611d64576001600160a01b03861687526005602052604087205460e083013503611d3a578160c08b930135614984575b60a08101358061494a575b5061010061385d9101614b86565b6148ca575b505050613872604083018361364c565b9061387f60c088016136a0565b9160005b8181106147eb57505050506020820161389c81846136b4565b9050613fdd575b5015613fd3576138bf6138b860e086016136a0565b918061375c565b60009391935b81811061390a5750505050505060206001600160a01b039101359216907f9d45e8614d63fdcb7d8e231afe42fcd0366c2c2d3792a5df9954be4fd5d61e3c600080a490565b613915818387614c82565b9061391f826136a0565b916001600160a01b038316600052600360205260406000206001600160a01b03861660005260205260ff6040600020541615610f9f576001600160a01b038316600052600160205260406000208a60005260205260ff60406000205416610f75576001600160a01b03881680613f7e575b5060608101359260c082013560a08301358b60406139c160206139b4818901614b86565b9301356080880135614ba3565b95013560038103613c2a575050908891855b888110613bfa575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018703613aa157508392613a1c928692896001600160a01b0397614ca8565b1692833b156101695760848760008e9681956001600160a01b0395866040519a8b9889977fcb4ef4e4000000000000000000000000000000000000000000000000000000008952166004880152166024860152604485015260648401525af191821561096357600192613a92575b505b016138c5565b613a9b906134a9565b38613a8a565b9450505050919250613ab66109818483614bb6565b92613ac46109818284614bb6565b916000905b888c888c848710613b99575050505050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b039101921692833b15610169576001600160a01b0393846000898f948296610a35613b71926040519b8c998a9889977f613ce049000000000000000000000000000000000000000000000000000000008952166004880152166024860152608060448601526084850190614c4e565b03925af191821561096357600192613b8a575b50613a8c565b613b93906134a9565b38613b84565b91613bdb613bb08860019798999594889795614c82565b613bc7602060608301359401356080830135614ba3565b93849160c08101359060a00135858e614ca8565b613be5878b614c3a565b52613bf08688614c3a565b5201920190613ac9565b8b6001600160a01b03613c14610af4848d848b1695614c82565b1603613c25578a93506001016139d3565b6139db565b6002819894939295969814600014613e2f575080159081158092613e26575b613d6a575b50505081158015613d60575b15613ce35750610ba9576001600160a01b0381163b15610169576040517f82b1c4230000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152808d16602483015260448201949094529260009184918290849082606481015b0393165af191821561096357600192613b8a5750613a8c565b9350506001600160a01b0381163b15610169576040517f5598d9670000000000000000000000000000000000000000000000000000000081526001600160a01b0387811660048301528c81166024830152604482019490945292600091849160649183918591165af191821561096357600192613b8a5750613a8c565b5060018511613c5a565b6040517fc035f9b50000000000000000000000000000000000000000000000000000000081526001600160a01b038c1660048201526040816024816001600160a01b038b165afa9283156109635789906000928395613dff575b50613de9575b9150508215613c4e57613ddc91614b4a565b11610ce657388086613c4e565b613df291614b4a565b11610d2a57388088613dca565b909450613e1c91925060403d604011610d8057610d718183613508565b9190919338613dc4565b50821515613c49565b9193509150600103610eef5780159081158092613f75575b613eb9575b5050506001600160a01b0381163b15610169576040517fc6c3bbe60000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152808d1660248301526044820194909452926000918491829084908260648101613cca565b6040517fe158dfdc0000000000000000000000000000000000000000000000000000000081526001600160a01b038a1660048201526040816024816001600160a01b0389165afa9283156109635787906000928395613f4e575b50613f38575b9150508215613e4c57613f2b91614b4a565b11610ce657388084613e4c565b613f4191614b4a565b11610d2a57388086613f19565b909450613f6b91925060403d604011610d8057610d718183613508565b9190919338613f13565b50821515613e47565b6001600160a01b0384166000526004908160205260406000209060005260205260ff60406000205416613990576040517f2f58c7cd000000000000000000000000000000000000000000000000000000008152fd5b6138bf8691610773565b613fea90839992996136b4565b613ffa60a0889493940188613708565b939092936000935b83851061401557505050505096386138a3565b9091929394614025868686614bc3565b908a614030836136a0565b9261403d60208201614b86565b6140546020604084013594013560a0840135614ba3565b926003810361447e5750895b888a8281811061444f575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018d1415915061422c905057506141eb575b606001358061414057506140b3828686613549565b35906001600160a01b0384163b15610169576064600092836001600160a01b0360405197889586947f1227fe8600000000000000000000000000000000000000000000000000000000865233600487015260248601526044850152165af1908115610963576001928392614131575b505b01955b0193929190614002565b61413a906134a9565b38614122565b6001036111db57614152828686613549565b35906001600160a01b0384163b156101695760c4600092836001600160a01b0360405197889586947ff242432a00000000000000000000000000000000000000000000000000000000865233600487015261dead60248701526044860152606485015260a060848501528260a4850152165af19081156109635760019283926141dc575b50614124565b6141e5906134a9565b386141d6565b6141f6838787613549565b356080820135031561409e5760046040517f4d9c9be5000000000000000000000000000000000000000000000000000000008152fd5b9250509197806142406109818f9385614bb6565b9261424e6109818383614bb6565b926000905b8284106143ca575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192606001358061431a57506001600160a01b0384163b15610169576142f19361130960006001600160a01b038195604051988996879586937f092c8aa5000000000000000000000000000000000000000000000000000000008552336004860152606060248601526064850190614c4e565b0393165af19182156109635760019261430b575b50614127565b614314906134a9565b38614305565b6001036111db576001600160a01b0384163b15610169576143a593600092836001600160a01b03602061439295836040519a8b9889977f2eb2c2d60000000000000000000000000000000000000000000000000000000089523360048a015261dead60248a015260a060448a015260a4890190614c4e565b60031993848983030160648a0152614c4e565b8681039283016084880152520193165af19182156109635760019261430b5750614127565b6143db848d949e948d969496614bc3565b6143f860206143eb818401614b86565b93013560a0830135614ba3565b91614433575b5061440a838b8b613549565b356144158588614c3a565b526144208486614c3a565b52600180809201930191019a908f614253565b6080614440858d8d613549565b359101350361121d57386143fe565b610af4614468916001600160a01b0393848c1695614bc3565b160361447657600101614060565b888a8261406b565b939994939091906002810361476a575060608101356001810361460757506001831115614554575061158d5760005b8181106144c0575050506001905b614127565b6144cb898787613549565b35906001600160a01b0384163b1561016957604051917f23b872dd00000000000000000000000000000000000000000000000000000000835233600484015261dead60248401526044830152600082606481836001600160a01b0389165af1908115610963576001928392614545575b50019801976144ad565b61454e906134a9565b3861453b565b91509792976145eb575b506001600160a01b031690614574818585613549565b35823b15610169576000926064849260405195869384927f23b872dd00000000000000000000000000000000000000000000000000000000845233600485015261dead602485015260448401525af19081156109635760019283926145dc575b500195614127565b6145e5906134a9565b386145d4565b60806145f8848787613549565b359101350361121d573861455e565b929493926111db5760018511156146cb575061158d5761462683614beb565b9260005b8181106146a75750506001600160a01b0316803b156101695761468f6000939184926040519586809481937f7d3c5ebe000000000000000000000000000000000000000000000000000000008352336004840152604060248401526044830190614c4e565b03925af19182156109635760019261430b5750614127565b600180916146b68c8a8a613549565b356146c18289614c3a565b520199019861462a565b919298935061474e575b506001600160a01b0316906146eb818585613549565b3591803b15610169576040517f6621a02500000000000000000000000000000000000000000000000000000000815233600482015260248101939093526000908390604490829084905af19081156109635760019283926145dc57500195614127565b608061475b848787613549565b359101350361121d57386146d5565b92949392600192508203611861576060013590810361479257506001926144bb913390614ef6565b6111db576001600160a01b0316803b15610169576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481019390935260009083908183816044810161468f565b6147f6818385614b93565b9061480960208b01356060840135614ba3565b60208301358061487257506001926001600160a01b038716158015614866575b1561484457906118e0604061483e93016136a0565b01613883565b6118e0604061191961486194612710611908608087013583614ba3565b61483e565b50608081013515614829565b6001036119b6576001926001600160a01b0387161580156148be575b156148a65790816119656040611919614861956136a0565b61199b61486192612710613141608085013583614ba3565b5060808101351561488e565b90614932939691611a4f60346148e360608c018c6135fb565b969095846040519586937fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602086019960601b1689528585013782019083820152036014810184520182613508565b926001600160a01b03841615610f4b57388781613862565b90925089885260026020526040882061496860208b01358254614b4a565b90558988526002602052604088205411611aa95789913861384f565b61499461324460808b018b613708565b61384457935090506149a860e088016136a0565b6001600160a01b0381166149e05760046040517fb05e92fa000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b03600654166040517f9c395bc20000000000000000000000000000000000000000000000000000000081526001600160a01b038c1660048201526001600160a01b0383166024820152602081604481855afa908115614b27578991614b08575b5015614a6f575b50614a6090611c0260808a018a613708565b15611c5b578890600193613844565b60206001600160a01b0360648d60405194859384927f90c9a2d00000000000000000000000000000000000000000000000000000000084521660048301526001600160a01b03871660248301523060448301525afa908115614afd578891614ade575b5015611c5b5738614a4e565b614af7915060203d602011611d1457611d068183613508565b38614ad2565b6040513d8a823e3d90fd5b614b21915060203d602011611d1457611d068183613508565b38614a47565b6040513d8b823e3d90fd5b90816020910312610169575180151581036101695790565b91908201809211614b5757565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b3580151581036101695790565b91908110156135595760a0020190565b81810292918115918404141715614b5757565b91908203918211614b5757565b91908110156135595760c0020190565b67ffffffffffffffff81116134bd5760051b60200190565b90614bf582614bd3565b614c026040519182613508565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0614c308294614bd3565b0190602036910137565b80518210156135595760209160051b010190565b90815180825260208080930193019160005b828110614c6e575050505090565b835185529381019392810192600101614c60565b91908110156135595760e0020190565b9190826040910312610169576020825192015190565b94919093929381159384158095614dea575b614cc8575b50505050505050565b604080517f399297250000000000000000000000000000000000000000000000000000000081526001600160a01b039283166004820152602481019390935296879183916044918391165afa938415614ddf576000918295614dbc575b508390614d7d575b50505082614d3e575b808080614cbf565b614d4791614b4a565b11614d5457808080614d36565b600490517f94d7a276000000000000000000000000000000000000000000000000000000008152fd5b614d8691614b4a565b11614d9357388082614d2d565b600484517f3e0866c7000000000000000000000000000000000000000000000000000000008152fd5b614dd7919550849250873d8911610d8057610d718183613508565b949091614d25565b86513d6000823e3d90fd5b50851515614cba565b6001600160a01b038291600080809481948294165af1903d15614ef0573d9067ffffffffffffffff8211614ec35760405191614e5760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184613508565b825260203d92013e5b15614e685750565b471015614e995760046040517fcd1c8867000000000000000000000000000000000000000000000000000000008152fd5b60046040517ff499da20000000000000000000000000000000000000000000000000000000008152fd5b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526041600452fd5b50614e60565b606460209293600060405195869485937f23b872dd0000000000000000000000000000000000000000000000000000000085526001600160a01b03809316600486015261dead60248601526044850152165af1801561096357614f565750565b614f6d9060203d8111611d1457611d068183613508565b50565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b03928316600482015292821660248401526044830193909352909160209183916064918391600091165af1801561096357614f565750565b81939293614fe4575b50501490565b60059291831b8101915b8135808211851b918252602080921852604060002091019282841015615015579290614fee565b509150503880614fde565b60005b8381106150335750506000910152565b8181015183820152602001615023565b7f9db553c251dd0d3abd116eb6d7fc748d4fb17226549384b42ac93826e2a74814907f000000000000000000000000000000000000d58696577347f78259bd376f1bec30147f0000000000000000000000000000000000000000000000000000000000000001461416156150b357565b905060405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527fe2361dc120cc5b14a7fc7f89e15db87b4f8f6d950ff9603e58c5da27bc980da960408201527fe6bbd6277e1bf288eed5e8d1780f9a50b239e86b153736bceebccf4ea79d90b360608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176134bd5760405251902090565b90916041036151ce57600082604082940135821a92601b841415806151c3575b15615188575050505090565b6020608092819560405193845282840152803560408401520135606082015282805260015afa156151b7575190565b604051903d90823e3d90fd5b50601c84141561517c565b5050600090565b9060405160a081016040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608082019360008552935b0192600a90818106603001855304928315615248577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9061520c565b92506080837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09203019201918252565b615282818061375c565b6060916000915b808310615550575050508051602080920120916152a8828201826136b4565b6060916000915b808310615468575050508281519101206040916152ce8382018261364c565b6060916000915b80831061538a5750505090818560e09351910120610100906152f8828401614b86565b948651978801987f352afb97db53d33e87be729b9d4e587ca2de5d80c540a656d64ac4ab3d244c5f8a528789015260608801526080870152606082013560a0870152608082013560c087015260a08201358387015260c082013590860152013561012084015261014090151581840152825261016082019082821067ffffffffffffffff8311176134bd575251902090565b909192615398848385614b93565b906153a2826136a0565b6153ad8984016136a0565b928951938b8501927fc4cb1148475c5cce4dc4ac1da9b1e88f0c270c5e7279b915db40949117e8c31784526001600160a01b038091168c8701528c83013560608701526080911681860152606082013560a086015260c091013581850152835260e083019183831067ffffffffffffffff8411176134bd576001938b8b9261545f94868552835190209061544c81518092610100958688019101615020565b830191820152038b810184520182613508565b930191906152d5565b909192615476848385614bc3565b61547f816136a0565b9161548b888301614b86565b916040908151936001600160a01b038b8601967f6123f3e52d7d4c81d116bd2cc2f3037b6bf3584638afdff0e0abd37a007463d888521683860152151560608501526080828201358186015260a09060608301358287015282013560c086015260e091013581850152835261010083019280841067ffffffffffffffff8511176134bd578961554793600196868552835190209061553481518092610120958688019101615020565b8301918201520389810184520182613508565b930191906152af565b90919261555e848385614c82565b615567816136a0565b602091615575838201614b86565b926040918251946001600160a01b03838701957fc566908c5227968aab2e8cab737a01e51d99317b10b3d5e2ae287e2ebff502f387521684870152151560608601526080838201358187015260a060608301358188015260c0918301358288015282013560e087015261010091013581860152845261012084019380851067ffffffffffffffff8611176134bd57600195615639948685528251902081516156268161014094878688019101615020565b8301918201520390810184520182613508565b9301919061528956fea26469706673582212209800c7c36427b365258d82fa3295222ea58e922efa24ba7e6b17182b8baae45e64736f6c63430008140033

Deployed Bytecode Sourcemap

2062:34820:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2062:34820:0;;;;;;;:::i;:::-;;;:::i;:::-;3807:10;2062:34820;;;;;-1:-1:-1;;;;;2062:34820:0;;;;;;;;;;;3785:53;2062:34820;;;;;;;;;;;;;;;;;;3785:53;2062:34820;;3807:10;;3856:52;2062:34820;3856:52;;2062:34820;;;;;;;;;;-1:-1:-1;;2062:34820:0;;;;;;;:::i;:::-;;;:::i;:::-;;-1:-1:-1;;;;;2062:34820:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2062:34820:0;;;;;;;;;;;;;;;;;;;;;;;;10525:38:14;2062:34820:0;;;;10525:38:14;:::i;:::-;10607:54;;10636:18;;:::i;:::-;2062:34820:0;;;10607:54:14;;;;;;;;2062:34820:0;;;;;;;;;;;;;;;;;;10607:54:14;;;;;;;;;:::i;:::-;2062:34820:0;10583:89:14;;2062:34820:0;;;;;;;;;;;-1:-1:-1;;2062:34820:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;4960:27;;;;;;2062:34820;4949:9;5023:10;2062:34820;;5006:16;2062:34820;;;;;;;;;5035:19;;;;;:::i;:::-;2062:34820;;;;;5006:59;2062:34820;;;;;;;;;;;;;;;;;;5006:59;5085:66;5131:19;;;;;:::i;:::-;2062:34820;;;;;;;5023:10;5085:66;;2062:34820;4949:9;;2062:34820;;;;;-1:-1:-1;;2062:34820:0;;;;;;;:::i;:::-;;;:::i;:::-;3524:10;2062:34820;;3502:21;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;;;;;;;;;;3502:53;2062:34820;;;;;;;;;;;;;;;;;;3502:53;2062:34820;;3524:10;;3573:58;2062:34820;3573:58;;2062:34820;;;;;;-1:-1:-1;;2062:34820:0;;;;;;;4116:33;;;4133:15;;2062:34820;;4116:33;;;;;;:::i;:::-;2062:34820;4106:44;;4065:10;2062:34820;;4053:11;4116:33;2062:34820;;;;;;;;;;;4065:10;4194:59;2062:34820;4194:59;;2062:34820;;;-1:-1:-1;;2062:34820:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;;383:20:13;379:82;;490:1;2062:34820:0;;;7067:18;;2062:34820;7062:324;7087:30;;;;;;7425:21;;7461:20;7457:98;;7062:324;-1:-1:-1;2062:34820:0;;;7457:98;7526:16;7514:10;;7526:16;:::i;:::-;7457:98;;;7067:18;7233:68;7167:22;;;;;;:::i;:::-;7233:68;;:::i;:::-;2062:34820;;7067:18;;;;;379:82:13;2062:34820:0;;;427:22:13;;;;2062:34820:0;;;;;-1:-1:-1;;2062:34820:0;;;;;;;;;2434:52;2062:34820;;;;;;;;;;;;;;;-1:-1:-1;;2062:34820:0;;;;;;;;;;;;;;;;;;;:::i;:::-;402:1:13;2062:34820:0;;;;383:20:13;379:82;;490:1;2062:34820:0;;;5836:18;2062:34820;5831:322;5856:30;;;;;;6192:21;;6228:20;6224:98;;-1:-1:-1;2062:34820:0;;;5836:18;6002:66;5936:22;;;;;;:::i;:::-;6020:10;6002:66;:::i;:::-;2062:34820;;5836:18;;;;;2062:34820;;-1:-1:-1;;2062:34820:0;;;;;;;;;;;;-1:-1:-1;;2062:34820:0;;;;;;;;402:1:13;2062:34820:0;;383:20:13;379:82;;490:1;2062:34820:0;;8237:24;2062:34820;;;;;8237:24;:::i;:::-;8313:33;;2062:34820;;8313:33;2062:34820;;;;8313:33;:::i;:::-;2103:29:14;;;;;:::i;:::-;2176:54;;2205:18;;:::i;:::-;2062:34820:0;;;2176:54:14;;;2062:34820:0;2176:54:14;;;;2062:34820:0;;;;;;;;;;;;;;;;;;2176:54:14;2062:34820:0;2152:89:14;;2261:27;;;;;;:::i;:::-;2062:34820:0;;8632:117;;2062:34820;;10866:24;2062:34820;;;;;10866:24;:::i;:::-;10932:15;10905:24;;;2062:34820;10905:42;10901:101;;10932:15;11016:22;;;2062:34820;11016:40;11012:94;;-1:-1:-1;;;;;2062:34820:0;;;;11120:11;2062:34820;;;;;;;11157:20;;2062:34820;11120:57;11116:117;;11247:25;;;2062:34820;11243:1418;;2062:34820;12685:31;;;2062:34820;12685:36;12681:291;;2062:34820;12987:38;2062:34820;12987:38;;;;:::i;:::-;12984:282;;2062:34820;8816:28;;;2062:34820;8816:28;;;;:::i;:::-;2062:34820;8859:18;;2062:34820;;8859:18;;:::i;:::-;13972:29;2062:34820;14003:40;;;;;;8902:25;;;;;2062:34820;8902:25;;;;:::i;:::-;:36;;8899:286;;13967:2060;9231:145;;;9424:25;9280:21;;2062:34820;;9280:21;;:::i;:::-;9231:145;;9424:25;;:::i;:::-;26313:22;2062:34820;26409:33;;;;;;2062:34820;;8376:18;;2062:34820;5411:10;2062:34820;9655:64;2062:34820;;9655:64;5476:21;5512:20;5508:98;;26401:4252;402:1:13;2062:34820:0;;;5508:98;5577:16;5411:10;;5577:16;:::i;:::-;5508:98;;;26401:4252;26492:26;;;;;:::i;:::-;26561:25;;;;:::i;:::-;-1:-1:-1;;;;;2062:34820:0;;;;575:1:15;2062:34820:0;;;;;-1:-1:-1;;;;;2062:34820:0;;;;;;;;;;;;31394:61;31390:119;;-1:-1:-1;;;;;2062:34820:0;;;;402:1:13;2062:34820:0;;;;;;;;;;;;;;;;31519:113;;-1:-1:-1;;;;;2062:34820:0;;31645:26;31642:181;;26401:4252;26909:25;;2062:34820;26909:25;;;:::i;:::-;26970:40;8376:18;2062:34820;;8376:18;2062:34820;11016:22;26970:20;;2062:34820;26970:40;:::i;:::-;27045:19;2062:34820;27045:19;;2062:34820;575:1:15;27085:31:0;;575:1:15;;27137:37:0;;;27200:31;;;;;;27193:302;3099:42;;;27564:30;;;;26845:26;27719:10;26845:26;;11247:25;26845:26;;2062:34820;12685:31;26784:19;;2062:34820;10905:24;26732:17;;2062:34820;27719:10;;:::i;:::-;-1:-1:-1;;;;;2062:34820:0;;27755:215;;;;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;;;10905:24;2062:34820;;27755:215;;;;;2062:34820;27755:215;;2062:34820;;27755:215;;2062:34820;5411:10;8376:18;2062:34820;;;26732:17;2062:34820;8313:33;2062:34820;;;;;;;;27755:215;;;;;;;402:1:13;27755:215:0;;;27560:2021;;;2062:34820;26401:4252;;27755:215;;;;:::i;:::-;;;;;2062:34820;;;;;;;;;27560:2021;28163:29;;;;;28148:46;28163:29;;;;:::i;:::-;28148:46;:::i;:::-;28268:29;28253:46;28268:29;;;;:::i;28253:46::-;28327:22;2062:34820;28322:840;28351:29;;;;;;3099:42;;;;;2062:34820;-1:-1:-1;;;;;2062:34820:0;;29283:278;;;;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;;;;;;;29283:278;;;;;;;2062:34820;29283:278;;2062:34820;;29283:278;;2062:34820;5411:10;8376:18;2062:34820;;;11016:22;8313:33;2062:34820;;;;;;;;:::i;:::-;;-1:-1:-1;;2062:34820:0;;;;;;;;;:::i;:::-;29283:278;2062:34820;;29283:278;;;;;;;402:1:13;29283:278:0;;;28322:840;27560:2021;;;29283:278;;;;:::i;:::-;;;;28327:22;28423:26;402:1:13;28423:26:0;;;;;;;;:::i;:::-;28842:10;10905:24;28616:17;;2062:34820;;28673:40;8376:18;2062:34820;;8376:18;2062:34820;11016:22;28673:20;;2062:34820;28673:40;:::i;:::-;28553:26;;;11247:25;28553:26;;2062:34820;;12685:31;28488:19;2062:34820;28553:26;;28842:10;:::i;:::-;28882:34;;;;:::i;:::-;3099:42;28943:41;;;;:::i;:::-;3099:42;2062:34820;;;28327:22;;;;;;27193:302;-1:-1:-1;;;;;2062:34820:0;;-1:-1:-1;;;;;27262:40:0;:24;;;;;:::i;:::-;:40;:::i;:::-;2062:34820;27262:59;27258:121;;402:1:13;2062:34820:0;27193:302;;27258:121;27350:5;;27081:3486;29606:30;;;;490:1:13;29606:30:0;;490:1:13;;26784:19:0;12685:31;26784:19;;2062:34820;33908:14;;;:39;;;;29602:965;33905:574;;29602:965;29783:16;;;2062:34820;;29783:34;;29602:965;29779:434;;;29842:115;;;-1:-1:-1;;;;;2062:34820:0;;29979:86;;;;2062:34820;;;29979:86;;-1:-1:-1;;;;;2062:34820:0;;;;29979:86;;2062:34820;5411:10;3099:42;;;2062:34820;3099:42;;;2062:34820;;;;;;;;;;;;;;3099:42;;;29979:86;3099:42;29842:115;2062:34820;;;29897:36;;;;29779:434;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;30114:79;;;;2062:34820;;;30114:79;;-1:-1:-1;;;;;2062:34820:0;;;;30114:79;;2062:34820;5411:10;3099:42;;;2062:34820;10905:24;26732:17;;;;2062:34820;3099:42;;;2062:34820;;-1:-1:-1;;2062:34820:0;;3099:42;;2062:34820;;-1:-1:-1;;2062:34820:0;30114:79;;;;;;;402:1:13;30114:79:0;;;29779:434;27081:3486;;29783:34;29803:14;402:1:13;29803:14:0;;29783:34;;33905:574;2062:34820;;;34010:75;;-1:-1:-1;;;;;2062:34820:0;;;34010:75;;2062:34820;;;8376:18;2062:34820;-1:-1:-1;;;;;2062:34820:0;;34010:75;;;;;;;2062:34820;;;34010:75;;;33905:574;34100:168;;;33905:574;26845:26;11247:25;26845:26;;2062:34820;34286:21;;;34282:186;;33905:574;;;;;34282:186;34332:25;;;:::i;:::-;:44;34328:125;;34282:186;;;;;34328:125;2062:34820;;;34408:25;;;;34100:168;34143:24;26784:19;12685:31;26784:19;;2062:34820;34143:24;;:::i;:::-;:36;34139:114;;34100:168;;;34139:114;2062:34820;;;34211:22;;;;34010:75;;;;;;;2062:34820;34010:75;2062:34820;34010:75;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;33908:39;26845:26;11247:25;26845:26;;2062:34820;33926:21;;33908:39;;29602:965;30238:29;;-1:-1:-1;402:1:13;30238:29:0;402:1:13;;12685:31:0;26784:19;;2062:34820;35198:14;;;;:39;;;;30234:333;35195:568;;30234:333;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;30407:74;;;;2062:34820;;;30407:74;;-1:-1:-1;;;;;2062:34820:0;;;;30407:74;;2062:34820;5411:10;3099:42;;;2062:34820;3099:42;;;2062:34820;;;;;;;;;;;;;;3099:42;;;30407:74;3099:42;35195:568;2062:34820;;;35300:69;;-1:-1:-1;;;;;2062:34820:0;;;35300:69;;2062:34820;;;8376:18;2062:34820;-1:-1:-1;;;;;2062:34820:0;;35300:69;;;;;;;2062:34820;;;35300:69;;;35195:568;35384:168;;;35195:568;26845:26;11247:25;26845:26;2062:34820;35570:21;;;35566:186;;35195:568;;;;35566:186;35616:25;;;:::i;:::-;:44;35612:125;;35566:186;;;;;35384:168;35427:24;26784:19;12685:31;26784:19;;2062:34820;35427:24;;:::i;:::-;:36;35423:114;;35384:168;;;35300:69;;;;;;;2062:34820;35300:69;2062:34820;35300:69;;;;;;;:::i;:::-;;;;;35198:39;26845:26;11247:25;26845:26;;2062:34820;35216:21;;35198:39;;30234:333;2062:34820;;;30529:22;;;;31642:181;-1:-1:-1;;;;;2062:34820:0;;;;;;;;;;;;;;;;;;;;;31691:53;31688:124;;31642:181;;;31688:124;2062:34820;;;31772:24;;;;31519:113;2062:34820;;;31602:18;;;;31390:119;2062:34820;;;31479:18;;;;9231:145;9424:25;5411:10;9231:145;;;8899:286;9084:25;2062:34820;8902:25;;9084;;:::i;:::-;2062:34820;9128:30;;2062:34820;;9128:30;2062:34820;;;;9128:30;:::i;:::-;8982:191;2062:34820;;;16929:34;;;;;;8899:286;;;;;;;;16901:26;17013;;;;;:::i;:::-;17082:25;;;;:::i;:::-;17195;;2062:34820;17195:25;;;:::i;:::-;17307:19;2062:34820;17307:19;;2062:34820;;17362:40;8376:18;2062:34820;;8376:18;2062:34820;12685:31;17362:20;;2062:34820;17362:40;:::i;:::-;17423:31;575:1:15;17423:31:0;;575:1:15;;17475:37:0;;17538:32;;;;;;17531:303;3099:42;;;17903:30;;;;17958:220;;;17899:3456;10905:24;17254:18;;2062:34820;18204:35;;18380:46;;;;;;:::i;:::-;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;18268:226;;;;3099:42;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;18268:226;;;;;2062:34820;18268:226;;5411:10;2062:34820;18268:226;;2062:34820;8376:18;3099:42;;2062:34820;8313:33;3099:42;;2062:34820;;18268:226;;;;;;;402:1:13;18268:226:0;;;;;18200:800;;;2062:34820;17899:3456;;2062:34820;16901:26;;;18268:226;;;;:::i;:::-;;;;18200:800;10905:24;17254:18;2062:34820;402:1:13;18528:34:0;402:1:13;;18748:46:0;;;;;:::i;:::-;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;18591:304;;;;8859:18;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;18591:304;;;;;2062:34820;18591:304;;5411:10;2062:34820;18591:304;;2062:34820;3099:42;8376:18;3099:42;;2062:34820;8313:33;3099:42;;2062:34820;3099:42;;;2062:34820;12685:31;3099:42;;;;;9128:30;3099:42;;;2062:34820;18591:304;;;;;;;402:1:13;18591:304:0;;;;;18524:476;;18200:800;;18591:304;;;;:::i;:::-;;;;18524:476;2062:34820;;;18959:17;;;;17958:220;18021:46;;;;;:::i;:::-;2062:34820;11016:22;17140:17;;2062:34820;18010:57;18006:149;17958:220;18006:149;;2062:34820;;;18107:20;;;;17899:3456;19301:29;;;;;;19286:46;19301:29;;;;:::i;19286:46::-;19406:29;19391:46;19406:29;;;;:::i;19391:46::-;19465:22;2062:34820;19489:29;;;;;;-1:-1:-1;;3099:42:0;;;10905:24;17254:18;;2062:34820;20585:35;;2062:34820;-1:-1:-1;;;;;2062:34820:0;;20649:204;;;;3099:42;2062:34820;3099:42;2062:34820;-1:-1:-1;;;;;2062:34820:0;;;;20649:204;;;;;;;2062:34820;20649:204;;5411:10;2062:34820;20649:204;;2062:34820;10905:24;8376:18;3099:42;;;;;;;;:::i;:::-;;-1:-1:-1;;3099:42:0;;;;8313:33;3099:42;;;;:::i;:::-;20649:204;2062:34820;;20649:204;;;;;;;402:1:13;20649:204:0;;;20581:755;;17899:3456;;20649:204;;;;:::i;:::-;;;;20581:755;17254:18;;;;10905:24;17254:18;2062:34820;402:1:13;20887:34:0;402:1:13;;-1:-1:-1;;;;;2062:34820:0;;20950:281;;;;2062:34820;;3099:42;2062:34820;;-1:-1:-1;;;;;2062:34820:0;3099:42;2062:34820;;20950:281;;;;;2062:34820;20950:281;;5411:10;2062:34820;20950:281;;2062:34820;3099:42;8376:18;3099:42;;2062:34820;12685:31;8313:33;3099:42;;;9128:30;3099:42;;;;:::i;:::-;;-1:-1:-1;;3099:42:0;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;3099:42:0;;;;;;;20950:281;2062:34820;;20950:281;;;;;;;402:1:13;20950:281:0;;;20883:453;17899:3456;;19465:22;19561:26;;;;;;;;;:::i;:::-;19632:25;;;;;2062:34820;19632:25;;;:::i;:::-;2062:34820;19751:40;8376:18;2062:34820;;8376:18;2062:34820;12685:31;19751:20;;2062:34820;19751:40;:::i;:::-;19820:236;;;19465:22;20111:46;;;402:1:13;20111:46:0;;;;;;;;:::i;:::-;2062:34820;20084:73;;;;:::i;:::-;3099:42;20184:41;;;;:::i;:::-;3099:42;2062:34820;;;;;19465:22;;;;19820:236;19887:46;11016:22;19887:46;;;;:::i;:::-;2062:34820;19694:17;;2062:34820;19876:57;19872:157;;19820:236;;;;;;17531:303;2062:34820;-1:-1:-1;;;;;17601:40:0;:24;2062:34820;;;;17601:24;;;:::i;:40::-;2062:34820;17601:59;17597:121;;402:1:13;2062:34820:0;17531:303;;17597:121;17689:5;;17419:7724;21380:30;;;;;;;490:1:13;21380:30:0;;490:1:13;;-1:-1:-1;10905:24:0;17254:18;;2062:34820;402:1:13;21435:34:0;402:1:13;;;21498:14:0;;402:1:13;;;21541:123:0;;;2062:34820;21720:24;;;;;;21494:1423;;;402:1:13;21494:1423:0;;17419:7724;;21695:23;21943:46;;;;;:::i;:::-;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;21779:241;;;;2062:34820;;21779:241;2062:34820;21779:241;;5411:10;2062:34820;21779:241;;2062:34820;3099:42;8376:18;3099:42;;2062:34820;8313:33;3099:42;;2062:34820;;;3099:42;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;21779:241;;;;;;;402:1:13;21779:241:0;;;;;21695:23;2062:34820;;;;21695:23;;;21779:241;;;;:::i;:::-;;;;21541:123;2062:34820;;;21600:36;;;;21494:1423;22285:236;;;;;;;;21494:1423;22699:46;;;;;;:::i;:::-;2062:34820;-1:-1:-1;;;;;2062:34820:0;;22547:225;;;;-1:-1:-1;;;;;2062:34820:0;3099:42;2062:34820;;;;;22547:225;;;;;2062:34820;22547:225;;5411:10;2062:34820;22547:225;;2062:34820;3099:42;8376:18;3099:42;;2062:34820;8313:33;3099:42;;2062:34820;;22547:225;;;;;;;402:1:13;22547:225:0;;;;;21494:1423;2062:34820;;21494:1423;17419:7724;;22547:225;;;;:::i;:::-;;;;22285:236;11016:22;22352:46;;;;;:::i;:::-;2062:34820;17140:17;;2062:34820;22341:57;22337:157;;22285:236;;;21431:3059;17254:18;;;;10905:24;17254:18;;2062:34820;22946:35;;402:1:13;23010:14:0;;402:1:13;;;23053:123:0;;;23234:25;;;:::i;:::-;23291:22;2062:34820;23315:23;;;;;;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;23679:71;;;;3099:42;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;;;23679:71;;;;;;2062:34820;23679:71;;5411:10;2062:34820;23679:71;;2062:34820;;8376:18;3099:42;;;8313:33;3099:42;;;;:::i;23291:22::-;402:1:13;23399:46:0;;;;;;;:::i;:::-;2062:34820;23372:73;;;;:::i;:::-;3099:42;2062:34820;;;23291:22;;;23006:1392;23807:236;;;;;;;;23006:1392;24180:46;;;;;;:::i;:::-;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;24069:184;;;;2062:34820;;;24069:184;;5411:10;2062:34820;24069:184;;2062:34820;210:1:10;;;2062:34820:0;;;;-1:-1:-1;;2062:34820:0;;210:1:10;;2062:34820:0;;-1:-1:-1;;;;;;;2062:34820:0;24069:184;;;;;;;402:1:13;24069:184:0;;;;;2062:34820;;23006:1392;17419:7724;;23807:236;11016:22;23874:46;;;;;:::i;:::-;2062:34820;17140:17;;2062:34820;23863:57;23859:157;;23807:236;;;21376:3767;24515:29;;;;;;-1:-1:-1;402:1:13;24515:29:0;402:1:13;;10905:24:0;17254:18;;2062:34820;402:1:13;24569:34:0;402:1:13;;5411:10:0;402:1:13;5411:10:0;24787;5411;;24787;;:::i;24565:493::-;10905:24;17254:18;2062:34820;24850:35;;-1:-1:-1;;;;;2062:34820:0;;24910:55;;;;2062:34820;;;24910:55;;5411:10;2062:34820;24910:55;;2062:34820;210:1:10;;;2062:34820:0;;;;;;;;;;-1:-1:-1;;;;;2062:34820:0;210:1:10;;;24910:55:0;210:1:10;24511:632:0;2062:34820;;;25105:22;;;;13972:29;14099:32;;;;;:::i;:::-;2062:34820;14170:46;8376:18;2062:34820;;8376:18;2062:34820;10905:24;14170:26;;2062:34820;14170:46;:::i;:::-;2062:34820;14251:22;;2062:34820;14294:30;;;2062:34820;402:1:13;2062:34820:0;-1:-1:-1;;;;;2062:34820:0;;14348:22;:55;;;;14290:1648;14345:469;;;14444:18;;2062:34820;14464:13;14444:18;;;:::i;:::-;14464:13;:::i;:::-;2062:34820;13972:29;;14345:469;14760:18;2062:34820;14689:32;14780:13;14569:24;14596:5;14553:40;11016:22;14569:24;;2062:34820;14553:40;;:::i;:::-;331:1:15;14650:15:0;;;;;:::i;:::-;14689:32;:::i;:::-;14760:18;;;:::i;14780:13::-;14345:469;;14348:55;14374:24;11016:22;14374:24;;2062:34820;14374:29;14348:55;;14290:1648;402:1:13;14839:29:0;402:1:13;;;2062:34820:0;-1:-1:-1;;;;;2062:34820:0;;14892:22;:55;;;;14835:1103;14889:961;;;15013:28;;15105:18;2062:34820;15013:28;15150:13;15013:28;;:::i;15105:18::-;5411:10;;15150:13;;:::i;14889:961::-;15561:32;15794:13;15277:24;15304:5;15261:40;11016:22;15277:24;;2062:34820;15261:40;;:::i;:::-;331:1:15;5411:10:0;15500:15;5411:10;;;15373:28;;;:::i;:::-;15500:15;:::i;15561:32::-;15657:28;15749:18;2062:34820;15657:28;;;:::i;14892:55::-;14918:24;11016:22;14918:24;;2062:34820;14918:29;14892:55;;14835:1103;2062:34820;;;15897:25;;;;12984:282;2968:33:14;2062:34820:0;;;13117:25;;2062:34820;;13117:25;2062:34820;;;;13117:25;:::i;:::-;2062:34820;;;2898:49:14;2062:34820:0;;;2898:49:14;;;2062:34820:0;2898:49:14;;5411:10:0;2062:34820;5411:10;10905:24;2062:34820;;;;;;;;;;;;;;;2898:49:14;;;;;;;;;:::i;:::-;2062:34820:0;2888:60:14;;2968:33;:::i;:::-;2062:34820:0;-1:-1:-1;;;;;2062:34820:0;;13161:26;13158:97;;12984:282;;;;12681:291;2062:34820;;;490:1:13;2062:34820:0;;;;;12738:61;8376:18;2062:34820;;8376:18;2062:34820;;;12738:61;:::i;:::-;2062:34820;;;;;490:1:13;2062:34820:0;;;;;;12818:73;12814:147;;12681:291;;;12814:147;2062:34820;;;12919:26;;;;11243:1418;11326:201;11375:21;;2062:34820;;11375:21;2062:34820;;;;11375:21;:::i;:::-;2062:34820;;;;11477:30;;5411:10;2062:34820;5411:10;10905:24;2062:34820;;;;11477:30;;;;;;:::i;:::-;2062:34820;11467:41;;11247:25;;;;2062:34820;11326:201;;:::i;:::-;11243:1418;11303:1347;2062:34820;;11584:21;;2062:34820;;11584:21;;:::i;:::-;-1:-1:-1;;;;;2062:34820:0;;;;;;;11684:20;;;;11624:1011;-1:-1:-1;;;;;11873:12:0;2062:34820;;;;;11873:59;;5411:10;2062:34820;11873:59;;2062:34820;-1:-1:-1;;;;;2062:34820:0;;8376:18;2062:34820;;;;11873:59;8313:33;11873:59;;;;;;;;;2062:34820;11873:59;;;11624:1011;11872:60;;11869:286;;11624:1011;2062:34820;12207:232;2062:34820;12264:21;11375;2062:34820;;11375:21;2062:34820;;;;12264:21;:::i;:::-;2062:34820;;;;;12382:29;;2062:34820;10905:24;2062:34820;;;;11477:30;12382:29;;;;;:::i;:::-;2062:34820;12372:40;;11247:25;;;;2062:34820;12207:232;;:::i;:::-;12372:40;;;402:1:13;12177:439:0;11243:1418;;12177:439;2062:34820;;;12572:20;;;;11869:286;2062:34820;;;;;11965:79;;;;2062:34820;11965:79;;5411:10;2062:34820;11965:79;;2062:34820;-1:-1:-1;;;;;2062:34820:0;;8376:18;2062:34820;;;12038:4;8313:33;2062:34820;;;11965:79;;;;;;;2062:34820;11965:79;;;11869:286;11964:80;;11961:171;;11869:286;;;11965:79;;;;2062:34820;11965:79;2062:34820;11965:79;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;11873:59;;;;2062:34820;11873:59;2062:34820;11873:59;;;;;;;:::i;:::-;;;;11116:117;2062:34820;;;11201:20;;;;11012:94;2062:34820;;;11080:14;;;;10901:101;2062:34820;;;10971:19;;;;2062:34820;;;;;-1:-1:-1;;2062:34820:0;;;;;;;:::i;:::-;;;:::i;:::-;;-1:-1:-1;;;;;2062:34820:0;;;;;2575:73;2062:34820;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2062:34820:0;;;;;-1:-1:-1;;;;;2062:34820:0;;:::i;:::-;;;;2927:46;2062:34820;;;;;;;;;;;;;;;;;;-1:-1:-1;;2062:34820:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3926:27:14;-1:-1:-1;;;;;2062:34820:0;;;;;;;;;4452:11;2062:34820;;3740:23:14;2062:34820:0;;;;3672:13:14;2062:34820:0;3740:23:14;:::i;:::-;2062:34820:0;;3853:29:14;2062:34820:0;;3853:29:14;:::i;:::-;2062:34820:0;3802:94:14;2062:34820:0;;;3802:94:14;;;2062:34820:0;3802:94:14;;;2062:34820:0;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;3802:94:14;;;;;;;;;:::i;:::-;2062:34820:0;;;3792:105:14;;3926:27;:::i;:::-;2062:34820:0;3916:37:14;;:61;;;2062:34820:0;4413:70;4410:116;;4452:11;2062:34820;;4621:33;;;4638:15;;2062:34820;;4621:33;;;;;;:::i;:::-;2062:34820;4611:44;;2062:34820;;;;;;;;;;;;;;;4699:51;2062:34820;4699:51;;2062:34820;4410:116;2062:34820;;;4492:34;;;;3916:61:14;3957:20;;;;3916:61;;2062:34820:0;;;;;-1:-1:-1;;2062:34820:0;;;;;-1:-1:-1;;;;;2062:34820:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2062:34820:0;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;2062:34820:0;;;;;;;;;;;383:20:13;379:82;;-1:-1:-1;490:1:13;2062:34820:0;;8237:24;2062:34820;;;;;8237:24;:::i;:::-;8313:33;;2062:34820;;8313:33;2062:34820;;;;8313:33;:::i;:::-;2103:29:14;;;;:::i;:::-;2176:54;;2205:18;;:::i;2176:54::-;2062:34820:0;2152:89:14;;2261:27;;;;;;:::i;:::-;2062:34820:0;;8632:117;;2062:34820;;10866:24;2062:34820;;;;;10866:24;:::i;:::-;10932:15;;2062:34820;10905:24;;2062:34820;10905:42;10901:101;;10932:15;11016:22;;;2062:34820;11016:40;11012:94;;-1:-1:-1;;;;;2062:34820:0;;;;11120:11;8376:18;2062:34820;;;;;;11157:20;;2062:34820;11120:57;11116:117;;11247:25;;;;;2062:34820;11243:1418;;2062:34820;12685:31;;;2062:34820;12685:36;12681:291;;2062:34820;12987:38;2062:34820;12987:38;;;;:::i;:::-;12984:282;;2062:34820;8816:28;;;;2062:34820;8816:28;;;;:::i;:::-;2062:34820;8859:18;;2062:34820;;8859:18;;:::i;:::-;13972:29;2062:34820;14003:40;;;;;;8902:25;;;;;8376:18;8902:25;;;;:::i;:::-;:36;;8899:286;;13967:2060;9231:145;;;9424:25;9280:21;;2062:34820;;9280:21;;:::i;9424:25::-;26313:22;;2062:34820;26409:33;;;;;;2062:34820;;;8376:18;2062:34820;-1:-1:-1;;;;;2062:34820:0;;;9655:64;2062:34820;;9655:64;6641:21;6677:20;6673:98;;2062:34820;;;;26401:4252;26492:26;;;;;:::i;:::-;26561:25;;;;:::i;:::-;-1:-1:-1;;;;;2062:34820:0;;;;575:1:15;8376:18:0;2062:34820;;;;-1:-1:-1;;;;;2062:34820:0;;;;8376:18;2062:34820;;;;;;;31394:61;31390:119;;-1:-1:-1;;;;;2062:34820:0;;;;;8376:18;2062:34820;;;;;;;8376:18;2062:34820;;;;;;;31519:113;;-1:-1:-1;;;;;2062:34820:0;;31645:26;31642:181;;26401:4252;-1:-1:-1;2062:34820:0;26732:17;;2062:34820;;11247:25;26845:26;;2062:34820;12685:31;26784:19;;2062:34820;26909:25;8376:18;26909:25;;;:::i;:::-;2062:34820;26970:40;2062:34820;;;8376:18;2062:34820;11016:22;26970:20;;2062:34820;26970:40;:::i;:::-;27045:19;;2062:34820;575:1:15;27085:31:0;;575:1:15;;27137:37:0;;;;;;27200:31;;;;;;;;;27193:302;3099:42;;27564:30;;;;-1:-1:-1;27564:30:0;;-1:-1:-1;27564:30:0;27719:10;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;2062:34820:0;;27755:215;;;;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;;;;;;;;;27755:215;;;;;2062:34820;27755:215;;2062:34820;;27755:215;;2062:34820;;;;;;8313:33;2062:34820;;;;;;;;27755:215;;;;;;;2062:34820;27755:215;;;27560:2021;;;2062:34820;26401:4252;;27755:215;;;;:::i;:::-;;;;27560:2021;28163:29;;;;;;;28148:46;28163:29;;;;:::i;28148:46::-;28268:29;28253:46;28268:29;;;;:::i;28253:46::-;28327:22;2062:34820;28322:840;28351:29;;;;;;;;3099:42;;;;;;;2062:34820;-1:-1:-1;;;;;2062:34820:0;;29283:278;;;;-1:-1:-1;;;;;2062:34820:0;;;;;;;;;;;;;;29283:278;;;;;;;2062:34820;29283:278;;2062:34820;;29283:278;;2062:34820;;;;;;11016:22;8313:33;2062:34820;;;;;;;;:::i;:::-;29283:278;2062:34820;;29283:278;;;;;;;2062:34820;29283:278;;;28322:840;27560:2021;;;29283:278;;;;:::i;:::-;;;;28327:22;28423:26;2062:34820;28423:26;;;;;;;;;:::i;:::-;28842:10;2062:34820;28616:17;;2062:34820;;28673:40;2062:34820;;;8376:18;2062:34820;11016:22;28673:20;;2062:34820;28673:40;:::i;28842:10::-;28882:34;;;;:::i;:::-;3099:42;28943:41;;;;:::i;:::-;3099:42;2062:34820;;;28327:22;;;;;;27193:302;27262:24;:40;2062:34820;-1:-1:-1;;;;;2062:34820:0;;;;27262:24;;:::i;:40::-;2062:34820;27262:59;27258:121;;27193:302;;-1:-1:-1;2062:34820:0;;27193:302;;27258:121;27350:5;;;;;27081:3486;490:1:13;29606:30:0;;;;;;;;29602:965;490:1:13;;;33908:14:0;;;;;;:39;;;;29602:965;33905:574;;29602:965;29783:16;;;;;2062:34820;;29783:34;;29602:965;29779:434;;;29842:115;;;-1:-1:-1;;;;;2062:34820:0;;29979:86;;;;2062:34820;;;29979:86;;-1:-1:-1;;;;;2062:34820:0;;;;29979:86;;2062:34820;;;;3099:42;;;2062:34820;3099:42;;;2062:34820;;;;;;;;;;;;;;3099:42;;;29979:86;3099:42;29779:434;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;30114:79;;;;2062:34820;;;30114:79;;-1:-1:-1;;;;;2062:34820:0;;;;30114:79;;2062:34820;;;;3099:42;;;2062:34820;3099:42;;;2062:34820;;;;;-1:-1:-1;;2062:34820:0;;3099:42;;2062:34820;;-1:-1:-1;;2062:34820:0;30114:79;;;;;;;2062:34820;30114:79;;;29779:434;27081:3486;;29783:34;29803:14;2062:34820;29803:14;;29783:34;;33905:574;2062:34820;;;34010:75;;-1:-1:-1;;;;;2062:34820:0;;;34010:75;;2062:34820;;;;;-1:-1:-1;;;;;2062:34820:0;;34010:75;;;;;;;;;2062:34820;;;34010:75;;;33905:574;34100:168;;;33905:574;34286:21;;;;34282:186;33905:574;34282:186;34332:25;;;:::i;:::-;:44;34328:125;;34282:186;;;33905:574;;34100:168;34143:24;;;:::i;:::-;:36;34139:114;;34100:168;;;;;34010:75;;;;;;;;2062:34820;34010:75;2062:34820;34010:75;;;;;;;:::i;:::-;;;;;;;;33908:39;33926:21;;;;33908:39;;29602:965;30238:29;;-1:-1:-1;30238:29:0;-1:-1:-1;2062:34820:0;30238:29;2062:34820;;35198:14;;;;;:39;;;;30234:333;35195:568;;30234:333;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;30407:74;;;;2062:34820;;;30407:74;;-1:-1:-1;;;;;2062:34820:0;;;;30407:74;;2062:34820;;;;3099:42;;;2062:34820;3099:42;;;2062:34820;;;;;;;;;;;;;;3099:42;;;30407:74;3099:42;35195:568;2062:34820;;;35300:69;;-1:-1:-1;;;;;2062:34820:0;;;35300:69;;2062:34820;;;;;-1:-1:-1;;;;;2062:34820:0;;35300:69;;;;;;;;;2062:34820;;;35300:69;;;35195:568;35384:168;;;35195:568;35570:21;;;;35566:186;35195:568;35566:186;35616:25;;;:::i;:::-;:44;35612:125;;35566:186;;;35195:568;;35384:168;35427:24;;;:::i;:::-;:36;35423:114;;35384:168;;;;;35300:69;;;;;;;;2062:34820;35300:69;2062:34820;35300:69;;;;;;;:::i;:::-;;;;;;;;35198:39;35216:21;;;;35198:39;;31642:181;-1:-1:-1;;;;;2062:34820:0;;;;;8376:18;2062:34820;;;;;;;8376:18;2062:34820;;;;;;;31691:53;31688:124;;31642:181;;;9231:145;9424:25;9334:30;9231:145;;;8899:286;9084:25;8376:18;8902:25;;9084;;:::i;:::-;2062:34820;9128:30;;2062:34820;;9128:30;2062:34820;;;;9128:30;:::i;:::-;8982:191;;2062:34820;;;16929:34;;;;;;8899:286;;;;;;;;16901:26;17013;;;;;:::i;:::-;17082:25;;;;:::i;:::-;17195;;8376:18;17195:25;;;:::i;:::-;17307:19;2062:34820;17307:19;;2062:34820;;17362:40;2062:34820;;;8376:18;2062:34820;12685:31;17362:20;;2062:34820;17362:40;:::i;:::-;17423:31;575:1:15;17423:31:0;;575:1:15;;17475:37:0;;17538:32;;;;;;17531:303;3099:42;;;17903:30;;;;17958:220;;;17899:3456;2062:34820;17254:18;2062:34820;18204:35;2062:34820;;18380:46;;;;;;:::i;:::-;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;18268:226;;;;3099:42;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;18268:226;;;;;2062:34820;18268:226;;18339:10;2062:34820;18268:226;;2062:34820;;3099:42;;2062:34820;8313:33;3099:42;;2062:34820;;18268:226;;;;;;;2062:34820;18268:226;;;;;18200:800;;;2062:34820;17899:3456;;2062:34820;16901:26;;;18268:226;;;;:::i;:::-;;;;18200:800;2062:34820;18528:34;2062:34820;;18748:46;;;;;:::i;:::-;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;18591:304;;;;8859:18;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;18591:304;;;;;2062:34820;18591:304;;18664:10;2062:34820;18591:304;;2062:34820;3099:42;2062:34820;3099:42;;2062:34820;8313:33;3099:42;;2062:34820;3099:42;;;2062:34820;12685:31;3099:42;;;;;9128:30;3099:42;;;2062:34820;18591:304;;;;;;;2062:34820;18591:304;;;;;18524:476;;18200:800;;18591:304;;;;:::i;:::-;;;;17958:220;18021:46;;;;;:::i;:::-;2062:34820;11016:22;17140:17;;2062:34820;18010:57;18006:149;17958:220;18006:149;2062:34820;;;18107:20;;;;17899:3456;19301:29;;;;;;19286:46;19301:29;;;;:::i;19286:46::-;19406:29;19391:46;19406:29;;;;:::i;19391:46::-;19465:22;2062:34820;19489:29;;;;;;-1:-1:-1;;3099:42:0;;;2062:34820;17254:18;2062:34820;20585:35;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;20649:204;;;;3099:42;2062:34820;3099:42;2062:34820;-1:-1:-1;;;;;2062:34820:0;;;;20649:204;;;;;;;2062:34820;20649:204;;20726:10;2062:34820;20649:204;;2062:34820;;;3099:42;;;;;;;;:::i;:::-;20649:204;2062:34820;;20649:204;;;;;;;2062:34820;20649:204;;;20581:755;;17899:3456;;20649:204;;;;:::i;:::-;;;;20581:755;20887:34;;;;2062:34820;20887:34;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;20950:281;;;;2062:34820;;3099:42;2062:34820;;-1:-1:-1;;;;;8376:18:0;3099:42;2062:34820;;20950:281;;;;;2062:34820;20950:281;;21028:10;2062:34820;20950:281;;2062:34820;3099:42;2062:34820;3099:42;;2062:34820;12685:31;8313:33;3099:42;;;9128:30;3099:42;;;;:::i;:::-;;;;;;-1:-1:-1;;3099:42:0;;;;;;;20950:281;2062:34820;;20950:281;;;;;;;2062:34820;20950:281;;;20883:453;17899:3456;;19465:22;19561:26;;;;;;;;;:::i;:::-;19632:25;;;;;8376:18;19632:25;;;:::i;:::-;2062:34820;19751:40;2062:34820;;;8376:18;2062:34820;12685:31;19751:20;;2062:34820;19751:40;:::i;:::-;19820:236;;;19465:22;20111:46;;;2062:34820;20111:46;;;;;;;;:::i;:::-;2062:34820;20084:73;;;;:::i;:::-;3099:42;20184:41;;;;:::i;:::-;3099:42;2062:34820;;;;;19465:22;;;;19820:236;19887:46;11016:22;19887:46;;;;:::i;:::-;2062:34820;19694:17;;2062:34820;19876:57;19872:157;;19820:236;;;;;;17531:303;2062:34820;-1:-1:-1;;;;;17601:40:0;:24;2062:34820;;;;17601:24;;;:::i;:40::-;2062:34820;17601:59;17597:121;;2062:34820;;17531:303;;17597:121;17689:5;;17419:7724;21380:30;;;;;;;490:1:13;21380:30:0;;490:1:13;;-1:-1:-1;2062:34820:0;17254:18;;2062:34820;;21435:34;;2062:34820;;-1:-1:-1;2062:34820:0;21498:14;;2062:34820;;;21541:123;;;2062:34820;21720:24;;;;;;21494:1423;;;2062:34820;21494:1423;;17419:7724;;21695:23;21943:46;;;;;:::i;:::-;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;21779:241;;;;2062:34820;;21779:241;2062:34820;21779:241;;21851:10;2062:34820;21779:241;;2062:34820;3099:42;2062:34820;3099:42;;2062:34820;8313:33;3099:42;;2062:34820;;;3099:42;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;21779:241;;;;;;;2062:34820;21779:241;;;;;21695:23;2062:34820;;;;21695:23;;;21779:241;;;;:::i;:::-;;;;21494:1423;22285:236;;;;;;;;21494:1423;22699:46;;;;;;:::i;:::-;2062:34820;-1:-1:-1;;;;;2062:34820:0;;22547:225;;;;-1:-1:-1;;;;;2062:34820:0;3099:42;2062:34820;;;;;22547:225;;;;;2062:34820;22547:225;;22615:10;2062:34820;22547:225;;2062:34820;3099:42;2062:34820;3099:42;;2062:34820;8313:33;3099:42;;2062:34820;;22547:225;;;;;;;2062:34820;22547:225;;;;;21494:1423;2062:34820;;21494:1423;17419:7724;;22547:225;;;;:::i;:::-;;;;22285:236;11016:22;22352:46;;;;;:::i;:::-;2062:34820;17140:17;;2062:34820;22341:57;22337:157;;22285:236;;;21431:3059;22946:35;;;;2062:34820;;;23010:14;;2062:34820;;;23053:123;;;23234:25;;;:::i;:::-;23291:22;2062:34820;23315:23;;;;;;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;23679:71;;;;3099:42;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;;;23679:71;;;;;;2062:34820;23679:71;;23725:10;2062:34820;23679:71;;2062:34820;;;3099:42;;;8313:33;3099:42;;;;:::i;23291:22::-;2062:34820;23399:46;;;;;;;:::i;:::-;2062:34820;23372:73;;;;:::i;:::-;3099:42;2062:34820;;;23291:22;;;23006:1392;23807:236;;;;;;;;23006:1392;24180:46;;;;;;:::i;:::-;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;24069:184;;;;2062:34820;;;24069:184;;24139:10;2062:34820;24069:184;;2062:34820;210:1:10;;;2062:34820:0;;;;-1:-1:-1;;2062:34820:0;;210:1:10;;2062:34820:0;;-1:-1:-1;;;;;;;2062:34820:0;24069:184;;;;;;;2062:34820;24069:184;;;;;2062:34820;;23006:1392;17419:7724;;23807:236;11016:22;23874:46;;;;;:::i;:::-;2062:34820;17140:17;;2062:34820;23863:57;23859:157;;23807:236;;;21376:3767;24515:29;;;;;;-1:-1:-1;2062:34820:0;24515:29;2062:34820;;;17254:18;2062:34820;;24569:34;;2062:34820;;24711:10;2062:34820;24711:10;24787;24711;;24787;;:::i;24565:493::-;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;24910:55;;;;2062:34820;;;24910:55;;24942:10;2062:34820;24910:55;;2062:34820;210:1:10;;;2062:34820:0;;;;;;;;;;-1:-1:-1;;;;;2062:34820:0;210:1:10;;;24910:55:0;210:1:10;13972:29:0;14099:32;;;;;:::i;:::-;2062:34820;14170:46;2062:34820;;;8376:18;2062:34820;;14170:26;;2062:34820;14170:46;:::i;:::-;8376:18;14251:22;;2062:34820;14294:30;;;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;14348:22;:55;;;;14290:1648;14345:469;;;14444:18;;2062:34820;14464:13;14444:18;;;:::i;14464:13::-;2062:34820;13972:29;;14345:469;14760:18;2062:34820;14689:32;14780:13;14569:24;14596:5;14553:40;11016:22;14569:24;;2062:34820;14553:40;;:::i;14780:13::-;14345:469;;14348:55;14374:24;11016:22;14374:24;;2062:34820;14374:29;14348:55;;14290:1648;2062:34820;14839:29;2062:34820;;;;-1:-1:-1;;;;;2062:34820:0;;14892:22;:55;;;;14835:1103;14889:961;;;15013:28;;15105:18;2062:34820;15013:28;15150:13;15013:28;;:::i;14889:961::-;15561:32;15794:13;15277:24;15304:5;15261:40;11016:22;15277:24;;2062:34820;15261:40;;:::i;:::-;331:1:15;15373:28:0;15500:15;15373:28;;;;;:::i;:::-;15428:10;15500:15;;:::i;14892:55::-;14918:24;11016:22;14918:24;;2062:34820;14918:29;14892:55;;12984:282;2968:33:14;2062:34820:0;;;;;;;2898:49:14;13117:25:0;;2062:34820;;13117:25;2062:34820;;;;13117:25;:::i;:::-;2062:34820;;;;;;2898:49:14;;;2062:34820:0;8376:18;2898:49:14;;2062:34820:0;;;;;;;;;;;;;;;;;2898:49:14;;;;;;;;;:::i;2968:33::-;2062:34820:0;-1:-1:-1;;;;;2062:34820:0;;13161:26;13158:97;;12984:282;;;;;12681:291;2062:34820;;;;;;490:1:13;8376:18:0;2062:34820;;;;12738:61;2062:34820;;;8376:18;2062:34820;;;12738:61;:::i;:::-;2062:34820;;;;;490:1:13;8376:18:0;2062:34820;;;;;12818:73;12814:147;;12681:291;;;;;11243:1418;11326:201;11375:21;;2062:34820;;11375:21;2062:34820;;;;11375:21;:::i;:::-;2062:34820;;;8376:18;11477:30;;2062:34820;;;;;;;;11477:30;;;;;;:::i;11326:201::-;11243:1418;11303:1347;2062:34820;;;;11584:21;;2062:34820;;11584:21;;:::i;:::-;-1:-1:-1;;;;;2062:34820:0;;;;;;;11684:20;;;;11624:1011;-1:-1:-1;;;;;11873:12:0;2062:34820;;;;;11873:59;;-1:-1:-1;;;;;2062:34820:0;;;11873:59;;2062:34820;-1:-1:-1;;;;;2062:34820:0;;;;;;8376:18;11873:59;8313:33;11873:59;;;;;;;;;2062:34820;11873:59;;;11624:1011;11872:60;;11869:286;;11624:1011;2062:34820;12207:232;2062:34820;12264:21;11375;2062:34820;;11375:21;2062:34820;;;;12264:21;:::i;12207:232::-;12372:40;;;12490:18;;2062:34820;12177:439;11243:1418;;11869:286;8376:18;-1:-1:-1;;;;;2062:34820:0;;;;11965:79;;;;;2062:34820;11965:79;;2062:34820;;11965:79;;2062:34820;-1:-1:-1;;;;;2062:34820:0;;;;;;12038:4;8313:33;2062:34820;;;11965:79;;;;;;;2062:34820;11965:79;;;11869:286;11964:80;;11961:171;;11869:286;;;11965:79;;;;8376:18;11965:79;8376:18;11965:79;;;;;;;:::i;:::-;;;;11873:59;;;;8376:18;11873:59;8376:18;11873:59;;;;;;;:::i;:::-;;;;379:82:13;427:22;;2062:34820:0;427:22:13;;;2062:34820:0;;;;-1:-1:-1;;;;;2062:34820:0;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;2062:34820:0;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;-1:-1:-1;;;;;2062:34820:0;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;8009:1762::-;;8237:24;;;;:::i;:::-;8313:33;;;;;;;:::i;:::-;2103:29:14;;;;:::i;:::-;2176:54;;2205:18;;:::i;2176:54::-;2062:34820:0;2152:89:14;;2261:27;;;;;;:::i;:::-;8632:117:0;-1:-1:-1;10792:20:0;-1:-1:-1;10866:24:0;;;;;:::i;:::-;10932:15;;10905:24;;;2062:34820;10905:42;10901:101;;10932:15;11016:22;;;2062:34820;11016:40;11012:94;;-1:-1:-1;;;;;2062:34820:0;;;;11120:11;8376:18;2062:34820;8313:33;2062:34820;;;11157:20;;;2062:34820;11120:57;11116:117;;11247:25;;;;;2062:34820;11243:1418;;8009:1762;12685:31;;;2062:34820;12685:36;12681:291;;8009:1762;12987:38;;;;;;:::i;:::-;12984:282;;8009:1762;8816:28;;;;8313:33;8816:28;;;;:::i;:::-;8859:18;;11247:25;8859:18;;;:::i;:::-;13972:29;-1:-1:-1;14003:40:0;;;;;;8902:25;;;;8376:18;8902:25;;;;;;:::i;:::-;:36;;8899:286;;13967:2060;-1:-1:-1;9231:145:0;;;9424:25;9280:21;11157:20;9280:21;;;:::i;:::-;9231:145;9424:25;;:::i;:::-;-1:-1:-1;26313:22:0;;;26409:33;;;;;;8376:18;;;;;;;-1:-1:-1;;;;;8376:18:0;;2062:34820;;;9655:64;;-1:-1:-1;9655:64:0;;8009:1762;:::o;26401:4252::-;26492:26;;;;;:::i;:::-;26561:25;;;;:::i;:::-;2062:34820;-1:-1:-1;;;;;2062:34820:0;;-1:-1:-1;2062:34820:0;575:1:15;8376:18:0;2062:34820;8313:33;-1:-1:-1;2062:34820:0;-1:-1:-1;;;;;2062:34820:0;;-1:-1:-1;2062:34820:0;8376:18;2062:34820;;8313:33;-1:-1:-1;2062:34820:0;;;31394:61;31390:119;;-1:-1:-1;;;;;2062:34820:0;;-1:-1:-1;2062:34820:0;;8376:18;2062:34820;8313:33;-1:-1:-1;2062:34820:0;;-1:-1:-1;2062:34820:0;8376:18;2062:34820;;8313:33;-1:-1:-1;2062:34820:0;;;31519:113;;-1:-1:-1;;;;;2062:34820:0;;31645:26;31642:181;;26401:4252;-1:-1:-1;10905:24:0;26732:17;;2062:34820;;11247:25;26845:26;;2062:34820;12685:31;26784:19;;2062:34820;26909:25;8313:33;26970:40;8376:18;26909:25;;;;;:::i;:::-;8376:18;;2062:34820;11016:22;26970:20;;2062:34820;26970:40;:::i;:::-;27045:19;;2062:34820;575:1:15;27085:31:0;;575:1:15;;27137:37:0;;;;;;27200:31;;;;;;27193:302;3099:42;;;27564:30;;;;27719:10;;;;;;;;-1:-1:-1;;;;;27719:10:0;;:::i;:::-;2062:34820;27755:215;;;;;;2062:34820;;-1:-1:-1;2062:34820:0;;;;-1:-1:-1;;;;;2062:34820:0;;8313:33;2062:34820;27755:215;;;;;2062:34820;27755:215;;2062:34820;27755:215;;;2062:34820;;;;;;;;;;;;;;27755:215;;;;;;;2062:34820;27755:215;;;27560:2021;;;2062:34820;26401:4252;;27755:215;;;;:::i;:::-;;;;27560:2021;28163:29;;;;;;;;28148:46;28163:29;;;;:::i;28148:46::-;28268:29;28253:46;28268:29;;;;:::i;28253:46::-;28327:22;-1:-1:-1;28322:840:0;28351:29;;;;;;;;;;3099:42;;;;;;;-1:-1:-1;;;;;3099:42:0;;2062:34820;;29283:278;;;;;;-1:-1:-1;;;;;2062:34820:0;;-1:-1:-1;2062:34820:0;;;;;;;;8313:33;2062:34820;29283:278;;;;;;;2062:34820;29283:278;;2062:34820;29283:278;;;2062:34820;;;;;;11016:22;2062:34820;;;;;;;;;:::i;:::-;29283:278;;;;;;;;;2062:34820;29283:278;;;28322:840;27560:2021;;;29283:278;;;;:::i;:::-;;;;28327:22;28423:26;28842:10;28423:26;;2062:34820;28423:26;;;;;;;;;:::i;:::-;28673:40;8376:18;10905:24;28616:17;;2062:34820;8376:18;;2062:34820;11016:22;28673:20;;2062:34820;28673:40;:::i;:::-;28553:26;;;11247:25;28553:26;;2062:34820;;12685:31;28488:19;2062:34820;28553:26;;28842:10;:::i;:::-;28882:34;;;;:::i;:::-;3099:42;28943:41;;;;:::i;:::-;3099:42;2062:34820;;;28327:22;;;27193:302;2062:34820;-1:-1:-1;;;;;27262:40:0;:24;2062:34820;;;;;27262:24;;:::i;:40::-;2062:34820;27262:59;27258:121;;27193:302;;-1:-1:-1;2062:34820:0;;27193:302;;27258:121;27350:5;;27081:3486;452:1:15;29606:30:0;;;;;;;;;29602:965;452:1:15;;;33908:14:0;;;;;;:39;;;;29602:965;33905:574;;29602:965;29783:16;;;;;2062:34820;;29783:34;;29602:965;29779:434;;;29842:115;;;-1:-1:-1;;;;;2062:34820:0;;29979:86;;;;8313:33;2062:34820;;29979:86;;-1:-1:-1;;;;;2062:34820:0;;;29979:86;;;2062:34820;;;;3099:42;;;2062:34820;3099:42;;;2062:34820;;;;;-1:-1:-1;;2062:34820:0;;;;-1:-1:-1;;2062:34820:0;3099:42;;;29979:86;;2062:34820;;29979:86;;;;;;;2062:34820;29979:86;;;29779:434;27081:3486;;29779:434;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;30114:79;;;;8313:33;2062:34820;;30114:79;;-1:-1:-1;;;;;2062:34820:0;;;30114:79;;;2062:34820;;;;3099:42;;;2062:34820;3099:42;;;2062:34820;;;;;-1:-1:-1;;2062:34820:0;;3099:42;;2062:34820;;-1:-1:-1;;2062:34820:0;30114:79;;;;;;;2062:34820;30114:79;;;29779:434;27081:3486;;29783:34;29803:14;2062:34820;29803:14;;29783:34;;33905:574;8313:33;2062:34820;;34010:75;;-1:-1:-1;;;;;2062:34820:0;;34010:75;;;2062:34820;8313:33;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;34010:75;;;;;;;;;-1:-1:-1;;;34010:75:0;;;33905:574;34100:168;;;33905:574;34286:21;;;;34282:186;33905:574;34282:186;34332:25;;;:::i;:::-;:44;34328:125;;34282:186;;;33905:574;;34100:168;34143:24;;;:::i;:::-;:36;34139:114;;34100:168;;;;;34010:75;;;;;;;;8313:33;34010:75;8313:33;34010:75;;;;;;;:::i;:::-;;;;;;;;33908:39;33926:21;;;;33908:39;;29602:965;30238:29;;-1:-1:-1;30238:29:0;-1:-1:-1;2062:34820:0;30238:29;2062:34820;;35198:14;;;;;:39;;;;30234:333;35195:568;;30234:333;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;30407:74;;;;8313:33;2062:34820;;30407:74;;-1:-1:-1;;;;;2062:34820:0;;;30407:74;;;2062:34820;;;;3099:42;;;2062:34820;3099:42;;;2062:34820;;;;;-1:-1:-1;;2062:34820:0;;;;-1:-1:-1;;2062:34820:0;3099:42;;;30407:74;3099:42;35195:568;8313:33;2062:34820;;35300:69;;-1:-1:-1;;;;;2062:34820:0;;35300:69;;;2062:34820;8313:33;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;35300:69;;;;;;;;;-1:-1:-1;;;35300:69:0;;;35195:568;35384:168;;;35195:568;35570:21;;;;35566:186;35195:568;35566:186;35616:25;;;:::i;:::-;:44;35612:125;;35566:186;;;35195:568;;35384:168;35427:24;;;:::i;:::-;:36;35423:114;;35384:168;;;;;35300:69;;;;;;;;8313:33;35300:69;8313:33;35300:69;;;;;;;:::i;:::-;;;;;;;;35198:39;35216:21;;;;35198:39;;31642:181;-1:-1:-1;;;;;2062:34820:0;;-1:-1:-1;2062:34820:0;31692:21;2062:34820;;8376:18;2062:34820;8313:33;-1:-1:-1;2062:34820:0;;-1:-1:-1;2062:34820:0;8376:18;2062:34820;;8313:33;-1:-1:-1;2062:34820:0;;;31642:181;31688:124;8313:33;2062:34820;31772:24;;;;9231:145;9424:25;9334:30;9231:145;;;8899:286;9084:25;;;;;;;:::i;:::-;9128:30;12685:31;9128:30;;;;;;;:::i;:::-;8982:191;;;16901:26;-1:-1:-1;16896:8333:0;16929:34;;;;;;8955:218;;;;;8899:286;;;;16901:26;17013;;;;;;;;;;:::i;:::-;17082:25;;;;;:::i;:::-;17195;;8376:18;17195:25;;;:::i;:::-;17362:40;8376:18;8313:33;17307:19;;2062:34820;8376:18;;2062:34820;12685:31;17362:20;;2062:34820;17362:40;:::i;:::-;17423:31;575:1:15;17423:31:0;;575:1:15;;17475:37:0;;17538:32;;;;;;;;;17531:303;3099:42;;17903:30;;;;-1:-1:-1;17903:30:0;;-1:-1:-1;17903:30:0;17958:220;;;17899:3456;10905:24;17254:18;2062:34820;18204:35;10905:24;;18380:46;;;;;;:::i;:::-;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;18268:226;;;;3099:42;-1:-1:-1;2062:34820:0;;-1:-1:-1;;;;;8313:33:0;2062:34820;18268:226;;;;;2062:34820;18268:226;;18339:10;18268:226;;;2062:34820;3099:42;;;2062:34820;3099:42;;;2062:34820;;18268:226;;;;;;;2062:34820;18268:226;;;;;18200:800;;;2062:34820;17899:3456;;2062:34820;;16901:26;;;;;18268:226;;;;:::i;:::-;;;;18200:800;2062:34820;18528:34;2062:34820;;18748:46;;;;;:::i;:::-;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;18591:304;;;;3099:42;-1:-1:-1;2062:34820:0;;-1:-1:-1;;;;;8313:33:0;2062:34820;18591:304;;;;;2062:34820;18591:304;;18664:10;18591:304;;;2062:34820;3099:42;;;;2062:34820;3099:42;;;2062:34820;3099:42;;;2062:34820;12685:31;3099:42;;;;;;;;;2062:34820;18591:304;;;;;;;2062:34820;18591:304;;;;;18524:476;;18200:800;;18591:304;;;;:::i;:::-;;;;17958:220;18021:46;;;;;:::i;:::-;2062:34820;11016:22;17140:17;;2062:34820;18010:57;18006:149;17958:220;18006:149;18107:20;8313:33;2062:34820;18107:20;;;;17899:3456;19301:29;;;;;;19286:46;19301:29;;;;;:::i;19286:46::-;19406:29;19391:46;19406:29;;;;:::i;19391:46::-;19465:22;-1:-1:-1;19460:1000:0;19489:29;;;;;;-1:-1:-1;;;3099:42:0;;;10905:24;17254:18;2062:34820;20585:35;10905:24;;2062:34820;-1:-1:-1;;;;;2062:34820:0;;20649:204;;;;3099:42;2062:34820;3099:42;-1:-1:-1;;;;;;2062:34820:0;;8313:33;2062:34820;20649:204;;;;;;;2062:34820;20649:204;;20726:10;20649:204;;;2062:34820;10905:24;3099:42;;;;;;;;;:::i;:::-;20649:204;2062:34820;;20649:204;;;;;;;2062:34820;20649:204;;;20581:755;;17899:3456;;20649:204;;;;:::i;:::-;;;;20581:755;2062:34820;20887:34;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;20950:281;;;;3099:42;2062:34820;-1:-1:-1;2062:34820:0;;-1:-1:-1;;;;;8376:18:0;3099:42;2062:34820;;8313:33;2062:34820;20950:281;;;;;2062:34820;20950:281;;21028:10;20950:281;;;2062:34820;3099:42;;;;2062:34820;12685:31;3099:42;;;;;;;;;:::i;:::-;-1:-1:-1;;3099:42:0;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;20950:281;2062:34820;;20950:281;;;;;;;2062:34820;20950:281;;;20883:453;17899:3456;;19465:22;19561:26;;;;;;;;;;;:::i;:::-;19751:40;8376:18;19632:25;;;;;:::i;:::-;8376:18;;2062:34820;12685:31;19751:20;;2062:34820;19751:40;:::i;:::-;19820:236;;;19465:22;20111:46;;;;;;:::i;:::-;2062:34820;20084:73;;;;:::i;:::-;3099:42;20184:41;;;;:::i;:::-;3099:42;2062:34820;;;;;;;;;19465:22;;;;;19820:236;11016:22;19887:46;;;;;:::i;:::-;2062:34820;19694:17;;2062:34820;19876:57;19872:157;;19820:236;;;17531:303;17601:24;:40;2062:34820;-1:-1:-1;;;;;2062:34820:0;;;;17601:24;;:::i;:40::-;2062:34820;17601:59;17597:121;;2062:34820;;17531:303;;17597:121;17689:5;;;;;17419:7724;21380:30;;;;;;;452:1:15;21380:30:0;;452:1:15;;-1:-1:-1;10905:24:0;17254:18;;2062:34820;;21435:34;;2062:34820;;-1:-1:-1;2062:34820:0;21498:14;;2062:34820;;;21541:123;;;-1:-1:-1;21720:24:0;;;;;;21494:1423;;;2062:34820;21494:1423;;17419:7724;;21695:23;21943:46;;;;;:::i;:::-;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;21779:241;;;;8313:33;2062:34820;21779:241;2062:34820;21779:241;;21851:10;21779:241;;;2062:34820;3099:42;;;;2062:34820;3099:42;;;2062:34820;-1:-1:-1;2062:34820:0;3099:42;2062:34820;;-1:-1:-1;;;;;2062:34820:0;;21779:241;;;;;;;2062:34820;21779:241;;;;;21695:23;2062:34820;;;;21695:23;;;21779:241;;;;:::i;:::-;;;;21494:1423;22285:236;;;;;;;21494:1423;2062:34820;-1:-1:-1;;;;;2062:34820:0;22699:46;;;;;;:::i;:::-;2062:34820;22547:225;;;;;-1:-1:-1;2062:34820:0;3099:42;2062:34820;;8313:33;2062:34820;22547:225;;;;;2062:34820;22547:225;;22615:10;22547:225;;;2062:34820;3099:42;;;;2062:34820;3099:42;;;2062:34820;22547:225;;;;;;;2062:34820;22547:225;;;;;21494:1423;2062:34820;;21494:1423;17419:7724;;22547:225;;;;:::i;:::-;;;;22285:236;11016:22;22352:46;;;;;:::i;:::-;2062:34820;17140:17;;2062:34820;22341:57;22337:157;;22285:236;;;21431:3059;22946:35;;;;10905:24;;2062:34820;23010:14;;2062:34820;;;23053:123;;;23234:25;;;:::i;:::-;23291:22;-1:-1:-1;23315:23:0;;;;;;2062:34820;;-1:-1:-1;;;;;2062:34820:0;23679:71;;;;;3099:42;-1:-1:-1;2062:34820:0;;;;8313:33;2062:34820;23679:71;;;;;;2062:34820;23679:71;;23725:10;23679:71;;;2062:34820;8313:33;3099:42;;;;;;;;;:::i;:::-;23679:71;;;;;;;;;2062:34820;23679:71;;;23006:1392;17419:7724;;23291:22;2062:34820;23399:46;;;;;;;:::i;:::-;2062:34820;23372:73;;;;:::i;:::-;3099:42;2062:34820;;;23291:22;;;23006:1392;23807:236;;;;;;;23006:1392;2062:34820;-1:-1:-1;;;;;2062:34820:0;24180:46;;;;;;:::i;:::-;2062:34820;24069:184;;;;;;8313:33;2062:34820;;24069:184;;24139:10;24069:184;;;2062:34820;210:1:10;;;2062:34820:0;;;;-1:-1:-1;;2062:34820:0;;210:1:10;;2062:34820:0;;-1:-1:-1;;24069:184:0;;;;;;;2062:34820;24069:184;;;;;2062:34820;;23006:1392;17419:7724;;23807:236;11016:22;23874:46;;;;;:::i;:::-;2062:34820;17140:17;;2062:34820;23863:57;23859:157;;23807:236;;;21376:3767;2062:34820;;;;;;-1:-1:-1;24515:29:0;;2062:34820;;10905:24;17254:18;2062:34820;;24569:34;;2062:34820;;24711:10;2062:34820;24711:10;24787;24711;;24787;;:::i;24565:493::-;10905:24;;-1:-1:-1;;;;;2062:34820:0;24910:55;;;;;8313:33;2062:34820;;24910:55;;24942:10;24910:55;;;2062:34820;210:1:10;;;2062:34820:0;;;;-1:-1:-1;;2062:34820:0;;;-1:-1:-1;2062:34820:0;210:1:10;;;24910:55:0;210:1:10;13972:29:0;14099:32;;;;;:::i;:::-;8376:18;14170:46;8376:18;;;2062:34820;10905:24;14170:26;;2062:34820;14170:46;:::i;:::-;8376:18;14251:22;;2062:34820;14294:30;;;2062:34820;;;-1:-1:-1;;;;;2062:34820:0;;14348:22;:55;;;;14290:1648;14345:469;;;14444:18;;8313:33;14464:13;14444:18;;;:::i;14464:13::-;2062:34820;13972:29;;14345:469;14760:18;8313:33;14689:32;14780:13;14569:24;14596:5;14553:40;11016:22;14569:24;;2062:34820;14553:40;;:::i;14780:13::-;14345:469;;14348:55;14374:24;11016:22;14374:24;;2062:34820;14374:29;14348:55;;14290:1648;2062:34820;14839:29;2062:34820;;;;-1:-1:-1;;;;;2062:34820:0;;14892:22;:55;;;;14835:1103;14889:961;;;15013:28;;15105:18;8313:33;15013:28;15150:13;15013:28;;:::i;14889:961::-;15561:32;15794:13;15277:24;15304:5;15261:40;11016:22;15277:24;;2062:34820;15261:40;;:::i;14892:55::-;14918:24;11016:22;14918:24;;2062:34820;14918:29;14892:55;;12984:282;13117:25;2968:33:14;13117:25:0;;;2898:49:14;2062:34820:0;13117:25;10905:24;13117:25;;;;:::i;:::-;2062:34820;;;;8313:33;2062:34820;2898:49:14;;;2062:34820:0;8376:18;2898:49:14;;2062:34820:0;10905:24;2062:34820;;;;;;;;;;;;;;;2898:49:14;;;;;;;;;:::i;2968:33::-;2062:34820:0;-1:-1:-1;;;;;2062:34820:0;;13161:26;13158:97;;12984:282;;;;;12681:291;2062:34820;;;;;;12738:17;8376:18;2062:34820;8313:33;2062:34820;;12738:61;8376:18;;;2062:34820;;;12738:61;:::i;:::-;2062:34820;;;;;12738:17;8376:18;2062:34820;8313:33;2062:34820;;;12818:73;12814:147;;12681:291;;;;;11243:1418;11326:201;11375:21;11016:22;11375:21;;;;:::i;11326:201::-;11243:1418;11303:1347;11584:21;;;;;11157:20;11584:21;;;:::i;:::-;-1:-1:-1;;;;;2062:34820:0;;;;11684:20;8313:33;2062:34820;11684:20;;;;11624:1011;-1:-1:-1;;;;;11873:12:0;2062:34820;;8313:33;2062:34820;;11873:59;;-1:-1:-1;;;;;2062:34820:0;;11873:59;;;2062:34820;-1:-1:-1;;;;;2062:34820:0;;;;;;8376:18;11873:59;2062:34820;11873:59;;;;;;;;;;;;;11624:1011;11872:60;;11869:286;;11624:1011;11375:21;12207:232;11375:21;12264;11016:22;11375:21;;12264;;:::i;12207:232::-;12372:40;;;12490:18;;2062:34820;12177:439;11243:1418;;11869:286;8376:18;-1:-1:-1;;;;;2062:34820:0;;8313:33;2062:34820;11965:79;;;;;2062:34820;11965:79;;2062:34820;11873:59;11965:79;;2062:34820;-1:-1:-1;;;;;2062:34820:0;;;;;;12038:4;2062:34820;;;;11965:79;;;;;;;;;;;11869:286;11964:80;;11961:171;;11869:286;;;11965:79;;;;8376:18;11965:79;8376:18;11965:79;;;;;;;:::i;:::-;;;;;8313:33;2062:34820;;;;;;;;11873:59;;;;8376:18;11873:59;8376:18;11873:59;;;;;;;:::i;:::-;;;;;8313:33;2062:34820;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::o;331:1:15:-;;;;;;;;;;:::o;2062:34820:0:-;;;;;;;;;;;;:::o;3099:42::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;2062:34820;;3099:42;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;2062:34820;;3099:42;;;;;;;;;;;;:::o;:::-;;2062:34820;;3099:42;;;;;;;;2062:34820;;3099:42;-1:-1:-1;3099:42:0;;;;;;;;;;;:::o;:::-;;;2062:34820;;3099:42;;;;;;;;;;;;2062:34820;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::o;32410:785::-;;;;;;;32607:14;;;;;:39;;;;32410:785;32604:584;;32410:785;;;;;;;;:::o;32604:584::-;2062:34820;;;;32709:85;;-1:-1:-1;;;;;2062:34820:0;;;32709:85;;;2062:34820;210:1:10;;;2062:34820:0;;;;;;;;;210:1:10;;2062:34820:0;;;32709:85;;;;;;;32620:1;;;32709:85;;;32604:584;32809:168;;;;;32604:584;32995:21;;;;32991:186;;32604:584;;;;;;32991:186;33041:25;;;:::i;:::-;:44;33037:125;;32991:186;;;;;33037:125;32709:85;2062:34820;;33117:25;;;;32809:168;32852:24;;;:::i;:::-;:36;32848:114;;32809:168;;;;;32848:114;32709:85;2062:34820;;32920:22;;;;32709:85;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;2062:34820;;;32620:1;2062:34820;;;;;32607:39;32625:21;;;;32607:39;;35998:340;-1:-1:-1;;;;;35998:340:0;;36087:35;2062:34820;;;;;;;;36087:35;;2062:34820;;;;;;;;;;;;;;;3099:42;2062:34820;;;;;;;3099:42;;:::i;:::-;2062:34820;;;;;;;;36137:5;36133:198;;35998:340;:::o;36133:198::-;36162:21;:30;;;;36220:21;2062:34820;;36220:21;;;;36159:161;36289:15;2062:34820;;36289:15;;;;2062:34820;;;;;;;;;;;;;;36663:216;3099:42;36817:54;36663:216;;-1:-1:-1;2062:34820:0;;36817:54;;;;;2062:34820;36817:54;;-1:-1:-1;;;;;2062:34820:0;;;36817:54;;;2062:34820;3099:42;;;;2062:34820;3099:42;;;2062:34820;;36817:54;;;;;;;;36663:216;:::o;36817:54::-;;;;;;;;;;;;;:::i;:::-;;36663:216::o;:::-;2062:34820;;;36817:54;;-1:-1:-1;;;;;2062:34820:0;;;36817:54;;;2062:34820;;;;3099:42;;;2062:34820;3099:42;;;2062:34820;;;;;;36817:54;;2062:34820;;3099:42;;2062:34820;;-1:-1:-1;;2062:34820:0;36817:54;;;;;;;;36663:216;:::o;2439:1436:11:-;;;;;2641:1227;;2439:1436;2641:1227;;;2439:1436;:::o;2641:1227::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2062:34820:0;;;;;;;;-1:-1:-1;;2062:34820:0;;;;:::o;:::-;;;;;;;;;;;;;4076:235:14;4168:22;4574:11;;4640:113;;4528:14;4640:113;;;;4201:103;;4076:235::o;4201:103::-;2062:34820:0;;;;4891:217:14;;;2062:34820:0;108:103:16;2062:34820:0;;4969:11:14;2062:34820:0;108:103:16;;2062:34820:0;5003:14:14;108:103:16;;;2062:34820:0;4640:113:14;108:103:16;;;2062:34820:0;4640:113:14;108:103:16;;;2062:34820:0;108:103:16;4891:217:14;;108:103:16;2062:34820:0;;;;;;;;;;;;;;4863:260:14;;4201:103;4076:235::o;5428:794::-;;;5665:2;5651:16;5647:68;;-1:-1:-1;5828:177:14;;;;;;;;6085:7;6090:2;6085:7;;;:18;;;5428:794;6081:134;;;6120:19;;;;;:::o;6081:134::-;5828:177;2062:34820:0;;;;5828:177:14;2062:34820:0;;;;;;;;5828:177:14;;;2062:34820:0;;;5828:177:14;;2062:34820:0;;;;6179:24:14;;;;;;;;;;6172:31;:::o;6179:24::-;5828:177;2062:34820:0;;;;;;;;;6085:18:14;6096:7;6101:2;6096:7;;;6085:18;;5647:68;5684:19;;-1:-1:-1;5684:19:14;:::o;6230:676::-;;6369:530;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6230:676::o;9644:710::-;9889:25;;;;:::i;:::-;2062:34820:0;7079:13:14;-1:-1:-1;7074:203:14;7094:21;;;;;;2062:34820:0;;;;;8436:25:14;2062:34820:0;;;7294:18:14;9953:25;;;;;;;:::i;:::-;2062:34820:0;7493:13:14;-1:-1:-1;7488:203:14;7508:21;;;;;;2062:34820:0;;;;;;;;7708:18:14;8480:19;10020:28;;;;;;;:::i;:::-;2062:34820:0;7916:13:14;-1:-1:-1;7911:212:14;7931:24;;;;;;2062:34820:0;;;;;;1121:170:16;2062:34820:0;;;;8140:18:14;1121:170:16;10261:38:14;;;;;;:::i;:::-;2062:34820:0;;;9803:507:14;;;2062:34820:0;259:819:16;2062:34820:0;;259:819:16;;;2062:34820:0;;259:819:16;;2062:34820:0;8554:20:14;259:819:16;;2062:34820:0;;10064:24:14;;2062:34820:0;8593:19:14;259:819:16;;2062:34820:0;8554:20:14;10103:22;;2062:34820:0;8631:26:14;259:819:16;;2062:34820:0;8593:19:14;10140:31;;2062:34820:0;259:819:16;;;2062:34820:0;8631:26:14;10186:25;;2062:34820:0;259:819:16;;;2062:34820:0;10226:20:14;2062:34820:0;1121:170:16;259:819;;2062:34820:0;7144:59:14;2062:34820:0;;;259:819:16;;;2062:34820:0;9803:507:14;;259:819:16;2062:34820:0;;;;;;;;;;;;;;10328:18:14;;9644:710;:::o;7916:13::-;8031:16;;;;;;;;:::i;:::-;9408:28;;;;:::i;:::-;9496:18;;;;;:::i;:::-;2062:34820:0;;;9339:278:14;;;;2062:34820:0;1522:130:16;2062:34820:0;;-1:-1:-1;;;;;2062:34820:0;;;1522:130:16;;;2062:34820:0;9455:22:14;;;2062:34820:0;;1522:130:16;;2062:34820:0;8554:20:14;2062:34820:0;;1522:130:16;;;2062:34820:0;;9533:26:14;;2062:34820:0;8593:19:14;1522:130:16;;2062:34820:0;8631:26:14;9578:24;;2062:34820:0;1522:130:16;;;2062:34820:0;9339:278:14;;1121:170:16;2062:34820:0;;;;;;;;;;;;;;;;;7984:65:14;2062:34820:0;;;;;;9315:313:14;;2062:34820:0;;;;1121:170:16;;;7984:65:14;;;;2062:34820:0;;;:::i;:::-;;;;;;;7984:65:14;;;;;;;;;:::i;:::-;2062:34820:0;;7916:13:14;;;;7493;7602;;;;;;;;:::i;:::-;8917:25;;;:::i;:::-;8961;;;;;;:::i;:::-;8480:19;;2062:34820:0;;;8851:300:14;-1:-1:-1;;;;;8851:300:14;;;2062:34820:0;1334:142:16;2062:34820:0;;;1334:142:16;;;2062:34820:0;;;;1334:142:16;;2062:34820:0;8554:20:14;9005:19;;;2062:34820:0;1334:142:16;;;2062:34820:0;8593:19:14;9043:18;2062:34820:0;9043:18:14;;2062:34820:0;1334:142:16;;;2062:34820:0;9080:17:14;;2062:34820:0;8631:26:14;1334:142:16;;2062:34820:0;1121:170:16;9116:20:14;;2062:34820:0;1334:142:16;;;2062:34820:0;8851:300:14;;1121:170:16;2062:34820:0;;;;;;;;;;;;;7558:59:14;2062:34820:0;;;;;;;;8827:335:14;;2062:34820:0;;;;1121:170:16;;;7558:59:14;;;;2062:34820:0;;;:::i;:::-;;;;;;;7558:59:14;;;;;;;;;:::i;:::-;2062:34820:0;;7493:13:14;;;;7079;7188;;;;;;;;:::i;:::-;8392:25;;;:::i;:::-;8436;;;;;;;:::i;:::-;8480:19;;2062:34820:0;;;8326:346:14;-1:-1:-1;;;;;8326:346:14;;;2062:34820:0;1121:170:16;2062:34820:0;;;1121:170:16;;;2062:34820:0;;;;1121:170:16;;2062:34820:0;8554:20:14;8480:19;;;2062:34820:0;1121:170:16;;;2062:34820:0;8593:19:14;2062:34820:0;8518:17:14;;2062:34820:0;1121:170:16;;;2062:34820:0;8631:26:14;8554:20;;;2062:34820:0;1121:170:16;;;2062:34820:0;8593:19:14;;2062:34820:0;1121:170:16;;;2062:34820:0;1121:170:16;8631:26:14;;2062:34820:0;1121:170:16;;;2062:34820:0;8326:346:14;;1121:170:16;2062:34820:0;;;;;;;;;;;;;;7144:59:14;2062:34820:0;;;;;;8302:381:14;;2062:34820:0;;;7144:59:14;;;;;;;2062:34820:0;;;:::i;:::-;;;;;;;7144:59:14;;;;;;;;;:::i;:::-;2062:34820:0;;7079:13:14;;;

Swarm Source

ipfs://9800c7c36427b365258d82fa3295222ea58e922efa24ba7e6b17182b8baae45e

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.