ETH Price: $2,966.62 (+3.55%)
Gas: 2 Gwei

Token

Metadate/a (MD)
 

Overview

Max Total Supply

3,413 MD

Holders

327

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
10 MD
0xd8F49165098943d450a52BD58d1B5de0D60d9ffD
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
Metadatea

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 16 : Metadatea.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

/*
                                                                                        @@@@@@@@@@@@
                                                                                        @@@@@@@@@@@@
                                                                                        @@@@@@@@@@@@
                                                                                        @@@@@@@@@@@@
                                                                                        @@@@@@@@@@@@
                                                                                        @@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                @@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                @@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                @@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                @@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                @@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                @@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@           @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@
@@@@@@@@@@@           @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@
@@@@@@@@@@@           @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@
@@@@@@@@@@@           @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@
@@@@@@@@@@@           @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@
@@@@@@@@@@@           @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@
@@@@@@@@@@@           @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@           @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@           @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@           @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@           @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@           @@@@@@@@@@@@          @@@@@@@@@@@@          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*/

import "erc721a/contracts/ERC721A.sol";
import "erc721a/contracts/extensions/ERC721AQueryable.sol";
import "erc721a/contracts/extensions/ERC721ABurnable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "./IERC4906.sol";
import "./Structs.sol";
import "./Art.sol";
import "./Utils.sol";

/// @title an ERC721A contract named Metadate/a
/// @author parker thompson
/// @notice NFTs with fully on-chain art generation
/// @dev implements ERC4906 to notify marketplaces of metadata updates
contract Metadatea is
    ERC721A,
    ERC721AQueryable,
    ERC721ABurnable,
    Ownable,
    IERC4906
{
    /// @notice variable to store an instance of the Art contract
    Art private _art;

    /// @notice deploys the Metadate/a contract and an instance of the Art contract
    constructor() ERC721A("Metadate/a", "MD") Ownable(msg.sender) {
        _art = new Art();

        // mint the first token to the deployer address
        _mint(msg.sender, 1);
        _mintArt(1, 0);
    }

    /// @notice get the start timestamp for collector claiming
    /// @dev 1705932000 == 9AM EST 1/22/24
    uint256 private constant _collectorsStart = 1705932000;

    /// @notice get the price to mint a token in wei
    /// @dev 5000000000000000 wei is 0.005 eth, ~$12.50 USD at time of deployment
    uint256 private constant _mintPrice = 5000000000000000;

    /// @notice get the status of super rare distribution
    /// @dev can only be updated by calling the distributeSuperRares function
    bool private _superRaresDistributed = false;

    /// @notice get the timestamp when minting closes
    /// @return mintCloseTime timestamp
    /// @dev will be updated when totalSupply is greater than _blanksToMint
    uint256 public mintCloseTime = 55555555555;

    /// @notice get the number of blanks that can be minted
    uint256 private constant _blanksToMint = 1000;

    /// @notice get the number of seconds to add to mintCloseTime after all blanks are minted
    /// @dev 259200 seconds == 72 hours
    uint256 private constant _mintSecondsTimerAfterBlanks = 259200;

    /// @notice get the count of token edits that have been made
    /// @return totalEdits count
    /// @dev stored as a public variable for accuracy and convenience
    uint256 public totalEdits = 0;

    /// @notice initialize an instance of the Abstract Glitch contract
    IERC721 private constant _abstractGlitch =
        IERC721(0xF9f27AA7718dCcF4b4306e0321c2Ce85215fA902);

    /// @notice map token IDs to a token struct to store metadata
    mapping(uint256 => Structs.Token) public tokens;

    /// @notice map wallet addresses that have claimed free tokens
    mapping(uint256 => bool) public claimedAbstractGlitchTokens;

    /// @notice map wallet addresses to the allow list
    mapping(address => bool) public allowListWallets;

    /// @notice check the active mint progression
    /// @dev use to qualify other contract functions
    function checkMintProgression() public view returns (uint256) {
        if (block.timestamp < _collectorsStart) {
            return 0; // minting hasn't started
        } else if (block.timestamp < _collectorsStart + 3 hours) {
            return 1; // abstract glitch holders claim
        } else if (block.timestamp < _collectorsStart + 7 hours) {
            return 2; // allow list mint
        } else if (block.timestamp < mintCloseTime) {
            return 3; // public mint
        } else {
            return 4; // mint ended
        }
    }

    /// @notice mint Metadate/a (MD) tokens
    /// @param quantity of tokens to mint
    /// @dev when _blanksToMint is reached, the minting window is updated
    function mint(uint256 quantity) public payable {
        uint256 mintProgression = checkMintProgression();

        if (msg.value < quantity * _mintPrice) {
            revert Utils.NotEnoughEth();
        }

        if (mintProgression == 2) {
            if (
                allowListWallets[msg.sender] ||
                _abstractGlitch.balanceOf(msg.sender) > 0
            ) {
                _handleMint(quantity);
            } else {
                revert Utils.NotAllowed();
            }
        } else if (mintProgression == 3) {
            _handleMint(quantity);
        } else {
            revert Utils.NotAllowed();
        }
    }

    /// @notice claim free Metadate/a (MD) tokens
    /// @param abstractGlitchId owned by message sender
    function claim(uint256 abstractGlitchId) public {
        if (
            _abstractGlitch.ownerOf(abstractGlitchId) == msg.sender &&
            !claimedAbstractGlitchTokens[abstractGlitchId] &&
            checkMintProgression() > 0 &&
            checkMintProgression() < 4
        ) {
            _handleMint(1);
            claimedAbstractGlitchTokens[abstractGlitchId] = true;
        } else {
            revert Utils.ClaimNotAvailable();
        }
    }

    /// @notice internal function to mint Metadate/a (MD) tokens
    /// @param quantity of tokens to mint
    function _handleMint(uint256 quantity) internal {
        for (uint256 i = 0; i < quantity; i++) {
            uint256 index = _nextTokenId() + i;
            if (index > _blanksToMint) {
                _mintArt(
                    index,
                    uint8(Utils.random(index + block.timestamp, 1, 6))
                );
            } else {
                if (index == _blanksToMint) {
                    mintCloseTime =
                        block.timestamp +
                        _mintSecondsTimerAfterBlanks;
                }
                _mintArt(index, 0);
            }
        }
        if (quantity <= 10) {
            _mint(msg.sender, quantity);
        } else {
            for (uint256 i = 0; i < quantity / 10; i++) {
                _mint(msg.sender, 10);
            }
            if (quantity % 10 > 0) {
                _mint(msg.sender, quantity % 10);
            }
        }
    }

    /// @notice saves the initial art of the token minted
    /// @dev uses the index of the _defaults mapping in the Art contract
    /// @dev only time the originalArtIndex is updated
    function _mintArt(uint256 id, uint256 originalArtIndex) internal {
        tokens[id].originalArtIndex = originalArtIndex;
        tokens[id].currentArtIndex = originalArtIndex;
    }

    /// @notice get the base64 encoded token URI
    /// @param tokenId of the token
    /// @return base64 encoded token URI
    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override(ERC721A, IERC721A)
        returns (string memory)
    {
        return _art.getTokenURI(tokenId, tokens[tokenId]);
    }

    /// @notice get the SVG art for a token
    /// @param tokenId of the token
    /// @return SVG art
    function getSvg(uint256 tokenId) public view returns (string memory) {
        return _art.renderSvg(tokens[tokenId]);
    }

    /// @notice edit a Metadate/a (MD) token
    /// @notice blank tokens can be edited once without burning any tokens
    /// @notice super rare tokens can be edited infinitely without burning any tokens
    /// @notice common tokens can be edited once by burning 4 other common tokens
    /// @notice only text, metadata, and text size can be edited for super rare tokens
    /// @param tokenIds array of token IDs to burn, including the token to keep as the FIRST token in the array
    /// @param artRules struct of art to update
    /// @param meta string of metadata to update
    function edit(
        uint256[] calldata tokenIds,
        Structs.ArtRules memory artRules,
        string memory meta
    ) public {
        uint256 tokenIdToKeep = tokenIds[0];
        if (!_ownsAllTokens(tokenIds, msg.sender)) {
            revert Utils.NotAllTokensOwned();
        }
        // checks to see if the token needs to be a blank or a super rare
        if (tokenIds.length == 1) {
            // checks to see if the token is a super rare
            if (
                tokens[tokenIdToKeep].currentArtIndex > 7 &&
                tokens[tokenIdToKeep].currentArtIndex < 11
            ) {
                if (
                    !Utils.validateTextSize(
                        artRules.labelText,
                        artRules.textSize
                    )
                ) {
                    revert Utils.InvalidText();
                }
                if (Utils.countCharacters(meta) > 100) {
                    revert Utils.MetaTooLong();
                }
                tokens[tokenIdToKeep].artRules.labelText = artRules.labelText;
                tokens[tokenIdToKeep].artRules.textSize = artRules.textSize;
                tokens[tokenIdToKeep].meta = meta;
                if (!tokens[tokenIdToKeep].edited) {
                    tokens[tokenIdToKeep].edited = true;
                }
            } else {
                if (
                    tokenIdToKeep > _blanksToMint ||
                    tokens[tokenIdToKeep].edited
                ) {
                    revert Utils.InvalidToken();
                }
                _updateArt(tokenIdToKeep, artRules, meta);
            }
            emit MetadataUpdate(tokenIdToKeep);
        } else if (tokenIds.length == 5) {
            if (tokens[tokenIdToKeep].edited) {
                revert Utils.InvalidToken();
            }
            for (uint256 i = 0; i < 5; i++) {
                if (
                    Utils.isSuperRareOrBlank(
                        tokens[tokenIds[i]].currentArtIndex
                    )
                ) {
                    revert Utils.InvalidToken();
                }
                if (tokenIds[i] == tokenIdToKeep) {
                    _updateArt(tokenIdToKeep, artRules, meta);
                    emit MetadataUpdate(tokenIdToKeep);
                } else {
                    burn(tokenIds[i]);
                    emit MetadataUpdate(tokenIds[i]);
                }
            }
        } else {
            revert Utils.InvalidQuantity();
        }
        totalEdits++;
    }

    /// @notice updates the metadata of a token
    /// @dev checks for art validity, but not if a token should be edited
    /// @dev the edit function checks if a token should be edited
    /// @dev this function is skipped for super rare tokens
    function _updateArt(
        uint256 tokenId,
        Structs.ArtRules memory artRules,
        string memory meta
    ) internal {
        if (artRules.spectrumIndex > 15) {
            revert Utils.InvalidSpectrum();
        }
        if (artRules.labelIndex > 7) {
            revert Utils.InvalidLabel();
        }
        if (!Utils.validateTextSize(artRules.labelText, artRules.textSize)) {
            revert Utils.InvalidText();
        }
        if (Utils.countCharacters(meta) > 100) {
            revert Utils.MetaTooLong();
        }
        tokens[tokenId].meta = meta;
        tokens[tokenId].artRules = Structs.ArtRules({
            stroke: artRules.stroke,
            vertical: artRules.vertical,
            spectrumIndex: artRules.spectrumIndex,
            labelIndex: artRules.labelIndex,
            labelText: artRules.labelText,
            textSize: artRules.textSize,
            whiteText: artRules.whiteText
        });
        // only update these if token has not been edited yet
        if (!tokens[tokenId].edited) {
            tokens[tokenId].edited = true;
            tokens[tokenId].currentArtIndex = 11;
        }
    }

    /// @notice check if all tokens in an array are owned by the same address
    function _ownsAllTokens(uint256[] calldata ids, address addy)
        internal
        view
        returns (bool)
    {
        for (uint256 i = 0; i < ids.length; i++) {
            if (ownerOf(ids[i]) != addy) {
                return false;
            }
        }
        return true;
    }

    /// @notice get the total number of tokens burned
    /// @return totalBurned count
    /// @dev will not include tokens manually sent to a 'burn' or 0x address
    function totalBurned() public view returns (uint256) {
        return _totalBurned();
    }

    /// @notice starts the token ID at 1 instead of 0
    function _startTokenId() internal view virtual override returns (uint256) {
        return 1;
    }

    /// @notice updates artwork for tokens that are burned
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual override {
        super._beforeTokenTransfers(from, to, startTokenId, quantity);
        if (to == address(0)) {
            tokens[startTokenId].currentArtIndex = 7;
        }
    }

    /// @notice add wallets to the allow list
    /// @param wallets to add
    function addAllowlistWallets(address[] calldata wallets) public onlyOwner {
        if (checkMintProgression() > 0) {
            revert Utils.NotAllowed();
        }
        for (uint256 i = 0; i < wallets.length; i++) {
            allowListWallets[wallets[i]] = true;
        }
    }

    /*
                                @@@@@@@@@@@@@@@              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                                @@@@@@@@@@@@@@@              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                                @@@@@@@@@@@@@@@              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                                @@@@@@@@@@@@@@@              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                                @@@@@@@@@@@@@@@              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                                @@@@@@@@@@@@@@@              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                                @@@@@@@@@@@@@@@              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                                @@@@@@@@@@@@@@@              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                  @@@@@@@@@@@@@@@                                                        @@@@@@@@@@@@@@@
                  @@@@@@@@@@@@@@@                                                        @@@@@@@@@@@@@@@
                  @@@@@@@@@@@@@@@                                                        @@@@@@@@@@@@@@@
                  @@@@@@@@@@@@@@@                                                        @@@@@@@@@@@@@@@
                  @@@@@@@@@@@@@@@                                                        @@@@@@@@@@@@@@@
                  @@@@@@@@@@@@@@@                                                        @@@@@@@@@@@@@@@
                  @@@@@@@@@@@@@@@                                                        @@@@@@@@@@@@@@@
                  @@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
                  @@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                  @@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                  @@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                  @@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                  @@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                  @@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
                  @@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@@@@@@@@@@@@@@@              
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@             @@@@@@@@@@@@@@@
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@             @@@@@@@@@@@@@@@
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@             @@@@@@@@@@@@@@@
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@             @@@@@@@@@@@@@@@
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@             @@@@@@@@@@@@@@@
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@             @@@@@@@@@@@@@@@
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@             @@@@@@@@@@@@@@@
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@                            @@@@@@@@@@@@@@@             @@@@@@@@@@@@@@@
    */

    /// @notice distributes super rare tokens
    /// @dev can only be called once after mint is closed
    function distributeSuperRares() public onlyOwner {
        if (checkMintProgression() < 4 || _superRaresDistributed) {
            revert Utils.NotAllowed();
        }
        for (uint256 i = 0; i < 200; i++) {
            // checks 200 common tokens for upgradability
            // edited and burned tokens will be skipped
            // it is likely that less than 200 super rares will exist
            uint256 random = Utils.random(i + 2024, _blanksToMint + 1, _totalMinted());
            if (!tokens[random].edited && tokens[random].currentArtIndex != 7) {
                tokens[random].currentArtIndex = Utils.random(i, 8, 10);
            }
        }
        _superRaresDistributed = true;
        emit BatchMetadataUpdate(_blanksToMint, _totalMinted());
    }

    /// @notice withdraw 50% of contract funds to each of two addresses
    function withdraw() external onlyOwner {
        uint256 bal = address(this).balance;
        if (bal == 0) {
            revert Utils.ZeroBalance();
        }

        uint256 amt1 = bal / 2;
        uint256 amt2 = bal - amt1;

        require(
            payable(0x9390333197446eC19B1B4Dc7dC7fc5ae4957ebBa).send(amt1) &&
                payable(0x38f0dBbA41258639ba0b2cdDC753E46157CE14d0).send(amt2)
        );
    }
}

File 2 of 16 : Utils.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

library Utils {
    /// @notice get a pseudo random number
    /// @param input to use as a randomness seed
    /// @param min value that can be returned
    /// @param max value that can be returned
    /// @return number that is randomized based on the params
    /// @dev the same input will always return the same output
    /// @dev min and max are inclusive values and can be returned
    function random(
        uint256 input,
        uint256 min,
        uint256 max
    ) internal pure returns (uint256) {
        uint256 randRange = max - min + 1;
        return min + (uint256(keccak256(abi.encodePacked(input))) % randRange);
    }

    /// @notice convert a number to a string
    /// @param number number to convert
    /// @return result string from the converted number
    function uint2string(
        uint256 number
    ) internal pure returns (string memory result) {
        if (number == 0) {
            return "0";
        }
        uint256 x = number;
        uint256 length;
        while (x != 0) {
            length++;
            x /= 10;
        }
        bytes memory conversion = new bytes(length);
        uint256 y = length;
        while (number != 0) {
            y = y - 1;
            uint8 temp = (48 + uint8(number - (number / 10) * 10));
            bytes1 b1 = bytes1(temp);
            conversion[y] = b1;
            number /= 10;
        }
        return string(conversion);
    }

    /// @notice convert a number to a hex formatted color
    /// @param color number to convert
    /// @return hex formatted color string
    function uint2hex(uint24 color) internal pure returns (string memory) {
        uint8 red = uint8(color >> 16);
        uint8 green = uint8(color >> 8);
        uint8 blue = uint8(color);
        return
            string(
                abi.encodePacked(
                    "#",
                    uint2string(red),
                    uint2string(green),
                    uint2string(blue)
                )
            );
    }

    /// @notice count the characters in a string
    /// @param input string to count
    /// @return number of characters in the string
    /// @dev counts the number of characters in a string
    /// @dev some complex characters (like emojis) may count as more than one
    function countCharacters(
        string memory input
    ) internal pure returns (uint256) {
        uint256 length = 0;
        uint256 i = 0;

        while (i < bytes(input).length) {
            if ((uint8(bytes(input)[i]) & 0xC0) != 0x80) {
                length++;
            }
            i++;
        }

        return length;
    }

    /// @notice validate text size for artwork
    /// @param textString string value of the text
    /// @param textSize number size of the text
    /// @return whether or not the text and size combo are valid
    function validateTextSize(
        string memory textString,
        uint256 textSize
    ) internal pure returns (bool) {
        if (textSize < 6 || textSize > 29) {
            return false;
        } else {
            uint256 length = countCharacters(textString);
            uint256 max;

            if (length <= 7) {
                max = 29;
            } else if (length <= 16) {
                max = 11;
            } else if (length <= 22) {
                max = 9;
            } else {
                revert("invalid length");
            }

            return (textSize <= max);
        }
    }

    /// @notice formats characters in a string for SVG code
    /// @param content string to format
    /// @return formatted string
    /// @dev checks for known characters that need to be converted for SVG (<, >, &)
    function formatCharacters(
        string memory content
    ) internal pure returns (string memory) {
        bytes memory contentBytes = bytes(content);
        bytes memory result = new bytes(contentBytes.length * 5);

        uint256 j = 0;
        for (uint256 i = 0; i < contentBytes.length; i++) {
            if (contentBytes[i] == "&") {
                result[j++] = bytes("&")[0];
                result[j++] = bytes("a")[0];
                result[j++] = bytes("m")[0];
                result[j++] = bytes("p")[0];
                result[j++] = bytes(";")[0];
            } else if (contentBytes[i] == "<") {
                result[j++] = bytes("&")[0];
                result[j++] = bytes("l")[0];
                result[j++] = bytes("t")[0];
                result[j++] = bytes(";")[0];
            } else if (contentBytes[i] == ">") {
                result[j++] = bytes("&")[0];
                result[j++] = bytes("g")[0];
                result[j++] = bytes("t")[0];
                result[j++] = bytes(";")[0];
            } else {
                result[j++] = contentBytes[i];
            }
        }

        bytes memory trimmedResult = new bytes(j);
        for (uint256 k = 0; k < j; k++) {
            trimmedResult[k] = result[k];
        }

        return string(trimmedResult);
    }

    /// @notice check if a token is a super rare or blank
    /// @param index of the current token art
    /// @return whether or not the token is a super rare or blank
    function isSuperRareOrBlank(uint256 index) internal pure returns (bool) {
        if (index == 0) {
            return true;
        } else if (index > 7 && index < 11) {
            return true;
        } else {
            return false;
        }
    }

    error NotEnoughEth();
    error MintEnded();
    error NotTime();
    error ClaimNotAvailable();
    error NotAllTokensOwned();
    error TokenIdMismatch();
    error InvalidToken();
    error InvalidText();
    error InvalidSpectrum();
    error InvalidLabel();
    error MetaTooLong();
    error InvalidQuantity();
    error NotAllowed();
    error ZeroBalance();
    error AlreadyCalled();
}

File 3 of 16 : Art.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

/*
---::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::---
-:.                      .                                            .               .          .:-
:.  .....:..............::::.:: .    .     .      .                  .                .           .-
:.  .+=-+*-=-:.-+:--:=+.###%-%*                               .                  .              . .-
:.  .+=-+*-=-:.-+:--:=+.###%-%*                 . .              .                 .   .          .-
:.  .+=-+*-=-:.-+:--:=+.###%-%*   .                                                               .-
:.  .+=-+*-=-:.-+:--:=+.###%-%*     .                       .          .                          .-
:.  .....:..............::::.::         .                             .        .        ..        .-
:.                          .         .          .                                              . .-
:.  .     .                              .                        .    .  .              .        .-
:.       .   .                           . .        .  .                                 .        .-
:.               .           .      .                            .                         .   .  .-
:.                .     .             .                                                           .-
:.                                        .             .    .                  .                 .-
:..     .                   .                                                .  ..                .-
:.                   .                                     .                     .       .       ..-
:.                                            .     .   .                    .                    .-
:.         .                                         .   .            .                     .     .-
:.     .                           .         .                                                    .-
:.        .                       .       .                                  .      .             .-
:.                               ..                              .                        .       .-
:.   .         ..:-==============================================================-:.              .-
:..    .     .+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%=       .    .-
:.         .+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%=          .-
:.   .    .#%%%%%%%%%%%%%%%%+-*%%%#--%#------+%--#%%%%%--%%%%%%%+-::-*%%%%%%%%%%%%%%%%%%+.        .-
:.       .+%%%%%%%%%%%%%%%%%= +%%%# .%* .****#%  #%%%%%. %%%%%*..=#*:..#%%%%%%%%%%%%%%%%%-        .-
:....    .%%%%%%%%%%%%%%%%%%= -++++ .%* .****%%  #%%%%%. %%%%%: *%%%%-.=%%%%%%%%%%%%%%%%%+.       .-
:.       .%%%%%%%%%%%%%%%%%%= :===- .%* .====%%  #%%%%%. %%%%#. #%%%%=.-%%%%%%%%%%%%%%%%%+        .-
:.        +%%%%%%%%%%%%%%%%%= +%%%# .%* .%%%%%%  #%%%%%..%%%%%= .*%%=. *%%%%%%%%%%%%%%%%%-        .-
:.        .#%%%%%%%%%%%%%%%%=.+%%%#.:%#......=%......-%......=%#-...:=%%%%%%%%%%%%%%%%%%+.        .-
:.        ..*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%=         ..-
:.       ..  .*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%=            .-
:.             ..:-=++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=-:.              .-
:.          ..     .                 .           .             .                                  .-
:.  .      .          .       .           .                 .              .      .               .-
:.             .             .      .        .         .   .            .   .  .    .         .   .-
:.   .         .         .         .                                   .                .         .-
:. .  .         .                                             .              .                    .-
:. .                                                               .               .              .-
:.                           .             .                              .           .           .-
:.                     .                                                                          .-
:.  .          .                                                                                  .-
:..                 .                     .                  .             .                      .-
:.       .            .         .  . .                              .                             .-
:.             .                     .                              .                   .     .   .-
:.                         .                       .                                    .    .    .-
:.                               .             .                       .                 .        .-
:.         .                          .             .                                   .         .-
:.                         .                                       ...  ...  ..  .... ...  ...    .-
:.     .      .                                           .    . ................::::.:::..::::.  .-
:.. .         .  .           .                         .         ................::::::::::::::.  .-
:.                 .                   .                 .        .............. ..............   .-
-:.    ..                  .         .           .                                               .::
---::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::---
*/

import "@openzeppelin/contracts/utils/Base64.sol";
import "./Structs.sol";
import "./Utils.sol";

contract Art {
    /// @notice index predefined label options
    mapping(uint256 => Structs.Label) private _labels;

    /// @notice index predefined color spectrums
    mapping(uint256 => Structs.Spectrum) private _spectrums;

    /// @notice index predefined art rules
    mapping(uint256 => Structs.ArtRules) private _defaults;

    /// @notice horizontal barcode SVG
    string constant horizontalBarcode =
        '<path d="M9 26.32H10.12V9H9V26.32Z"/><path d="M10.84 26.32H11.32V9H10.84V26.32Z"/><path d="M12.77 26.32H13.25V9H12.77V26.32Z"/><path d="M14.05 26.32H14.53V9H14.05V26.32Z"/><path d="M15.9 26.32H18.3V9H15.9V26.32Z"/><path d="M19.75 26.32H20.23V9H19.75V26.32Z"/><path d="M21.03 26.32H22.07V9H21.03V26.32Z"/><path d="M23.52 26.32H24V9H23.52V26.32Z"/><path d="M26.65 26.32H27.13V9H26.65V26.32Z"/><path d="M29.78 26.32H30.26V9H29.78V26.32Z"/><path d="M31.71 26.32H32.83V9H31.71V26.32Z"/><path d="M33.63 26.32H34.11V9H33.63V26.32Z"/><path d="M36.76 26.32H37.88V9H36.76V26.32Z"/><path d="M38.69 26.32H39.17V9H38.69V26.32Z"/><path d="M40.57 26.32H41.01V9H40.57V26.32Z"/><path d="M42.46 26.32H42.94V9H42.46V26.32Z"/><path d="M43.74 26.32H44.86V9H43.74V26.32Z"/><path d="M47.51 26.32H47.99V9H47.51V26.32Z"/><path d="M48.8 26.32H51.12V9H48.8V26.32Z"/><path d="M51.93 26.32H53.69V9H51.93V26.32Z"/><path d="M54.49 26.32H55.61V9H54.49V26.32Z"/><path d="M57.62 26.32H59.38V9H57.62V26.32Z"/><path d="M60.11 26.32H60.59V9H60.11V26.32Z"/><path d="M61.4 26.32H62.52V9H61.4V26.32Z"/>';

    /// @notice vertical barcode SVG
    string constant verticalBarcode =
        '<path d="M9 9L9 10.12L26.32 10.12V9L9 9Z"/><path d="M9 10.84L9 11.32L26.32 11.32V10.84L9 10.84Z"/><path d="M9 12.77L9 13.25L26.32 13.25V12.77L9 12.77Z"/><path d="M9 14.05L9 14.53L26.32 14.53V14.05L9 14.05Z"/><path d="M9 15.9L9 18.3L26.32 18.3V15.9L9 15.9Z"/><path d="M9 19.75L9 20.23L26.32 20.23V19.75L9 19.75Z"/><path d="M9 21.03L9 22.07L26.32 22.07V21.03L9 21.03Z"/><path d="M9 23.52L9 24L26.32 24V23.52L9 23.52Z"/><path d="M9 26.65L9 27.13H26.32V26.65H9Z"/><path d="M9 29.78L9 30.26H26.32V29.78H9Z"/><path d="M9 31.71L9 32.83H26.32V31.71H9Z"/><path d="M9 33.63L9 34.11H26.32V33.63H9Z"/><path d="M9 36.76L9 37.88H26.32V36.76H9Z"/><path d="M9 38.69L9 39.17H26.32V38.69H9Z"/><path d="M9 40.57L9 41.01H26.32L26.32 40.57H9Z"/><path d="M9 42.46L9 42.94H26.32V42.46H9Z"/><path d="M9 43.74L9 44.86H26.32V43.74H9Z"/><path d="M9 47.51L9 47.99H26.32V47.51H9Z"/><path d="M9 48.8L9 51.12H26.32V48.8H9Z"/><path d="M9 51.93L9 53.69H26.32V51.93H9Z"/><path d="M9 54.49L9 55.61H26.32V54.49H9Z"/><path d="M9 57.62L9 59.38H26.32V57.62H9Z"/><path d="M9 60.11L9 60.59H26.32V60.11H9Z"/><path d="M9 61.4L9 62.52H26.32V61.4H9Z"/>';

    constructor() {
        /// @notice populates all of the predefined art mappings
        _populateData();
    }

    /// @notice generate art rules for a token
    /// @param token for which to generate art rules
    /// @return artRules for a given token
    function _generateArtRules(Structs.Token memory token)
        internal
        view
        returns (Structs.ArtRules memory artRules)
    {
        uint256 artIndex = token.currentArtIndex;
        if (artIndex == 7) {
            // token is burned
            artRules = _defaults[7];
        } else if (artIndex > 7 && artIndex < 11) {
            // token is a super rare
            if (token.edited) {
                artRules = _defaults[artIndex];
                artRules.labelText = token.artRules.labelText;
                artRules.textSize = token.artRules.textSize;
            } else {
                artRules = _defaults[artIndex];
            }
        } else {
            // token is a blank or a common
            if (token.edited) {
                artRules = token.artRules;
            } else {
                artRules = _defaults[artIndex];
            }
        }
    }

    /// @notice render SVG code for a given token
    /// @param token for which to render SVG code
    /// @return svg code
    function renderSvg(Structs.Token memory token)
        public
        view
        returns (string memory svg)
    {
        string memory bg = "#FFF";
        string memory barcode;
        Structs.ArtRules memory artRules = _generateArtRules(token);
        uint256 artIndex = token.currentArtIndex;

        if (artIndex > 7 && artIndex < 11) {
            // token is a super rare
            // update the background color
            if (artIndex == 8) {
                bg = "#F6871F";
            } else if (artIndex == 9) {
                bg = "#00A651";
            } else if (artIndex == 10) {
                bg = "#004E7C";
            }
        }

        if (artIndex != 7) {
            barcode = artRules.vertical ? verticalBarcode : horizontalBarcode;
        }

        svg = string(
            abi.encodePacked(
                '<svg width="800" height="800" viewBox="0 0 202 202" fill="none" xmlns="http://www.w3.org/2000/svg"><rect id="bg" x="1" y="1" rx="6" width="200" height="200" fill="',
                bg,
                '"/><rect id="label" ',
                _labels[artRules.labelIndex].rounded ? 'rx="21"' : "",
                ' x="19" y="80" width="164" height="42" fill="#212121"/><path id="textpath" d="M19 101L183 101"/><text fill="#231F20" font-family="system-ui" font-size="',
                Utils.uint2string(artRules.textSize),
                '" font-weight="bold" text-anchor="middle" letter-spacing="0em" dy=".36em"><textPath href="#textpath" startOffset="50%">',
                Utils.formatCharacters(artRules.labelText),
                '</textPath></text><circle id="c6" cx="189" cy="189" r="5"/><circle id="c5" cx="179" cy="189" r="5"/><circle id="c4" cx="169" cy="189" r="5"/><circle id="c3" cx="159" cy="189" r="5"/><circle id="c2" cx="149" cy="189" r="5"/><circle id="c1" cx="139" cy="189" r="5"/><g id="barcode">',
                barcode,
                "</g><defs><style>#barcode path{fill:#010101}#label{fill:",
                _labels[artRules.labelIndex].color,
                "}text{fill:",
                artRules.whiteText ? "#FFF" : "#000",
                "}#bg{",
                artRules.stroke ? "stroke:#231F20" : "",
                "}",
                _spectrums[artRules.spectrumIndex].styles,
                "</style></defs></svg>"
            )
        );
    }

    /// @notice generate metadata for a given token
    /// @param tokenId of the token for which to generate metadata
    /// @param token for which to generate metadata
    /// @return metadata as a json string
    function _generateMetadata(uint256 tokenId, Structs.Token memory token)
        internal
        view
        returns (string memory)
    {
        return
            string(
                abi.encodePacked(
                    '{"name": "Metadate/a ',
                    Utils.uint2string(tokenId),
                    '", "description": "An immersive art installation recording the convergence of data.", "attributes": [',
                    _generateAttributes(token),
                    '], "image": "data:image/svg+xml;base64,',
                    Base64.encode(bytes(renderSvg(token))),
                    '"}'
                )
            );
    }

    /// @notice generate attributes for a given token
    /// @param token for which to generate attributes
    /// @return attributes for a given token
    function _generateAttributes(Structs.Token memory token)
        internal
        view
        returns (bytes memory)
    {
        if (token.currentArtIndex != 7) {
            Structs.ArtRules memory artRules = _generateArtRules(token);
            return
                abi.encodePacked(
                    _attribute("Burned", '"false"', true),
                    _attribute(
                        "Edited",
                        token.edited ? '"true"' : '"false"',
                        true
                    ),
                    _attribute(
                        "Original",
                        string(abi.encodePacked('"',_defaults[token.originalArtIndex].labelText,'"')),
                        true
                    ),
                    _attribute(
                        "Super Rare",
                        token.currentArtIndex > 7 && token.currentArtIndex < 11
                            ? '"true"'
                            : '"false"',
                        true
                    ),
                    _attribute(
                        "Stroke",
                        artRules.stroke ? '"true"' : '"false"',
                        true
                    ),
                    _attribute(
                        "Barcode",
                        artRules.vertical ? '"Vertical"' : '"Horizontal"',
                        true
                    ),
                    _attribute(
                        "Label Style",
                        _labels[artRules.labelIndex].rounded
                            ? '"Round"'
                            : '"Square"',
                        true
                    ),
                    _attribute(
                        "Color Spectrum",
                        string(abi.encodePacked('"',_spectrums[artRules.spectrumIndex].name,'"')),
                        true
                    ),
                    _attribute(
                        "Label Color",
                        string(abi.encodePacked('"',_labels[artRules.labelIndex].name,'"')),
                        true
                    ),
                    _attribute(
                        "Text Color",
                        artRules.whiteText ? '"White"' : '"Black"',
                        true
                    ),
                    _attribute(
                        "Text Size",
                        Utils.uint2string(artRules.textSize),
                        true
                    ),
                    _attribute("Metadata", string(abi.encodePacked('"',token.meta,'"')), false)
                );
        } else {
            return abi.encodePacked(_attribute("Burned", '"true"', false));
        }
    }

    /// @notice generate a formatted attribute
    /// @param attType type of attribute
    /// @param attValue value of attribute
    /// @param trailingComma whether or not to include a trailing comma
    function _attribute(
        string memory attType,
        string memory attValue,
        bool trailingComma
    ) internal pure returns (string memory) {
        return
            string(
                abi.encodePacked(
                    "{",
                    '"trait_type": "',
                    attType,
                    '",'
                    '"value": ',
                    attValue,
                    "}",
                    trailingComma ? "," : ""
                )
            );
    }

    /// @notice get the base64 encoded token URI
    /// @param tokenId of the token for which to get the base64 encoded token URI
    /// @param token for which to get the base64 encoded token URI
    /// @return base64 encoded token URI
    function getTokenURI(uint256 tokenId, Structs.Token memory token)
        public
        view
        returns (string memory)
    {
        return
            string(
                abi.encodePacked(
                    "data:application/json;base64,",
                    Base64.encode(bytes(_generateMetadata(tokenId, token)))
                )
            );
    }

    /// @notice initialize the art labels, spectrums, and defaults
    /// @dev only called once during deployment
    function _populateData() internal {
        _labels[0] = Structs.Label({
            name: "White",
            color: "#FFFEF7",
            rounded: true
        });
        _labels[1] = Structs.Label({
            name: "White",
            color: "#FFFEF7",
            rounded: false
        });
        _labels[2] = Structs.Label({
            name: "Red",
            color: "#E60020",
            rounded: true
        });
        _labels[3] = Structs.Label({
            name: "Red",
            color: "#E60020",
            rounded: false
        });
        _labels[4] = Structs.Label({
            name: "Yellow",
            color: "#FFAE00",
            rounded: true
        });
        _labels[5] = Structs.Label({
            name: "Yellow",
            color: "#FFAE00",
            rounded: false
        });
        _labels[6] = Structs.Label({
            name: "Gray",
            color: "#252425",
            rounded: true
        });
        _labels[7] = Structs.Label({
            name: "Gray",
            color: "#252425",
            rounded: false
        });
        _spectrums[0] = Structs.Spectrum({
            name: "Lagos",
            styles: "#c1{fill:#F16690;opacity:80%;}#c2{fill:#F16690;opacity:100%;}#c3{fill:#EFC3A3;opacity:80%;}#c4{fill:#EFC3A3;opacity:100%;}#c5{fill:#FFCF01;opacity:80%;}#c6{fill:#FFCF01;opacity:100%;}"
        });
        _spectrums[1] = Structs.Spectrum({
            name: "San Paulo",
            styles: "#c1{fill:#F15D2A;opacity:80%;}#c2{fill:#F15D2A;opacity:100%;}#c3{fill:#B2A9A7;opacity:80%;}#c4{fill:#B2A9A7;opacity:100%;}#c5{fill:#2D6CB5;opacity:80%;}#c6{fill:#2D6CB5;opacity:100%;}"
        });
        _spectrums[2] = Structs.Spectrum({
            name: "Bogota",
            styles: "#c1{fill:#F26D61;opacity:80%;}#c2{fill:#F26D61;opacity:100%;}#c3{fill:#A3C7E9;opacity:80%;}#c4{fill:#A3C7E9;opacity:100%;}#c5{fill:#669060;opacity:80%;}#c6{fill:#669060;opacity:100%;}"
        });
        _spectrums[3] = Structs.Spectrum({
            name: "Johannesburg",
            styles: "#c1{fill:#EE202E;opacity:80%;}#c2{fill:#EE202E;opacity:100%;}#c3{fill:#F5E1D3;opacity:80%;}#c4{fill:#F5E1D3;opacity:100%;}#c5{fill:#333132;opacity:80%;}#c6{fill:#333132;opacity:100%;}"
        });
        _spectrums[4] = Structs.Spectrum({
            name: "Vancouver",
            styles: "#c1{fill:#231F20;opacity:15%;}#c2{fill:#231F20;opacity:30%;}#c3{fill:#231F20;opacity:45%;}#c4{fill:#231F20;opacity:60%;}#c5{fill:#231F20;opacity:75%;}#c6{fill:#231F20;opacity:90%;}"
        });
        _spectrums[5] = Structs.Spectrum({
            name: "Arizona",
            styles: "#c1{fill:#FFCF01;opacity:15%;}#c2{fill:#FFCF01;opacity:30%;}#c3{fill:#FFCF01;opacity:45%;}#c4{fill:#FFCF01;opacity:60%;}#c5{fill:#FFCF01;opacity:75%;}#c6{fill:#FFCF01;opacity:90%;}"
        });
        _spectrums[6] = Structs.Spectrum({
            name: "Miami",
            styles: "#c1{fill:#EF4277;opacity:80%;}#c2{fill:#EF4277;opacity:100%;}#c3{fill:#26A191;opacity:80%;}#c4{fill:#26A191;opacity:100%;}#c5{fill:#FFCF01;opacity:80%;}#c6{fill:#FFCF01;opacity:100%;}"
        });
        _spectrums[7] = Structs.Spectrum({
            name: "San Antonio",
            styles: "#c1{fill:#FB8C05;opacity:100%;}#c2{fill:#990037;opacity:100%;}#c3{fill:#00315E;opacity:100%;}#c4{fill:#00315E;opacity:100%;}#c5{fill:#990037;opacity:100%;}#c6{fill:#FB8C05;opacity:100%;}"
        });
        _spectrums[8] = Structs.Spectrum({
            name: "New York",
            styles: "#c1{fill:#002850;opacity:15%;}#c2{fill:#002850;opacity:30%;}#c3{fill:#002850;opacity:45%;}#c4{fill:#002850;opacity:60%;}#c5{fill:#002850;opacity:75%;}#c6{fill:#002850;opacity:90%;}"
        });
        _spectrums[9] = Structs.Spectrum({
            name: "Maryland",
            styles: "#c1{fill:#FA8A24;opacity:100%;}#c2{fill:#1A1818;opacity:100%;}#c3{fill:#E60020;opacity:100%;}#c4{fill:#E60020;opacity:100%;}#c5{fill:#1A1818;opacity:100%;}#c6{fill:#FA8A24;opacity:100%;}"
        });
        _spectrums[10] = Structs.Spectrum({
            name: "Singapore",
            styles: "#c1{fill:#B58B7F;opacity:100%;}#c2{fill:#1A1818;opacity:100%;}#c3{fill:#00A4A5;opacity:100%;}#c4{fill:#00A4A5;opacity:100%;}#c5{fill:#1A1818;opacity:100%;}#c6{fill:#B58B7F;opacity:100%;}"
        });
        _spectrums[11] = Structs.Spectrum({
            name: "Wyoming",
            styles: "#c1{fill:#B17E54;opacity:15%;}#c2{fill:#A26C41;opacity:30%;}#c3{fill:#955D31;opacity:45%;}#c4{fill:#874D1F;opacity:60%;}#c5{fill:#783E0C;opacity:75%;}#c6{fill:#6A3100;opacity:90%;}"
        });
        _spectrums[12] = Structs.Spectrum({
            name: "Cluj",
            styles: "#c1{fill:#FFF032;opacity:100%;}#c2{fill:#003E6A;opacity:100%;}#c3{fill:#4E4E49;opacity:100%;}#c4{fill:#4E4E49;opacity:100%;}#c5{fill:#003E6A;opacity:100%;}#c6{fill:#FFF032;opacity:100%;}"
        });
        _spectrums[13] = Structs.Spectrum({
            name: "Chicago",
            styles: "#c1{fill:#E60020;opacity:15%;}#c2{fill:#E60020;opacity:30%;}#c3{fill:#E60020;opacity:45%;}#c4{fill:#E60020;opacity:60%;}#c5{fill:#E60020;opacity:75%;}#c6{fill:#E60020;opacity:90%;}"
        });
        _spectrums[14] = Structs.Spectrum({
            name: "Portland",
            styles: "#c1{fill:#568861;opacity:100%;}#c2{fill:#457B53;opacity:100%;}#c3{fill:#326E43;opacity:100%;}#c4{fill:#206134;opacity:100%;}#c5{fill:#005526;opacity:100%;}#c6{fill:#004B1C;opacity:100%;}"
        });
        _spectrums[15] = Structs.Spectrum({name: "None", styles: ""});
        // blank
        _defaults[0] = Structs.ArtRules({
            stroke: false,
            vertical: false,
            spectrumIndex: 0,
            labelIndex: 0,
            labelText: "",
            textSize: 9,
            whiteText: false
        });
        _defaults[1] = Structs.ArtRules({
            stroke: false,
            vertical: false,
            spectrumIndex: 5,
            labelIndex: 0,
            labelText: "July 11th, 2022",
            textSize: 11,
            whiteText: false
        });
        _defaults[2] = Structs.ArtRules({
            stroke: false,
            vertical: true,
            spectrumIndex: 4,
            labelIndex: 0,
            labelText: "PAIN BEFORE PROGRESS",
            textSize: 9,
            whiteText: false
        });
        _defaults[3] = Structs.ArtRules({
            stroke: false,
            vertical: false,
            spectrumIndex: 9,
            labelIndex: 0,
            labelText: "November 6th, 1990",
            textSize: 9,
            whiteText: false
        });
        _defaults[4] = Structs.ArtRules({
            stroke: false,
            vertical: false,
            spectrumIndex: 14,
            labelIndex: 0,
            labelText: "October 31st, 2008",
            textSize: 9,
            whiteText: false
        });
        _defaults[5] = Structs.ArtRules({
            stroke: false,
            vertical: true,
            spectrumIndex: 8,
            labelIndex: 0,
            labelText: "THE MARATHON CONTINUES",
            textSize: 9,
            whiteText: false
        });
        _defaults[6] = Structs.ArtRules({
            stroke: true,
            vertical: true,
            spectrumIndex: 3,
            labelIndex: 0,
            labelText: "MAMBA MENTALITY",
            textSize: 9,
            whiteText: false
        });
        // burned
        _defaults[7] = Structs.ArtRules({
            stroke: false,
            vertical: false,
            spectrumIndex: 15,
            labelIndex: 2,
            labelText: "*NOT FOR RESALE",
            textSize: 14,
            whiteText: true
        });
        // super rare: orange
        _defaults[8] = Structs.ArtRules({
            stroke: false,
            vertical: true,
            spectrumIndex: 8,
            labelIndex: 0,
            labelText: "",
            textSize: 9,
            whiteText: false
        });
        // super rare: green
        _defaults[9] = Structs.ArtRules({
            stroke: false,
            vertical: false,
            spectrumIndex: 1,
            labelIndex: 0,
            labelText: "",
            textSize: 9,
            whiteText: false
        });
        // super rare: blue
        _defaults[10] = Structs.ArtRules({
            stroke: false,
            vertical: false,
            spectrumIndex: 13,
            labelIndex: 2,
            labelText: "",
            textSize: 9,
            whiteText: false
        });
    }
}

File 4 of 16 : Structs.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

library Structs {
    struct Label {
        string name;
        string color;
        bool rounded;
    }

    struct Spectrum {
        string name;
        string styles;
    }

    struct ArtRules {
        bool stroke;
        bool vertical;
        bool whiteText;
        string labelText;
        uint256 spectrumIndex;
        uint256 labelIndex;
        uint256 textSize;
    }

    struct Token {
        bool edited;
        uint256 originalArtIndex;
        uint256 currentArtIndex;
        string meta;
        ArtRules artRules;
    }
}

File 5 of 16 : IERC4906.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.23;

/// @title EIP-721 Metadata Update Extension
interface IERC4906 {
    /// @dev This event emits when the metadata of a token is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFT.
    event MetadataUpdate(uint256 _tokenId);

    /// @dev This event emits when the metadata of a range of tokens is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFTs.    
    event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}

File 6 of 16 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

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

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * 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 address zero.
     *
     * 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 7 of 16 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

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

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

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

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

pragma solidity ^0.8.4;

import './IERC721ABurnable.sol';
import '../ERC721A.sol';

/**
 * @title ERC721ABurnable.
 *
 * @dev ERC721A token that can be irreversibly burned (destroyed).
 */
abstract contract ERC721ABurnable is ERC721A, IERC721ABurnable {
    /**
     * @dev Burns `tokenId`. See {ERC721A-_burn}.
     *
     * Requirements:
     *
     * - The caller must own `tokenId` or be an approved operator.
     */
    function burn(uint256 tokenId) public virtual override {
        _burn(tokenId, true);
    }
}

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

pragma solidity ^0.8.4;

import './IERC721AQueryable.sol';
import '../ERC721A.sol';

/**
 * @title ERC721AQueryable.
 *
 * @dev ERC721A subclass with convenience query functions.
 */
abstract contract ERC721AQueryable is ERC721A, IERC721AQueryable {
    /**
     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
     *
     * If the `tokenId` is out of bounds:
     *
     * - `addr = address(0)`
     * - `startTimestamp = 0`
     * - `burned = false`
     * - `extraData = 0`
     *
     * If the `tokenId` is burned:
     *
     * - `addr = <Address of owner before token was burned>`
     * - `startTimestamp = <Timestamp when token was burned>`
     * - `burned = true`
     * - `extraData = <Extra data when token was burned>`
     *
     * Otherwise:
     *
     * - `addr = <Address of owner>`
     * - `startTimestamp = <Timestamp of start of ownership>`
     * - `burned = false`
     * - `extraData = <Extra data at start of ownership>`
     */
    function explicitOwnershipOf(uint256 tokenId) public view virtual override returns (TokenOwnership memory) {
        TokenOwnership memory ownership;
        if (tokenId < _startTokenId() || tokenId >= _nextTokenId()) {
            return ownership;
        }
        ownership = _ownershipAt(tokenId);
        if (ownership.burned) {
            return ownership;
        }
        return _ownershipOf(tokenId);
    }

    /**
     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
     * See {ERC721AQueryable-explicitOwnershipOf}
     */
    function explicitOwnershipsOf(uint256[] calldata tokenIds)
        external
        view
        virtual
        override
        returns (TokenOwnership[] memory)
    {
        unchecked {
            uint256 tokenIdsLength = tokenIds.length;
            TokenOwnership[] memory ownerships = new TokenOwnership[](tokenIdsLength);
            for (uint256 i; i != tokenIdsLength; ++i) {
                ownerships[i] = explicitOwnershipOf(tokenIds[i]);
            }
            return ownerships;
        }
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`,
     * in the range [`start`, `stop`)
     * (i.e. `start <= tokenId < stop`).
     *
     * This function allows for tokens to be queried if the collection
     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
     *
     * Requirements:
     *
     * - `start < stop`
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) external view virtual override returns (uint256[] memory) {
        unchecked {
            if (start >= stop) revert InvalidQueryRange();
            uint256 tokenIdsIdx;
            uint256 stopLimit = _nextTokenId();
            // Set `start = max(start, _startTokenId())`.
            if (start < _startTokenId()) {
                start = _startTokenId();
            }
            // Set `stop = min(stop, stopLimit)`.
            if (stop > stopLimit) {
                stop = stopLimit;
            }
            uint256 tokenIdsMaxLength = balanceOf(owner);
            // Set `tokenIdsMaxLength = min(balanceOf(owner), stop - start)`,
            // to cater for cases where `balanceOf(owner)` is too big.
            if (start < stop) {
                uint256 rangeLength = stop - start;
                if (rangeLength < tokenIdsMaxLength) {
                    tokenIdsMaxLength = rangeLength;
                }
            } else {
                tokenIdsMaxLength = 0;
            }
            uint256[] memory tokenIds = new uint256[](tokenIdsMaxLength);
            if (tokenIdsMaxLength == 0) {
                return tokenIds;
            }
            // We need to call `explicitOwnershipOf(start)`,
            // because the slot at `start` may not be initialized.
            TokenOwnership memory ownership = explicitOwnershipOf(start);
            address currOwnershipAddr;
            // If the starting slot exists (i.e. not burned), initialize `currOwnershipAddr`.
            // `ownership.address` will not be zero, as `start` is clamped to the valid token ID range.
            if (!ownership.burned) {
                currOwnershipAddr = ownership.addr;
            }
            for (uint256 i = start; i != stop && tokenIdsIdx != tokenIdsMaxLength; ++i) {
                ownership = _ownershipAt(i);
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            // Downsize the array to fit.
            assembly {
                mstore(tokenIds, tokenIdsIdx)
            }
            return tokenIds;
        }
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(`totalSupply`) in complexity.
     * It is meant to be called off-chain.
     *
     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
     * multiple smaller scans if the collection is large enough to cause
     * an out-of-gas error (10K collections should be fine).
     */
    function tokensOfOwner(address owner) external view virtual override returns (uint256[] memory) {
        unchecked {
            uint256 tokenIdsIdx;
            address currOwnershipAddr;
            uint256 tokenIdsLength = balanceOf(owner);
            uint256[] memory tokenIds = new uint256[](tokenIdsLength);
            TokenOwnership memory ownership;
            for (uint256 i = _startTokenId(); tokenIdsIdx != tokenIdsLength; ++i) {
                ownership = _ownershipAt(i);
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            return tokenIds;
        }
    }
}

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

pragma solidity ^0.8.4;

import './IERC721A.sol';

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return _tokenApprovals[tokenId].value;
    }

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

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

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

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

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

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

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

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

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

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

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

        _beforeTokenTransfers(from, to, tokenId, 1);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            uint256 toMasked;
            uint256 end = startTokenId + quantity;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        address from = address(uint160(prevOwnershipPacked));

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.4;

import '../IERC721A.sol';

/**
 * @dev Interface of ERC721AQueryable.
 */
interface IERC721AQueryable is IERC721A {
    /**
     * Invalid query range (`start` >= `stop`).
     */
    error InvalidQueryRange();

    /**
     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
     *
     * If the `tokenId` is out of bounds:
     *
     * - `addr = address(0)`
     * - `startTimestamp = 0`
     * - `burned = false`
     * - `extraData = 0`
     *
     * If the `tokenId` is burned:
     *
     * - `addr = <Address of owner before token was burned>`
     * - `startTimestamp = <Timestamp when token was burned>`
     * - `burned = true`
     * - `extraData = <Extra data when token was burned>`
     *
     * Otherwise:
     *
     * - `addr = <Address of owner>`
     * - `startTimestamp = <Timestamp of start of ownership>`
     * - `burned = false`
     * - `extraData = <Extra data at start of ownership>`
     */
    function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory);

    /**
     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
     * See {ERC721AQueryable-explicitOwnershipOf}
     */
    function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory);

    /**
     * @dev Returns an array of token IDs owned by `owner`,
     * in the range [`start`, `stop`)
     * (i.e. `start <= tokenId < stop`).
     *
     * This function allows for tokens to be queried if the collection
     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
     *
     * Requirements:
     *
     * - `start < stop`
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) external view returns (uint256[] memory);

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(`totalSupply`) in complexity.
     * It is meant to be called off-chain.
     *
     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
     * multiple smaller scans if the collection is large enough to cause
     * an out-of-gas error (10K collections should be fine).
     */
    function tokensOfOwner(address owner) external view returns (uint256[] memory);
}

File 12 of 16 : IERC721ABurnable.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

import '../IERC721A.sol';

/**
 * @dev Interface of ERC721ABurnable.
 */
interface IERC721ABurnable is IERC721A {
    /**
     * @dev Burns `tokenId`. See {ERC721A-_burn}.
     *
     * Requirements:
     *
     * - The caller must own `tokenId` or be an approved operator.
     */
    function burn(uint256 tokenId) external;
}

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

pragma solidity ^0.8.4;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

File 14 of 16 : Base64.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Base64.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return result;
    }
}

File 15 of 16 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

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

File 16 of 16 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

Settings
{
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"ClaimNotAvailable","type":"error"},{"inputs":[],"name":"InvalidLabel","type":"error"},{"inputs":[],"name":"InvalidQuantity","type":"error"},{"inputs":[],"name":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"InvalidSpectrum","type":"error"},{"inputs":[],"name":"InvalidText","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"MetaTooLong","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"NotAllTokensOwned","type":"error"},{"inputs":[],"name":"NotAllowed","type":"error"},{"inputs":[],"name":"NotEnoughEth","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ZeroBalance","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address[]","name":"wallets","type":"address[]"}],"name":"addAllowlistWallets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowListWallets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"checkMintProgression","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"abstractGlitchId","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimedAbstractGlitchTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"distributeSuperRares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"components":[{"internalType":"bool","name":"stroke","type":"bool"},{"internalType":"bool","name":"vertical","type":"bool"},{"internalType":"bool","name":"whiteText","type":"bool"},{"internalType":"string","name":"labelText","type":"string"},{"internalType":"uint256","name":"spectrumIndex","type":"uint256"},{"internalType":"uint256","name":"labelIndex","type":"uint256"},{"internalType":"uint256","name":"textSize","type":"uint256"}],"internalType":"struct Structs.ArtRules","name":"artRules","type":"tuple"},{"internalType":"string","name":"meta","type":"string"}],"name":"edit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitOwnershipOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"explicitOwnershipsOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getSvg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintCloseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokens","outputs":[{"internalType":"bool","name":"edited","type":"bool"},{"internalType":"uint256","name":"originalArtIndex","type":"uint256"},{"internalType":"uint256","name":"currentArtIndex","type":"uint256"},{"internalType":"string","name":"meta","type":"string"},{"components":[{"internalType":"bool","name":"stroke","type":"bool"},{"internalType":"bool","name":"vertical","type":"bool"},{"internalType":"bool","name":"whiteText","type":"bool"},{"internalType":"string","name":"labelText","type":"string"},{"internalType":"uint256","name":"spectrumIndex","type":"uint256"},{"internalType":"uint256","name":"labelIndex","type":"uint256"},{"internalType":"uint256","name":"textSize","type":"uint256"}],"internalType":"struct Structs.ArtRules","name":"artRules","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"tokensOfOwnerIn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBurned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalEdits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040525f600960146101000a81548160ff021916908315150217905550640cef5e80e3600a555f600b5534801562000037575f80fd5b50336040518060400160405280600a81526020017f4d657461646174652f61000000000000000000000000000000000000000000008152506040518060400160405280600281526020017f4d440000000000000000000000000000000000000000000000000000000000008152508160029081620000b6919062000826565b508060039081620000c8919062000826565b50620000d9620001f960201b60201c565b5f8190555050505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362000153575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016200014a91906200094d565b60405180910390fd5b62000164816200020160201b60201c565b506040516200017390620005b4565b604051809103905ff0801580156200018d573d5f803e3d5ffd5b5060095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001e0336001620002c460201b60201c565b620001f360015f6200049960201b60201c565b62000968565b5f6001905090565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f805490505f820362000303576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620003175f848385620004cf60201b60201c565b600160406001901b17820260055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282540192505081905550620003a183620003835f865f6200053860201b60201c565b62000394856200056760201b60201c565b176200057660201b60201c565b60045f8381526020019081526020015f20819055505f80838301905073ffffffffffffffffffffffffffffffffffffffff8516915082825f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4600183015b8181146200043d5780835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a460018101905062000402565b505f820362000478576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f819055505050620004945f848385620005a060201b60201c565b505050565b80600c5f8481526020019081526020015f206001018190555080600c5f8481526020019081526020015f20600201819055505050565b620004e384848484620005a660201b60201c565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362000532576007600c5f8481526020019081526020015f20600201819055505b50505050565b5f8060e883901c905060e862000556868684620005ac60201b60201c565b62ffffff16901b9150509392505050565b5f6001821460e11b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b50505050565b5f9392505050565b61680b80620057f183390190565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200063e57607f821691505b602082108103620006545762000653620005f9565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620006b87fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200067b565b620006c486836200067b565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6200070e620007086200070284620006dc565b620006e5565b620006dc565b9050919050565b5f819050919050565b6200072983620006ee565b62000741620007388262000715565b84845462000687565b825550505050565b5f90565b6200075762000749565b620007648184846200071e565b505050565b5b818110156200078b576200077f5f826200074d565b6001810190506200076a565b5050565b601f821115620007da57620007a4816200065a565b620007af846200066c565b81016020851015620007bf578190505b620007d7620007ce856200066c565b83018262000769565b50505b505050565b5f82821c905092915050565b5f620007fc5f1984600802620007df565b1980831691505092915050565b5f620008168383620007eb565b9150826002028217905092915050565b6200083182620005c2565b67ffffffffffffffff8111156200084d576200084c620005cc565b5b62000859825462000626565b620008668282856200078f565b5f60209050601f8311600181146200089c575f841562000887578287015190505b62000893858262000809565b86555062000902565b601f198416620008ac866200065a565b5f5b82811015620008d557848901518255600182019150602085019450602081019050620008ae565b86831015620008f55784890151620008f1601f891682620007eb565b8355505b6001600288020188555050505b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f62000935826200090a565b9050919050565b620009478162000929565b82525050565b5f602082019050620009625f8301846200093c565b92915050565b614e7b80620009765f395ff3fe60806040526004361061020e575f3560e01c80638462151c11610117578063bd296d231161009f578063d89135cd1161006e578063d89135cd1461078a578063d9e54e24146107b4578063dac2e804146107de578063e985e9c514610808578063f2fde38b146108445761020e565b8063bd296d23146106c2578063c23dc68f146106ea578063c87b56dd14610726578063d1f7a9c5146107625761020e565b806399a2557a116100e657806399a2557a146105ea578063a0712d6814610626578063a22cb46514610642578063b0dc78fa1461066a578063b88d4fde146106a65761020e565b80638462151c146105305780638a0275fe1461056c5780638da5cb5b1461059657806395d89b41146105c05761020e565b806342842e0e1161019a5780635bbb2177116101695780635bbb21771461042a5780636352211e146104665780636511cc77146104a257806370a08231146104de578063715018a61461051a5761020e565b806342842e0e1461036a57806342966c68146103865780634f64b2be146103ae5780635a72bfa9146103ee5761020e565b806318160ddd116101e157806318160ddd146102d057806323b872dd146102fa578063379607f5146103165780633ccfd60b1461033e5780634063151d146103545761020e565b806301ffc9a71461021257806306fdde031461024e578063081812fc14610278578063095ea7b3146102b4575b5f80fd5b34801561021d575f80fd5b5061023860048036038101906102339190613732565b61086c565b6040516102459190613777565b60405180910390f35b348015610259575f80fd5b506102626108fd565b60405161026f919061381a565b60405180910390f35b348015610283575f80fd5b5061029e6004803603810190610299919061386d565b61098d565b6040516102ab91906138d7565b60405180910390f35b6102ce60048036038101906102c9919061391a565b610a07565b005b3480156102db575f80fd5b506102e4610b46565b6040516102f19190613967565b60405180910390f35b610314600480360381019061030f9190613980565b610b5b565b005b348015610321575f80fd5b5061033c6004803603810190610337919061386d565b610e69565b005b348015610349575f80fd5b50610352610fe1565b005b34801561035f575f80fd5b506103686110ea565b005b610384600480360381019061037f9190613980565b611261565b005b348015610391575f80fd5b506103ac60048036038101906103a7919061386d565b611280565b005b3480156103b9575f80fd5b506103d460048036038101906103cf919061386d565b61128e565b6040516103e5959493929190613acf565b60405180910390f35b3480156103f9575f80fd5b50610414600480360381019061040f919061386d565b611457565b6040516104219190613777565b60405180910390f35b348015610435575f80fd5b50610450600480360381019061044b9190613b8f565b611474565b60405161045d9190613d23565b60405180910390f35b348015610471575f80fd5b5061048c6004803603810190610487919061386d565b611534565b60405161049991906138d7565b60405180910390f35b3480156104ad575f80fd5b506104c860048036038101906104c39190613d43565b611545565b6040516104d59190613777565b60405180910390f35b3480156104e9575f80fd5b5061050460048036038101906104ff9190613d43565b611562565b6040516105119190613967565b60405180910390f35b348015610525575f80fd5b5061052e611617565b005b34801561053b575f80fd5b5061055660048036038101906105519190613d43565b61162a565b6040516105639190613e16565b60405180910390f35b348015610577575f80fd5b50610580611766565b60405161058d9190613967565b60405180910390f35b3480156105a1575f80fd5b506105aa61176c565b6040516105b791906138d7565b60405180910390f35b3480156105cb575f80fd5b506105d4611794565b6040516105e1919061381a565b60405180910390f35b3480156105f5575f80fd5b50610610600480360381019061060b9190613e36565b611824565b60405161061d9190613e16565b60405180910390f35b610640600480360381019061063b919061386d565b611a23565b005b34801561064d575f80fd5b5061066860048036038101906106639190613eb0565b611bf8565b005b348015610675575f80fd5b50610690600480360381019061068b919061386d565b611cfe565b60405161069d919061381a565b60405180910390f35b6106c060048036038101906106bb9190614016565b611db3565b005b3480156106cd575f80fd5b506106e860048036038101906106e39190614209565b611e25565b005b3480156106f5575f80fd5b50610710600480360381019061070b919061386d565b6122d9565b60405161071d9190614305565b60405180910390f35b348015610731575f80fd5b5061074c6004803603810190610747919061386d565b612343565b604051610759919061381a565b60405180910390f35b34801561076d575f80fd5b5061078860048036038101906107839190614373565b6123fa565b005b348015610795575f80fd5b5061079e6124de565b6040516107ab9190613967565b60405180910390f35b3480156107bf575f80fd5b506107c86124ec565b6040516107d59190613967565b60405180910390f35b3480156107e9575f80fd5b506107f2612560565b6040516107ff9190613967565b60405180910390f35b348015610813575f80fd5b5061082e600480360381019061082991906143be565b612566565b60405161083b9190613777565b60405180910390f35b34801561084f575f80fd5b5061086a60048036038101906108659190613d43565b6125f4565b005b5f6301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108c657506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806108f65750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60606002805461090c90614429565b80601f016020809104026020016040519081016040528092919081815260200182805461093890614429565b80156109835780601f1061095a57610100808354040283529160200191610983565b820191905f5260205f20905b81548152906001019060200180831161096657829003601f168201915b5050505050905090565b5f61099782612678565b6109cd576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60065f8381526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f610a1182611534565b90508073ffffffffffffffffffffffffffffffffffffffff16610a326126d2565b73ffffffffffffffffffffffffffffffffffffffff1614610a9557610a5e81610a596126d2565b612566565b610a94576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b8260065f8481526020019081526020015f205f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b5f610b4f6126d9565b6001545f540303905090565b5f610b65826126e1565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610bcc576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80610bd7846127a4565b91509150610bed8187610be86126d2565b6127c7565b610c3957610c0286610bfd6126d2565b612566565b610c38576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610c9e576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cab868686600161280a565b8015610cb5575f82555b60055f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154600190039190508190555060055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815460010191905081905550610d7d85610d5988888761286a565b7c020000000000000000000000000000000000000000000000000000000017612891565b60045f8681526020019081526020015f20819055505f7c0200000000000000000000000000000000000000000000000000000000841603610df9575f6001850190505f60045f8381526020019081526020015f205403610df7575f548114610df6578360045f8381526020019081526020015f20819055505b5b505b838573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4610e6186868660016128bb565b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1673f9f27aa7718dccf4b4306e0321c2ce85215fa90273ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610ecd9190613967565b602060405180830381865afa158015610ee8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f0c919061446d565b73ffffffffffffffffffffffffffffffffffffffff16148015610f4a5750600d5f8281526020019081526020015f205f9054906101000a900460ff16155b8015610f5c57505f610f5a6124ec565b115b8015610f6f57506004610f6d6124ec565b105b15610fac57610f7e60016128c1565b6001600d5f8381526020019081526020015f205f6101000a81548160ff021916908315150217905550610fde565b6040517f3c21f90f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b610fe96129c2565b5f4790505f8103611026576040517f669567ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60028261103491906144f2565b90505f81836110439190614522565b9050739390333197446ec19b1b4dc7dc7fc5ae4957ebba73ffffffffffffffffffffffffffffffffffffffff166108fc8390811502906040515f60405180830381858888f1935050505080156110dd57507338f0dbba41258639ba0b2cddc753e46157ce14d073ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f193505050505b6110e5575f80fd5b505050565b6110f26129c2565b60046110fc6124ec565b10806111145750600960149054906101000a900460ff165b1561114b576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b60c8811015611201575f6111846107e8836111689190614555565b60016103e86111779190614555565b61117f612a49565b612a5a565b9050600c5f8281526020019081526020015f205f015f9054906101000a900460ff161580156111c857506007600c5f8381526020019081526020015f206002015414155b156111f3576111da826008600a612a5a565b600c5f8381526020019081526020015f20600201819055505b50808060010191505061114d565b506001600960146101000a81548160ff0219169083151502179055507f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c6103e8611249612a49565b604051611257929190614588565b60405180910390a1565b61127b83838360405180602001604052805f815250611db3565b505050565b61128b816001612abf565b50565b600c602052805f5260405f205f91509050805f015f9054906101000a900460ff16908060010154908060020154908060030180546112cb90614429565b80601f01602080910402602001604051908101604052809291908181526020018280546112f790614429565b80156113425780601f1061131957610100808354040283529160200191611342565b820191905f5260205f20905b81548152906001019060200180831161132557829003601f168201915b505050505090806004016040518060e00160405290815f82015f9054906101000a900460ff161515151581526020015f820160019054906101000a900460ff161515151581526020015f820160029054906101000a900460ff161515151581526020016001820180546113b490614429565b80601f01602080910402602001604051908101604052809291908181526020018280546113e090614429565b801561142b5780601f106114025761010080835404028352916020019161142b565b820191905f5260205f20905b81548152906001019060200180831161140e57829003601f168201915b505050505081526020016002820154815260200160038201548152602001600482015481525050905085565b600d602052805f5260405f205f915054906101000a900460ff1681565b60605f8383905090505f8167ffffffffffffffff81111561149857611497613ef2565b5b6040519080825280602002602001820160405280156114d157816020015b6114be613681565b8152602001906001900390816114b65790505b5090505f5b828114611528576114ff8686838181106114f3576114f26145af565b5b905060200201356122d9565b828281518110611512576115116145af565b5b60200260200101819052508060010190506114d6565b50809250505092915050565b5f61153e826126e1565b9050919050565b600e602052805f5260405f205f915054906101000a900460ff1681565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036115c8576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054169050919050565b61161f6129c2565b6116285f612cfb565b565b60605f805f61163885611562565b90505f8167ffffffffffffffff81111561165557611654613ef2565b5b6040519080825280602002602001820160405280156116835781602001602082028036833780820191505090505b50905061168e613681565b5f6116976126d9565b90505b838614611758576116aa81612dbe565b9150816040015161174d575f73ffffffffffffffffffffffffffffffffffffffff16825f015173ffffffffffffffffffffffffffffffffffffffff16146116f257815f015194505b8773ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361174c578083878060010198508151811061173f5761173e6145af565b5b6020026020010181815250505b5b80600101905061169a565b508195505050505050919050565b600b5481565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600380546117a390614429565b80601f01602080910402602001604051908101604052809291908181526020018280546117cf90614429565b801561181a5780601f106117f15761010080835404028352916020019161181a565b820191905f5260205f20905b8154815290600101906020018083116117fd57829003601f168201915b5050505050905090565b606081831061185f576040517f32c1995a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80611869612de7565b90506118736126d9565b851015611885576118826126d9565b94505b80841115611891578093505b5f61189b87611562565b9050848610156118bd575f8686039050818110156118b7578091505b506118c1565b5f90505b5f8167ffffffffffffffff8111156118dc576118db613ef2565b5b60405190808252806020026020018201604052801561190a5781602001602082028036833780820191505090505b5090505f82036119205780945050505050611a1c565b5f61192a886122d9565b90505f816040015161193d57815f015190505b5f8990505b8881141580156119525750848714155b15611a0e5761196081612dbe565b92508260400151611a03575f73ffffffffffffffffffffffffffffffffffffffff16835f015173ffffffffffffffffffffffffffffffffffffffff16146119a857825f015191505b8a73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611a0257808488806001019950815181106119f5576119f46145af565b5b6020026020010181815250505b5b806001019050611942565b508583528296505050505050505b9392505050565b5f611a2c6124ec565b90506611c37937e0800082611a4191906145dc565b341015611a7a576040517ff14a42b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028103611bab57600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1680611b6157505f73f9f27aa7718dccf4b4306e0321c2ce85215fa90273ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b8152600401611b2091906138d7565b602060405180830381865afa158015611b3b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b5f9190614631565b115b15611b7457611b6f826128c1565b611ba6565b6040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611bf4565b60038103611bc157611bbc826128c1565b611bf3565b6040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b5050565b8060075f611c046126d2565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611cad6126d2565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611cf29190613777565b60405180910390a35050565b606060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663489320a4600c5f8581526020019081526020015f206040518263ffffffff1660e01b8152600401611d6a91906148f4565b5f60405180830381865afa158015611d84573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611dac9190614982565b9050919050565b611dbe848484610b5b565b5f8373ffffffffffffffffffffffffffffffffffffffff163b14611e1f57611de884848484612def565b611e1e576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b5f84845f818110611e3957611e386145af565b5b905060200201359050611e4d858533612f3a565b611e83576040517f97792c3200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185859050036120c1576007600c5f8381526020019081526020015f2060020154118015611ec65750600b600c5f8381526020019081526020015f2060020154105b1561201657611edd83606001518460c00151612fc2565b611f13576040517f7a2a029c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6064611f1e8361306b565b1115611f56576040517f69ed1ea500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260600151600c5f8381526020019081526020015f206004016001019081611f7e9190614b54565b508260c00151600c5f8381526020019081526020015f206004016004018190555081600c5f8381526020019081526020015f206003019081611fc09190614b54565b50600c5f8281526020019081526020015f205f015f9054906101000a900460ff16612011576001600c5f8381526020019081526020015f205f015f6101000a81548160ff0219169083151502179055505b612085565b6103e88111806120425750600c5f8281526020019081526020015f205f015f9054906101000a900460ff165b15612079576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120848184846130d5565b5b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7816040516120b49190613967565b60405180910390a16122bb565b6005858590500361228857600c5f8281526020019081526020015f205f015f9054906101000a900460ff1615612123576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b600581101561228257612164600c5f888885818110612147576121466145af565b5b9050602002013581526020019081526020015f2060020154613369565b1561219b576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818686838181106121af576121ae6145af565b5b9050602002013503612202576121c68285856130d5565b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7826040516121f59190613967565b60405180910390a1612275565b612224868683818110612218576122176145af565b5b90506020020135611280565b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7868683818110612258576122576145af565b5b9050602002013560405161226c9190613967565b60405180910390a15b8080600101915050612125565b506122ba565b6040517f524f409b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b600b5f8154809291906122cd90614c23565b91905055505050505050565b6122e1613681565b6122e9613681565b6122f16126d9565b8310806123055750612301612de7565b8310155b15612313578091505061233e565b61231c83612dbe565b9050806040015115612331578091505061233e565b61233a836133a1565b9150505b919050565b606060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a3915e6583600c5f8681526020019081526020015f206040518363ffffffff1660e01b81526004016123b1929190614c6a565b5f60405180830381865afa1580156123cb573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906123f39190614982565b9050919050565b6124026129c2565b5f61240b6124ec565b1115612443576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b828290508110156124d9576001600e5f858585818110612468576124676145af565b5b905060200201602081019061247d9190613d43565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508080600101915050612445565b505050565b5f6124e76133c1565b905090565b5f6365ae74e0421015612501575f905061255d565b612a306365ae74e06125139190614555565b421015612523576001905061255d565b6162706365ae74e06125359190614555565b421015612545576002905061255d565b600a54421015612558576003905061255d565b600490505b90565b600a5481565b5f60075f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6125fc6129c2565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361266c575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161266391906138d7565b60405180910390fd5b61267581612cfb565b50565b5f816126826126d9565b1115801561269057505f5482105b80156126cb57505f7c010000000000000000000000000000000000000000000000000000000060045f8581526020019081526020015f205416145b9050919050565b5f33905090565b5f6001905090565b5f80829050806126ef6126d9565b1161276d575f5481101561276c575f60045f8381526020019081526020015f205490505f7c010000000000000000000000000000000000000000000000000000000082160361276a575b5f81036127605760045f836001900393508381526020019081526020015f20549050612739565b809250505061279f565b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b5f805f60065f8581526020019081526020015f2090508092508254915050915091565b5f73ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b612816848484846133ca565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612864576007600c5f8481526020019081526020015f20600201819055505b50505050565b5f8060e883901c905060e86128808686846133d0565b62ffffff16901b9150509392505050565b5f73ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b5f5b8181101561294c575f816128d5612de7565b6128df9190614555565b90506103e88111156129145761290f8161290742846128fe9190614555565b60016006612a5a565b60ff166133d8565b61293e565b6103e88103612933576203f4804261292c9190614555565b600a819055505b61293d815f6133d8565b5b5080806001019150506128c3565b50600a81116129645761295f338261340e565b6129bf565b5f5b600a8261297391906144f2565b8110156129925761298533600a61340e565b8080600101915050612966565b505f600a826129a19190614c98565b11156129be576129bd33600a836129b89190614c98565b61340e565b5b5b50565b6129ca6135b7565b73ffffffffffffffffffffffffffffffffffffffff166129e861176c565b73ffffffffffffffffffffffffffffffffffffffff1614612a4757612a0b6135b7565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401612a3e91906138d7565b60405180910390fd5b565b5f612a526126d9565b5f5403905090565b5f8060018484612a6a9190614522565b612a749190614555565b90508085604051602001612a889190614ce8565b604051602081830303815290604052805190602001205f1c612aaa9190614c98565b84612ab59190614555565b9150509392505050565b5f612ac9836126e1565b90505f8190505f80612ada866127a4565b915091508415612b4357612af68184612af16126d2565b6127c7565b612b4257612b0b83612b066126d2565b612566565b612b41576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b5b612b50835f88600161280a565b8015612b5a575f82555b600160806001901b0360055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282540192505081905550612bfe83612bbb855f8861286a565b7c02000000000000000000000000000000000000000000000000000000007c01000000000000000000000000000000000000000000000000000000001717612891565b60045f8881526020019081526020015f20819055505f7c0200000000000000000000000000000000000000000000000000000000851603612c7a575f6001870190505f60045f8381526020019081526020015f205403612c78575f548114612c77578460045f8381526020019081526020015f20819055505b5b505b855f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612ce2835f8860016128bb565b60015f8154809291906001019190505550505050505050565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612dc6613681565b612de060045f8481526020019081526020015f20546135be565b9050919050565b5f8054905090565b5f8373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612e146126d2565b8786866040518563ffffffff1660e01b8152600401612e369493929190614d54565b6020604051808303815f875af1925050508015612e7157506040513d601f19601f82011682018060405250810190612e6e9190614db2565b60015b612ee7573d805f8114612e9f576040519150601f19603f3d011682016040523d82523d5f602084013e612ea4565b606091505b505f815103612edf576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b5f805f90505b84849050811015612fb5578273ffffffffffffffffffffffffffffffffffffffff16612f84868684818110612f7857612f776145af565b5b90506020020135611534565b73ffffffffffffffffffffffffffffffffffffffff1614612fa8575f915050612fbb565b8080600101915050612f40565b50600190505b9392505050565b5f6006821080612fd25750601d82115b15612fdf575f9050613065565b5f612fe98461306b565b90505f60078211612ffd57601d905061305c565b6010821161300e57600b905061305b565b6016821161301f576009905061305a565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161305190614e27565b60405180910390fd5b5b5b80841115925050505b92915050565b5f805f90505f5b83518110156130cb57608060c0858381518110613092576130916145af565b5b602001015160f81c60f81b60f81c1660ff16146130b85781806130b490614c23565b9250505b80806130c390614c23565b915050613072565b8192505050919050565b600f82608001511115613114576040517f02e14b0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60078260a001511115613153576040517f3d36cb8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61316582606001518360c00151612fc2565b61319b576040517f7a2a029c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60646131a68261306b565b11156131de576040517f69ed1ea500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600c5f8581526020019081526020015f2060030190816131ff9190614b54565b506040518060e00160405280835f01511515815260200183602001511515815260200183604001511515815260200183606001518152602001836080015181526020018360a0015181526020018360c00151815250600c5f8581526020019081526020015f206004015f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff02191690831515021790555060608201518160010190816132d89190614b54565b506080820151816002015560a0820151816003015560c08201518160040155905050600c5f8481526020019081526020015f205f015f9054906101000a900460ff16613364576001600c5f8581526020019081526020015f205f015f6101000a81548160ff021916908315150217905550600b600c5f8581526020019081526020015f20600201819055505b505050565b5f80820361337a576001905061339c565b60078211801561338a5750600b82105b15613398576001905061339c565b5f90505b919050565b6133a9613681565b6133ba6133b5836126e1565b6135be565b9050919050565b5f600154905090565b50505050565b5f9392505050565b80600c5f8481526020019081526020015f206001018190555080600c5f8481526020019081526020015f20600201819055505050565b5f805490505f820361344c576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6134585f84838561280a565b600160406001901b17820260055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055506134ca836134bb5f865f61286a565b6134c485613672565b17612891565b60045f8381526020019081526020015f20819055505f80838301905073ffffffffffffffffffffffffffffffffffffffff8516915082825f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4600183015b8181146135645780835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a460018101905061352b565b505f820361359e576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f8190555050506135b25f8483856128bb565b505050565b5f33905090565b6135c6613681565b81815f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060a082901c816020019067ffffffffffffffff16908167ffffffffffffffff16815250505f7c01000000000000000000000000000000000000000000000000000000008316141581604001901515908115158152505060e882901c816060019062ffffff16908162ffffff1681525050919050565b5f6001821460e11b9050919050565b60405180608001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f67ffffffffffffffff1681526020015f151581526020015f62ffffff1681525090565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613711816136dd565b811461371b575f80fd5b50565b5f8135905061372c81613708565b92915050565b5f60208284031215613747576137466136d5565b5b5f6137548482850161371e565b91505092915050565b5f8115159050919050565b6137718161375d565b82525050565b5f60208201905061378a5f830184613768565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156137c75780820151818401526020810190506137ac565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6137ec82613790565b6137f6818561379a565b93506138068185602086016137aa565b61380f816137d2565b840191505092915050565b5f6020820190508181035f83015261383281846137e2565b905092915050565b5f819050919050565b61384c8161383a565b8114613856575f80fd5b50565b5f8135905061386781613843565b92915050565b5f60208284031215613882576138816136d5565b5b5f61388f84828501613859565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6138c182613898565b9050919050565b6138d1816138b7565b82525050565b5f6020820190506138ea5f8301846138c8565b92915050565b6138f9816138b7565b8114613903575f80fd5b50565b5f81359050613914816138f0565b92915050565b5f80604083850312156139305761392f6136d5565b5b5f61393d85828601613906565b925050602061394e85828601613859565b9150509250929050565b6139618161383a565b82525050565b5f60208201905061397a5f830184613958565b92915050565b5f805f60608486031215613997576139966136d5565b5b5f6139a486828701613906565b93505060206139b586828701613906565b92505060406139c686828701613859565b9150509250925092565b6139d98161375d565b82525050565b5f82825260208201905092915050565b5f6139f982613790565b613a0381856139df565b9350613a138185602086016137aa565b613a1c816137d2565b840191505092915050565b613a308161383a565b82525050565b5f60e083015f830151613a4b5f8601826139d0565b506020830151613a5e60208601826139d0565b506040830151613a7160408601826139d0565b5060608301518482036060860152613a8982826139ef565b9150506080830151613a9e6080860182613a27565b5060a0830151613ab160a0860182613a27565b5060c0830151613ac460c0860182613a27565b508091505092915050565b5f60a082019050613ae25f830188613768565b613aef6020830187613958565b613afc6040830186613958565b8181036060830152613b0e81856137e2565b90508181036080830152613b228184613a36565b90509695505050505050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f840112613b4f57613b4e613b2e565b5b8235905067ffffffffffffffff811115613b6c57613b6b613b32565b5b602083019150836020820283011115613b8857613b87613b36565b5b9250929050565b5f8060208385031215613ba557613ba46136d5565b5b5f83013567ffffffffffffffff811115613bc257613bc16136d9565b5b613bce85828601613b3a565b92509250509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b613c0c816138b7565b82525050565b5f67ffffffffffffffff82169050919050565b613c2e81613c12565b82525050565b5f62ffffff82169050919050565b613c4b81613c34565b82525050565b608082015f820151613c655f850182613c03565b506020820151613c786020850182613c25565b506040820151613c8b60408501826139d0565b506060820151613c9e6060850182613c42565b50505050565b5f613caf8383613c51565b60808301905092915050565b5f602082019050919050565b5f613cd182613bda565b613cdb8185613be4565b9350613ce683613bf4565b805f5b83811015613d16578151613cfd8882613ca4565b9750613d0883613cbb565b925050600181019050613ce9565b5085935050505092915050565b5f6020820190508181035f830152613d3b8184613cc7565b905092915050565b5f60208284031215613d5857613d576136d5565b5b5f613d6584828501613906565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f613da28383613a27565b60208301905092915050565b5f602082019050919050565b5f613dc482613d6e565b613dce8185613d78565b9350613dd983613d88565b805f5b83811015613e09578151613df08882613d97565b9750613dfb83613dae565b925050600181019050613ddc565b5085935050505092915050565b5f6020820190508181035f830152613e2e8184613dba565b905092915050565b5f805f60608486031215613e4d57613e4c6136d5565b5b5f613e5a86828701613906565b9350506020613e6b86828701613859565b9250506040613e7c86828701613859565b9150509250925092565b613e8f8161375d565b8114613e99575f80fd5b50565b5f81359050613eaa81613e86565b92915050565b5f8060408385031215613ec657613ec56136d5565b5b5f613ed385828601613906565b9250506020613ee485828601613e9c565b9150509250929050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b613f28826137d2565b810181811067ffffffffffffffff82111715613f4757613f46613ef2565b5b80604052505050565b5f613f596136cc565b9050613f658282613f1f565b919050565b5f67ffffffffffffffff821115613f8457613f83613ef2565b5b613f8d826137d2565b9050602081019050919050565b828183375f83830152505050565b5f613fba613fb584613f6a565b613f50565b905082815260208101848484011115613fd657613fd5613eee565b5b613fe1848285613f9a565b509392505050565b5f82601f830112613ffd57613ffc613b2e565b5b813561400d848260208601613fa8565b91505092915050565b5f805f806080858703121561402e5761402d6136d5565b5b5f61403b87828801613906565b945050602061404c87828801613906565b935050604061405d87828801613859565b925050606085013567ffffffffffffffff81111561407e5761407d6136d9565b5b61408a87828801613fe9565b91505092959194509250565b5f80fd5b5f80fd5b5f67ffffffffffffffff8211156140b8576140b7613ef2565b5b6140c1826137d2565b9050602081019050919050565b5f6140e06140db8461409e565b613f50565b9050828152602081018484840111156140fc576140fb613eee565b5b614107848285613f9a565b509392505050565b5f82601f83011261412357614122613b2e565b5b81356141338482602086016140ce565b91505092915050565b5f60e0828403121561415157614150614096565b5b61415b60e0613f50565b90505f61416a84828501613e9c565b5f83015250602061417d84828501613e9c565b602083015250604061419184828501613e9c565b604083015250606082013567ffffffffffffffff8111156141b5576141b461409a565b5b6141c18482850161410f565b60608301525060806141d584828501613859565b60808301525060a06141e984828501613859565b60a08301525060c06141fd84828501613859565b60c08301525092915050565b5f805f8060608587031215614221576142206136d5565b5b5f85013567ffffffffffffffff81111561423e5761423d6136d9565b5b61424a87828801613b3a565b9450945050602085013567ffffffffffffffff81111561426d5761426c6136d9565b5b6142798782880161413c565b925050604085013567ffffffffffffffff81111561429a576142996136d9565b5b6142a68782880161410f565b91505092959194509250565b608082015f8201516142c65f850182613c03565b5060208201516142d96020850182613c25565b5060408201516142ec60408501826139d0565b5060608201516142ff6060850182613c42565b50505050565b5f6080820190506143185f8301846142b2565b92915050565b5f8083601f84011261433357614332613b2e565b5b8235905067ffffffffffffffff8111156143505761434f613b32565b5b60208301915083602082028301111561436c5761436b613b36565b5b9250929050565b5f8060208385031215614389576143886136d5565b5b5f83013567ffffffffffffffff8111156143a6576143a56136d9565b5b6143b28582860161431e565b92509250509250929050565b5f80604083850312156143d4576143d36136d5565b5b5f6143e185828601613906565b92505060206143f285828601613906565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061444057607f821691505b602082108103614453576144526143fc565b5b50919050565b5f81519050614467816138f0565b92915050565b5f60208284031215614482576144816136d5565b5b5f61448f84828501614459565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6144fc8261383a565b91506145078361383a565b92508261451757614516614498565b5b828204905092915050565b5f61452c8261383a565b91506145378361383a565b925082820390508181111561454f5761454e6144c5565b5b92915050565b5f61455f8261383a565b915061456a8361383a565b9250828201905080821115614582576145816144c5565b5b92915050565b5f60408201905061459b5f830185613958565b6145a86020830184613958565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6145e68261383a565b91506145f18361383a565b92508282026145ff8161383a565b91508282048414831517614616576146156144c5565b5b5092915050565b5f8151905061462b81613843565b92915050565b5f60208284031215614646576146456136d5565b5b5f6146538482850161461d565b91505092915050565b5f815f1c9050919050565b5f60ff82169050919050565b5f6146856146808361465c565b614667565b9050919050565b5f819050919050565b5f6146a76146a28361465c565b61468c565b9050919050565b5f819050815f5260205f209050919050565b5f81546146cc81614429565b6146d681866139df565b9450600182165f81146146f0576001811461470657614738565b60ff198316865281151560200286019350614738565b61470f856146ae565b5f5b8381101561473057815481890152600182019150602081019050614711565b808801955050505b50505092915050565b5f8160081c9050919050565b5f61475f61475a83614741565b614667565b9050919050565b5f8160101c9050919050565b5f61478461477f83614766565b614667565b9050919050565b5f60e083015f8084015490506147a081614673565b6147ac5f8701826139d0565b506147b68161474d565b6147c360208701826139d0565b506147cd81614772565b6147da60408701826139d0565b506001840185830360608701526147f183826146c0565b9250506002840154905061480481614695565b6148116080870182613a27565b506003840154905061482281614695565b61482f60a0870182613a27565b506004840154905061484081614695565b61484d60c0870182613a27565b50819250505092915050565b5f60a083015f80840154905061486e81614673565b61487a5f8701826139d0565b506001840154905061488b81614695565b6148986020870182613a27565b50600284015490506148a981614695565b6148b66040870182613a27565b506003840185830360608701526148cd83826146c0565b9250506004840185830360808701526148e6838261478b565b925050819250505092915050565b5f6020820190508181035f83015261490c8184614859565b905092915050565b5f6149266149218461409e565b613f50565b90508281526020810184848401111561494257614941613eee565b5b61494d8482856137aa565b509392505050565b5f82601f83011261496957614968613b2e565b5b8151614979848260208601614914565b91505092915050565b5f60208284031215614997576149966136d5565b5b5f82015167ffffffffffffffff8111156149b4576149b36136d9565b5b6149c084828501614955565b91505092915050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302614a137fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826149d8565b614a1d86836149d8565b95508019841693508086168417925050509392505050565b5f819050919050565b5f614a58614a53614a4e8461383a565b614a35565b61383a565b9050919050565b5f819050919050565b614a7183614a3e565b614a85614a7d82614a5f565b8484546149e4565b825550505050565b5f90565b614a99614a8d565b614aa4818484614a68565b505050565b5b81811015614ac757614abc5f82614a91565b600181019050614aaa565b5050565b601f821115614b0c57614add816146ae565b614ae6846149c9565b81016020851015614af5578190505b614b09614b01856149c9565b830182614aa9565b50505b505050565b5f82821c905092915050565b5f614b2c5f1984600802614b11565b1980831691505092915050565b5f614b448383614b1d565b9150826002028217905092915050565b614b5d82613790565b67ffffffffffffffff811115614b7657614b75613ef2565b5b614b808254614429565b614b8b828285614acb565b5f60209050601f831160018114614bbc575f8415614baa578287015190505b614bb48582614b39565b865550614c1b565b601f198416614bca866146ae565b5f5b82811015614bf157848901518255600182019150602085019450602081019050614bcc565b86831015614c0e5784890151614c0a601f891682614b1d565b8355505b6001600288020188555050505b505050505050565b5f614c2d8261383a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614c5f57614c5e6144c5565b5b600182019050919050565b5f604082019050614c7d5f830185613958565b8181036020830152614c8f8184614859565b90509392505050565b5f614ca28261383a565b9150614cad8361383a565b925082614cbd57614cbc614498565b5b828206905092915050565b5f819050919050565b614ce2614cdd8261383a565b614cc8565b82525050565b5f614cf38284614cd1565b60208201915081905092915050565b5f81519050919050565b5f82825260208201905092915050565b5f614d2682614d02565b614d308185614d0c565b9350614d408185602086016137aa565b614d49816137d2565b840191505092915050565b5f608082019050614d675f8301876138c8565b614d7460208301866138c8565b614d816040830185613958565b8181036060830152614d938184614d1c565b905095945050505050565b5f81519050614dac81613708565b92915050565b5f60208284031215614dc757614dc66136d5565b5b5f614dd484828501614d9e565b91505092915050565b7f696e76616c6964206c656e6774680000000000000000000000000000000000005f82015250565b5f614e11600e8361379a565b9150614e1c82614ddd565b602082019050919050565b5f6020820190508181035f830152614e3e81614e05565b905091905056fea2646970667358221220372f96efb9bf8fd2c063fd42d3ae70e20116b2a331f1377a5970c58b7675af5064736f6c63430008170033608060405234801562000010575f80fd5b50620000216200002760201b60201c565b62002064565b60405180606001604052806040518060400160405280600581526020017f576869746500000000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f23464646454637000000000000000000000000000000000000000000000000008152508152602001600115158152505f808081526020019081526020015f205f820151815f019081620000d4919062001f80565b506020820151816001019081620000ec919062001f80565b506040820151816002015f6101000a81548160ff02191690831515021790555090505060405180606001604052806040518060400160405280600581526020017f576869746500000000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f234646464546370000000000000000000000000000000000000000000000000081525081526020015f15158152505f80600181526020019081526020015f205f820151815f019081620001bc919062001f80565b506020820151816001019081620001d4919062001f80565b506040820151816002015f6101000a81548160ff02191690831515021790555090505060405180606001604052806040518060400160405280600381526020017f526564000000000000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f23453630303230000000000000000000000000000000000000000000000000008152508152602001600115158152505f80600281526020019081526020015f205f820151815f019081620002a5919062001f80565b506020820151816001019081620002bd919062001f80565b506040820151816002015f6101000a81548160ff02191690831515021790555090505060405180606001604052806040518060400160405280600381526020017f526564000000000000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f234536303032300000000000000000000000000000000000000000000000000081525081526020015f15158152505f80600381526020019081526020015f205f820151815f0190816200038d919062001f80565b506020820151816001019081620003a5919062001f80565b506040820151816002015f6101000a81548160ff02191690831515021790555090505060405180606001604052806040518060400160405280600681526020017f59656c6c6f77000000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f23464641453030000000000000000000000000000000000000000000000000008152508152602001600115158152505f80600481526020019081526020015f205f820151815f01908162000476919062001f80565b5060208201518160010190816200048e919062001f80565b506040820151816002015f6101000a81548160ff02191690831515021790555090505060405180606001604052806040518060400160405280600681526020017f59656c6c6f77000000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f234646414530300000000000000000000000000000000000000000000000000081525081526020015f15158152505f80600581526020019081526020015f205f820151815f0190816200055e919062001f80565b50602082015181600101908162000576919062001f80565b506040820151816002015f6101000a81548160ff02191690831515021790555090505060405180606001604052806040518060400160405280600481526020017f477261790000000000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f23323532343235000000000000000000000000000000000000000000000000008152508152602001600115158152505f80600681526020019081526020015f205f820151815f01908162000647919062001f80565b5060208201518160010190816200065f919062001f80565b506040820151816002015f6101000a81548160ff02191690831515021790555090505060405180606001604052806040518060400160405280600481526020017f477261790000000000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f233235323432350000000000000000000000000000000000000000000000000081525081526020015f15158152505f80600781526020019081526020015f205f820151815f0190816200072f919062001f80565b50602082015181600101908162000747919062001f80565b506040820151816002015f6101000a81548160ff02191690831515021790555090505060405180604001604052806040518060400160405280600581526020017f4c61676f7300000000000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060b781526020016200619c60b7913981525060015f8081526020019081526020015f205f820151815f019081620007f3919062001f80565b5060208201518160010190816200080b919062001f80565b5090505060405180604001604052806040518060400160405280600981526020017f53616e205061756c6f000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060b781526020016200653260b7913981525060015f600181526020019081526020015f205f820151815f01908162000899919062001f80565b506020820151816001019081620008b1919062001f80565b5090505060405180604001604052806040518060400160405280600681526020017f426f676f7461000000000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060b7815260200162005d5260b7913981525060015f600281526020019081526020015f205f820151815f0190816200093f919062001f80565b50602082015181600101908162000957919062001f80565b5090505060405180604001604052806040518060400160405280600c81526020017f4a6f68616e6e657362757267000000000000000000000000000000000000000081525081526020016040518060e0016040528060b7815260200162005e0960b7913981525060015f600381526020019081526020015f205f820151815f019081620009e5919062001f80565b506020820151816001019081620009fd919062001f80565b5090505060405180604001604052806040518060400160405280600981526020017f56616e636f75766572000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060b481526020016200630d60b4913981525060015f600481526020019081526020015f205f820151815f01908162000a8b919062001f80565b50602082015181600101908162000aa3919062001f80565b5090505060405180604001604052806040518060400160405280600781526020017f4172697a6f6e610000000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060b48152602001620066a360b4913981525060015f600581526020019081526020015f205f820151815f01908162000b31919062001f80565b50602082015181600101908162000b49919062001f80565b5090505060405180604001604052806040518060400160405280600581526020017f4d69616d6900000000000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060b78152602001620063c160b7913981525060015f600681526020019081526020015f205f820151815f01908162000bd7919062001f80565b50602082015181600101908162000bef919062001f80565b5090505060405180604001604052806040518060400160405280600b81526020017f53616e20416e746f6e696f00000000000000000000000000000000000000000081525081526020016040518060e0016040528060ba8152602001620060e260ba913981525060015f600781526020019081526020015f205f820151815f01908162000c7d919062001f80565b50602082015181600101908162000c95919062001f80565b5090505060405180604001604052806040518060400160405280600881526020017f4e657720596f726b00000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060b481526020016200675760b4913981525060015f600881526020019081526020015f205f820151815f01908162000d23919062001f80565b50602082015181600101908162000d3b919062001f80565b5090505060405180604001604052806040518060400160405280600881526020017f4d6172796c616e6400000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060ba81526020016200647860ba913981525060015f600981526020019081526020015f205f820151815f01908162000dc9919062001f80565b50602082015181600101908162000de1919062001f80565b5090505060405180604001604052806040518060400160405280600981526020017f53696e6761706f7265000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060ba81526020016200625360ba913981525060015f600a81526020019081526020015f205f820151815f01908162000e6f919062001f80565b50602082015181600101908162000e87919062001f80565b5090505060405180604001604052806040518060400160405280600781526020017f57796f6d696e670000000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060b481526020016200602e60b4913981525060015f600b81526020019081526020015f205f820151815f01908162000f15919062001f80565b50602082015181600101908162000f2d919062001f80565b5090505060405180604001604052806040518060400160405280600481526020017f436c756a0000000000000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060ba815260200162005f7460ba913981525060015f600c81526020019081526020015f205f820151815f01908162000fbb919062001f80565b50602082015181600101908162000fd3919062001f80565b5090505060405180604001604052806040518060400160405280600781526020017f4368696361676f0000000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060b4815260200162005ec060b4913981525060015f600d81526020019081526020015f205f820151815f01908162001061919062001f80565b50602082015181600101908162001079919062001f80565b5090505060405180604001604052806040518060400160405280600881526020017f506f72746c616e6400000000000000000000000000000000000000000000000081525081526020016040518060e0016040528060ba8152602001620065e960ba913981525060015f600e81526020019081526020015f205f820151815f01908162001107919062001f80565b5060208201518160010190816200111f919062001f80565b5090505060405180604001604052806040518060400160405280600481526020017f4e6f6e6500000000000000000000000000000000000000000000000000000000815250815260200160405180602001604052805f81525081525060015f600f81526020019081526020015f205f820151815f019081620011a2919062001f80565b506020820151816001019081620011ba919062001f80565b509050506040518060e001604052805f151581526020015f151581526020015f1515815260200160405180602001604052805f81525081526020015f81526020015f8152602001600981525060025f8081526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff021916908315150217905550606082015181600101908162001289919062001f80565b506080820151816002015560a0820151816003015560c082015181600401559050506040518060e001604052805f151581526020015f151581526020015f151581526020016040518060400160405280600f81526020017f4a756c7920313174682c203230323200000000000000000000000000000000008152508152602001600581526020015f8152602001600b81525060025f600181526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff02191690831515021790555060608201518160010190816200139f919062001f80565b506080820151816002015560a0820151816003015560c082015181600401559050506040518060e001604052805f151581526020016001151581526020015f151581526020016040518060400160405280601481526020017f5041494e204245464f52452050524f47524553530000000000000000000000008152508152602001600481526020015f8152602001600981525060025f600281526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff0219169083151502179055506060820151816001019081620014b6919062001f80565b506080820151816002015560a0820151816003015560c082015181600401559050506040518060e001604052805f151581526020015f151581526020015f151581526020016040518060400160405280601281526020017f4e6f76656d626572203674682c203139393000000000000000000000000000008152508152602001600981526020015f8152602001600981525060025f600381526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff0219169083151502179055506060820151816001019081620015cc919062001f80565b506080820151816002015560a0820151816003015560c082015181600401559050506040518060e001604052805f151581526020015f151581526020015f151581526020016040518060400160405280601281526020017f4f63746f62657220333173742c203230303800000000000000000000000000008152508152602001600e81526020015f8152602001600981525060025f600481526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff0219169083151502179055506060820151816001019081620016e2919062001f80565b506080820151816002015560a0820151816003015560c082015181600401559050506040518060e001604052805f151581526020016001151581526020015f151581526020016040518060400160405280601681526020017f544845204d41524154484f4e20434f4e54494e554553000000000000000000008152508152602001600881526020015f8152602001600981525060025f600581526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff0219169083151502179055506060820151816001019081620017f9919062001f80565b506080820151816002015560a0820151816003015560c082015181600401559050506040518060e001604052806001151581526020016001151581526020015f151581526020016040518060400160405280600f81526020017f4d414d4241204d454e54414c49545900000000000000000000000000000000008152508152602001600381526020015f8152602001600981525060025f600681526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff021916908315150217905550606082015181600101908162001911919062001f80565b506080820151816002015560a0820151816003015560c082015181600401559050506040518060e001604052805f151581526020015f151581526020016001151581526020016040518060400160405280600f81526020017f2a4e4f5420464f5220524553414c4500000000000000000000000000000000008152508152602001600f815260200160028152602001600e81525060025f600781526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff021916908315150217905550606082015181600101908162001a29919062001f80565b506080820151816002015560a0820151816003015560c082015181600401559050506040518060e001604052805f151581526020016001151581526020015f1515815260200160405180602001604052805f8152508152602001600881526020015f8152602001600981525060025f600881526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff021916908315150217905550606082015181600101908162001b19919062001f80565b506080820151816002015560a0820151816003015560c082015181600401559050506040518060e001604052805f151581526020015f151581526020015f1515815260200160405180602001604052805f8152508152602001600181526020015f8152602001600981525060025f600981526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff021916908315150217905550606082015181600101908162001c08919062001f80565b506080820151816002015560a0820151816003015560c082015181600401559050506040518060e001604052805f151581526020015f151581526020015f1515815260200160405180602001604052805f8152508152602001600d815260200160028152602001600981525060025f600a81526020019081526020015f205f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff021916908315150217905550606082015181600101908162001cf8919062001f80565b506080820151816002015560a0820151816003015560c08201518160040155905050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168062001d9857607f821691505b60208210810362001dae5762001dad62001d53565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830262001e127fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262001dd5565b62001e1e868362001dd5565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f62001e6862001e6262001e5c8462001e36565b62001e3f565b62001e36565b9050919050565b5f819050919050565b62001e838362001e48565b62001e9b62001e928262001e6f565b84845462001de1565b825550505050565b5f90565b62001eb162001ea3565b62001ebe81848462001e78565b505050565b5b8181101562001ee55762001ed95f8262001ea7565b60018101905062001ec4565b5050565b601f82111562001f345762001efe8162001db4565b62001f098462001dc6565b8101602085101562001f19578190505b62001f3162001f288562001dc6565b83018262001ec3565b50505b505050565b5f82821c905092915050565b5f62001f565f198460080262001f39565b1980831691505092915050565b5f62001f70838362001f45565b9150826002028217905092915050565b62001f8b8262001d1c565b67ffffffffffffffff81111562001fa75762001fa662001d26565b5b62001fb3825462001d80565b62001fc082828562001ee9565b5f60209050601f83116001811462001ff6575f841562001fe1578287015190505b62001fed858262001f63565b8655506200205c565b601f198416620020068662001db4565b5f5b828110156200202f5784890151825560018201915060208501945060208101905062002008565b868310156200204f57848901516200204b601f89168262001f45565b8355505b6001600288020188555050505b505050505050565b613ce080620020725f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c8063489320a414610038578063a3915e6514610068575b5f80fd5b610052600480360381019061004d9190612355565b610098565b60405161005f9190612416565b60405180910390f35b610082600480360381019061007d9190612436565b6103dc565b60405161008f9190612416565b60405180910390f35b60605f6040518060400160405280600481526020017f2346464600000000000000000000000000000000000000000000000000000000815250905060605f6100df85610417565b90505f856040015190506007811180156100f95750600b81105b156101cc5760088103610143576040518060400160405280600781526020017f234636383731460000000000000000000000000000000000000000000000000081525093506101cb565b60098103610188576040518060400160405280600781526020017f233030413635310000000000000000000000000000000000000000000000000081525093506101ca565b600a81036101c9576040518060400160405280600781526020017f233030344537430000000000000000000000000000000000000000000000000081525093505b5b5b5b6007811461021e5781602001516101fe576040518061046001604052806104268152602001613885610426913961021b565b60405180610480016040528061045381526020016133f261045391395b92505b835f808460a0015181526020019081526020015f206002015f9054906101000a900460ff1661025b5760405180602001604052805f815250610292565b6040518060400160405280600781526020017f72783d22323122000000000000000000000000000000000000000000000000008152505b61029f8460c00151610903565b6102ac8560600151610a81565b865f808860a0015181526020019081526020015f206001018760400151610308576040518060400160405280600481526020017f233030300000000000000000000000000000000000000000000000000000000081525061033f565b6040518060400160405280600481526020017f23464646000000000000000000000000000000000000000000000000000000008152505b885f015161035b5760405180602001604052805f815250610392565b6040518060400160405280600e81526020017f7374726f6b653a233233314632300000000000000000000000000000000000008152505b60015f8b6080015181526020019081526020015f206001016040516020016103c299989796959493929190612bbe565b604051602081830303815290604052945050505050919050565b60606103f06103eb84846115a0565b6115ee565b6040516020016104009190612cf4565b604051602081830303815290604052905092915050565b61041f611fcd565b5f826040015190506007810361054e5760025f600781526020019081526020015f206040518060e00160405290815f82015f9054906101000a900460ff161515151581526020015f820160019054906101000a900460ff161515151581526020015f820160029054906101000a900460ff161515151581526020016001820180546104a9906129d4565b80601f01602080910402602001604051908101604052809291908181526020018280546104d5906129d4565b80156105205780601f106104f757610100808354040283529160200191610520565b820191905f5260205f20905b81548152906001019060200180831161050357829003601f168201915b50505050508152602001600282015481526020016003820154815260200160048201548152505091506108fd565b60078111801561055e5750600b81105b156107cc57825f0151156106ad5760025f8281526020019081526020015f206040518060e00160405290815f82015f9054906101000a900460ff161515151581526020015f820160019054906101000a900460ff161515151581526020015f820160029054906101000a900460ff161515151581526020016001820180546105e5906129d4565b80601f0160208091040260200160405190810160405280929190818152602001828054610611906129d4565b801561065c5780601f106106335761010080835404028352916020019161065c565b820191905f5260205f20905b81548152906001019060200180831161063f57829003601f168201915b50505050508152602001600282015481526020016003820154815260200160048201548152505091508260800151606001518260600181905250826080015160c001518260c00181815250506107c7565b60025f8281526020019081526020015f206040518060e00160405290815f82015f9054906101000a900460ff161515151581526020015f820160019054906101000a900460ff161515151581526020015f820160029054906101000a900460ff16151515158152602001600182018054610726906129d4565b80601f0160208091040260200160405190810160405280929190818152602001828054610752906129d4565b801561079d5780601f106107745761010080835404028352916020019161079d565b820191905f5260205f20905b81548152906001019060200180831161078057829003601f168201915b50505050508152602001600282015481526020016003820154815260200160048201548152505091505b6108fc565b825f0151156107e157826080015191506108fb565b60025f8281526020019081526020015f206040518060e00160405290815f82015f9054906101000a900460ff161515151581526020015f820160019054906101000a900460ff161515151581526020015f820160029054906101000a900460ff1615151515815260200160018201805461085a906129d4565b80601f0160208091040260200160405190810160405280929190818152602001828054610886906129d4565b80156108d15780601f106108a8576101008083540402835291602001916108d1565b820191905f5260205f20905b8154815290600101906020018083116108b457829003601f168201915b50505050508152602001600282015481526020016003820154815260200160048201548152505091505b5b5b50919050565b60605f8203610949576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050610a7c565b5f8290505f5b5f821461097857808061096190612d42565b915050600a826109719190612db6565b915061094f565b5f8167ffffffffffffffff8111156109935761099261202f565b5b6040519080825280601f01601f1916602001820160405280156109c55781602001600182028036833780820191505090505b5090505f8290505b5f8614610a74576001816109e19190612de6565b90505f600a80886109f29190612db6565b6109fc9190612e19565b87610a079190612de6565b6030610a139190612e66565b90505f8160f81b905080848481518110610a3057610a2f612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a88610a6b9190612db6565b975050506109cd565b819450505050505b919050565b60605f8290505f60058251610a969190612e19565b67ffffffffffffffff811115610aaf57610aae61202f565b5b6040519080825280601f01601f191660200182016040528015610ae15781602001600182028036833780820191505090505b5090505f805b83518110156114cc577f2600000000000000000000000000000000000000000000000000000000000000848281518110610b2457610b23612e9a565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610e7b576040518060400160405280600181526020017f26000000000000000000000000000000000000000000000000000000000000008152505f81518110610b9e57610b9d612e9a565b5b602001015160f81c60f81b838380610bb590612d42565b945081518110610bc857610bc7612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506040518060400160405280600181526020017f61000000000000000000000000000000000000000000000000000000000000008152505f81518110610c3e57610c3d612e9a565b5b602001015160f81c60f81b838380610c5590612d42565b945081518110610c6857610c67612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506040518060400160405280600181526020017f6d000000000000000000000000000000000000000000000000000000000000008152505f81518110610cde57610cdd612e9a565b5b602001015160f81c60f81b838380610cf590612d42565b945081518110610d0857610d07612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506040518060400160405280600181526020017f70000000000000000000000000000000000000000000000000000000000000008152505f81518110610d7e57610d7d612e9a565b5b602001015160f81c60f81b838380610d9590612d42565b945081518110610da857610da7612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506040518060400160405280600181526020017f3b000000000000000000000000000000000000000000000000000000000000008152505f81518110610e1e57610e1d612e9a565b5b602001015160f81c60f81b838380610e3590612d42565b945081518110610e4857610e47612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506114bf565b7f3c00000000000000000000000000000000000000000000000000000000000000848281518110610eaf57610eae612e9a565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603611166576040518060400160405280600181526020017f26000000000000000000000000000000000000000000000000000000000000008152505f81518110610f2957610f28612e9a565b5b602001015160f81c60f81b838380610f4090612d42565b945081518110610f5357610f52612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506040518060400160405280600181526020017f6c000000000000000000000000000000000000000000000000000000000000008152505f81518110610fc957610fc8612e9a565b5b602001015160f81c60f81b838380610fe090612d42565b945081518110610ff357610ff2612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506040518060400160405280600181526020017f74000000000000000000000000000000000000000000000000000000000000008152505f8151811061106957611068612e9a565b5b602001015160f81c60f81b83838061108090612d42565b94508151811061109357611092612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506040518060400160405280600181526020017f3b000000000000000000000000000000000000000000000000000000000000008152505f8151811061110957611108612e9a565b5b602001015160f81c60f81b83838061112090612d42565b94508151811061113357611132612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506114be565b7f3e0000000000000000000000000000000000000000000000000000000000000084828151811061119a57611199612e9a565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603611451576040518060400160405280600181526020017f26000000000000000000000000000000000000000000000000000000000000008152505f8151811061121457611213612e9a565b5b602001015160f81c60f81b83838061122b90612d42565b94508151811061123e5761123d612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506040518060400160405280600181526020017f67000000000000000000000000000000000000000000000000000000000000008152505f815181106112b4576112b3612e9a565b5b602001015160f81c60f81b8383806112cb90612d42565b9450815181106112de576112dd612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506040518060400160405280600181526020017f74000000000000000000000000000000000000000000000000000000000000008152505f8151811061135457611353612e9a565b5b602001015160f81c60f81b83838061136b90612d42565b94508151811061137e5761137d612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506040518060400160405280600181526020017f3b000000000000000000000000000000000000000000000000000000000000008152505f815181106113f4576113f3612e9a565b5b602001015160f81c60f81b83838061140b90612d42565b94508151811061141e5761141d612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506114bd565b83818151811061146457611463612e9a565b5b602001015160f81c60f81b83838061147b90612d42565b94508151811061148e5761148d612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505b5b5b8080600101915050610ae7565b505f8167ffffffffffffffff8111156114e8576114e761202f565b5b6040519080825280601f01601f19166020018201604052801561151a5781602001600182028036833780820191505090505b5090505f5b828110156115935783818151811061153a57611539612e9a565b5b602001015160f81c60f81b82828151811061155857611557612e9a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350808060010191505061151f565b5080945050505050919050565b60606115ab83610903565b6115b48361174d565b6115c56115c085610098565b6115ee565b6040516020016115d7939291906130cb565b604051602081830303815290604052905092915050565b60605f82510361160e5760405180602001604052805f8152509050611748565b5f6040518060600160405280604081526020016138456040913990505f60036002855161163b9190613127565b6116459190612db6565b60046116519190612e19565b67ffffffffffffffff81111561166a5761166961202f565b5b6040519080825280601f01601f19166020018201604052801561169c5781602001600182028036833780820191505090505b509050600182016020820185865187015b80821015611708576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453600184019350506116ad565b505060038651066001811461172457600281146117375761173f565b603d6001830353603d600283035361173f565b603d60018303535b50505080925050505b919050565b60606007826040015114611eb3575f61176583610417565b90506117dd6040518060400160405280600681526020017f4275726e656400000000000000000000000000000000000000000000000000008152506040518060400160405280600781526020017f2266616c736522000000000000000000000000000000000000000000000000008152506001611f4f565b6118976040518060400160405280600681526020017f4564697465640000000000000000000000000000000000000000000000000000815250855f0151611859576040518060400160405280600781526020017f2266616c73652200000000000000000000000000000000000000000000000000815250611890565b6040518060400160405280600681526020017f22747275652200000000000000000000000000000000000000000000000000008152505b6001611f4f565b61190e6040518060400160405280600881526020017f4f726967696e616c00000000000000000000000000000000000000000000000081525060025f886020015181526020019081526020015f206001016040516020016118f891906131a4565b6040516020818303038152906040526001611f4f565b6119dc6040518060400160405280600a81526020017f53757065722052617265000000000000000000000000000000000000000000008152506007886040015111801561195f5750600b8860400151105b61199e576040518060400160405280600781526020017f2266616c736522000000000000000000000000000000000000000000000000008152506119d5565b6040518060400160405280600681526020017f22747275652200000000000000000000000000000000000000000000000000008152505b6001611f4f565b611a966040518060400160405280600681526020017f5374726f6b650000000000000000000000000000000000000000000000000000815250865f0151611a58576040518060400160405280600781526020017f2266616c73652200000000000000000000000000000000000000000000000000815250611a8f565b6040518060400160405280600681526020017f22747275652200000000000000000000000000000000000000000000000000008152505b6001611f4f565b611b516040518060400160405280600781526020017f426172636f6465000000000000000000000000000000000000000000000000008152508760200151611b13576040518060400160405280600c81526020017f22486f72697a6f6e74616c220000000000000000000000000000000000000000815250611b4a565b6040518060400160405280600a81526020017f22566572746963616c22000000000000000000000000000000000000000000008152505b6001611f4f565b611c2b6040518060400160405280600b81526020017f4c6162656c205374796c650000000000000000000000000000000000000000008152505f808a60a0015181526020019081526020015f206002015f9054906101000a900460ff16611bed576040518060400160405280600881526020017f2253717561726522000000000000000000000000000000000000000000000000815250611c24565b6040518060400160405280600781526020017f22526f756e6422000000000000000000000000000000000000000000000000008152505b6001611f4f565b611ca16040518060400160405280600e81526020017f436f6c6f7220537065637472756d00000000000000000000000000000000000081525060015f8b6080015181526020019081526020015f205f01604051602001611c8b91906131a4565b6040516020818303038152906040526001611f4f565b611d166040518060400160405280600b81526020017f4c6162656c20436f6c6f720000000000000000000000000000000000000000008152505f808c60a0015181526020019081526020015f205f01604051602001611d0091906131a4565b6040516020818303038152906040526001611f4f565b611dd16040518060400160405280600a81526020017f5465787420436f6c6f72000000000000000000000000000000000000000000008152508b60400151611d93576040518060400160405280600781526020017f22426c61636b2200000000000000000000000000000000000000000000000000815250611dca565b6040518060400160405280600781526020017f22576869746522000000000000000000000000000000000000000000000000008152505b6001611f4f565b611e1e6040518060400160405280600981526020017f546578742053697a650000000000000000000000000000000000000000000000815250611e178d60c00151610903565b6001611f4f565b611e816040518060400160405280600881526020017f4d657461646174610000000000000000000000000000000000000000000000008152508f60600151604051602001611e6c91906131d0565b6040516020818303038152906040525f611f4f565b604051602001611e9c9c9b9a999897969594939291906131fc565b604051602081830303815290604052915050611f4a565b611f286040518060400160405280600681526020017f4275726e656400000000000000000000000000000000000000000000000000008152506040518060400160405280600681526020017f22747275652200000000000000000000000000000000000000000000000000008152505f611f4f565b604051602001611f3891906132a1565b60405160208183030381529060405290505b919050565b6060838383611f6c5760405180602001604052805f815250611fa3565b6040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152505b604051602001611fb593929190613395565b60405160208183030381529060405290509392505050565b6040518060e001604052805f151581526020015f151581526020015f15158152602001606081526020015f81526020015f81526020015f81525090565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6120658261201f565b810181811067ffffffffffffffff821117156120845761208361202f565b5b80604052505050565b5f61209661200a565b90506120a2828261205c565b919050565b5f80fd5b5f8115159050919050565b6120bf816120ab565b81146120c9575f80fd5b50565b5f813590506120da816120b6565b92915050565b5f819050919050565b6120f2816120e0565b81146120fc575f80fd5b50565b5f8135905061210d816120e9565b92915050565b5f80fd5b5f80fd5b5f67ffffffffffffffff8211156121355761213461202f565b5b61213e8261201f565b9050602081019050919050565b828183375f83830152505050565b5f61216b6121668461211b565b61208d565b90508281526020810184848401111561218757612186612117565b5b61219284828561214b565b509392505050565b5f82601f8301126121ae576121ad612113565b5b81356121be848260208601612159565b91505092915050565b5f60e082840312156121dc576121db61201b565b5b6121e660e061208d565b90505f6121f5848285016120cc565b5f830152506020612208848285016120cc565b602083015250604061221c848285016120cc565b604083015250606082013567ffffffffffffffff8111156122405761223f6120a7565b5b61224c8482850161219a565b6060830152506080612260848285016120ff565b60808301525060a0612274848285016120ff565b60a08301525060c0612288848285016120ff565b60c08301525092915050565b5f60a082840312156122a9576122a861201b565b5b6122b360a061208d565b90505f6122c2848285016120cc565b5f8301525060206122d5848285016120ff565b60208301525060406122e9848285016120ff565b604083015250606082013567ffffffffffffffff81111561230d5761230c6120a7565b5b6123198482850161219a565b606083015250608082013567ffffffffffffffff81111561233d5761233c6120a7565b5b612349848285016121c7565b60808301525092915050565b5f6020828403121561236a57612369612013565b5b5f82013567ffffffffffffffff81111561238757612386612017565b5b61239384828501612294565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156123d35780820151818401526020810190506123b8565b5f8484015250505050565b5f6123e88261239c565b6123f281856123a6565b93506124028185602086016123b6565b61240b8161201f565b840191505092915050565b5f6020820190508181035f83015261242e81846123de565b905092915050565b5f806040838503121561244c5761244b612013565b5b5f612459858286016120ff565b925050602083013567ffffffffffffffff81111561247a57612479612017565b5b61248685828601612294565b9150509250929050565b5f81905092915050565b7f3c7376672077696474683d2238303022206865696768743d22383030222076695f8201527f6577426f783d223020302032303220323032222066696c6c3d226e6f6e65222060208201527f786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f737660408201527f67223e3c726563742069643d2262672220783d22312220793d2231222072783d60608201527f2236222077696474683d2232303022206865696768743d22323030222066696c60808201527f6c3d22000000000000000000000000000000000000000000000000000000000060a082015250565b5f61258c60a383612490565b91506125978261249a565b60a382019050919050565b5f6125ac8261239c565b6125b68185612490565b93506125c68185602086016123b6565b80840191505092915050565b7f222f3e3c726563742069643d226c6162656c22200000000000000000000000005f82015250565b5f612606601483612490565b9150612611826125d2565b601482019050919050565b7f20783d2231392220793d223830222077696474683d22313634222068656967685f8201527f743d223432222066696c6c3d2223323132313231222f3e3c706174682069643d60208201527f2274657874706174682220643d224d3139203130314c31383320313031222f3e60408201527f3c746578742066696c6c3d22233233314632302220666f6e742d66616d696c7960608201527f3d2273797374656d2d75692220666f6e742d73697a653d220000000000000000608082015250565b5f6126e8609883612490565b91506126f38261261c565b609882019050919050565b7f2220666f6e742d7765696768743d22626f6c642220746578742d616e63686f725f8201527f3d226d6964646c6522206c65747465722d73706163696e673d2230656d22206460208201527f793d222e3336656d223e3c746578745061746820687265663d2223746578747060408201527f617468222073746172744f66667365743d22353025223e000000000000000000606082015250565b5f6127a4607783612490565b91506127af826126fe565b607782019050919050565b7f3c2f74657874506174683e3c2f746578743e3c636972636c652069643d2263365f8201527f222063783d22313839222063793d223138392220723d2235222f3e3c6369726360208201527f6c652069643d226335222063783d22313739222063793d223138392220723d2260408201527f35222f3e3c636972636c652069643d226334222063783d22313639222063793d60608201527f223138392220723d2235222f3e3c636972636c652069643d226333222063783d60808201527f22313539222063793d223138392220723d2235222f3e3c636972636c6520696460a08201527f3d226332222063783d22313439222063793d223138392220723d2235222f3e3c60c08201527f636972636c652069643d226331222063783d22313339222063793d223138392260e08201527f20723d2235222f3e3c672069643d22626172636f6465223e000000000000000061010082015250565b5f61292061011883612490565b915061292b826127ba565b61011882019050919050565b7f3c2f673e3c646566733e3c7374796c653e23626172636f646520706174687b665f8201527f696c6c3a233031303130317d236c6162656c7b66696c6c3a0000000000000000602082015250565b5f612991603883612490565b915061299c82612937565b603882019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806129eb57607f821691505b6020821081036129fe576129fd6129a7565b5b50919050565b5f819050815f5260205f209050919050565b5f8154612a22816129d4565b612a2c8186612490565b9450600182165f8114612a465760018114612a5b57612a8d565b60ff1983168652811515820286019350612a8d565b612a6485612a04565b5f5b83811015612a8557815481890152600182019150602081019050612a66565b838801955050505b50505092915050565b7f7d746578747b66696c6c3a0000000000000000000000000000000000000000005f82015250565b5f612aca600b83612490565b9150612ad582612a96565b600b82019050919050565b7f7d2362677b0000000000000000000000000000000000000000000000000000005f82015250565b5f612b14600583612490565b9150612b1f82612ae0565b600582019050919050565b7f7d000000000000000000000000000000000000000000000000000000000000005f82015250565b5f612b5e600183612490565b9150612b6982612b2a565b600182019050919050565b7f3c2f7374796c653e3c2f646566733e3c2f7376673e00000000000000000000005f82015250565b5f612ba8601583612490565b9150612bb382612b74565b601582019050919050565b5f612bc882612580565b9150612bd4828c6125a2565b9150612bdf826125fa565b9150612beb828b6125a2565b9150612bf6826126dc565b9150612c02828a6125a2565b9150612c0d82612798565b9150612c1982896125a2565b9150612c2482612913565b9150612c3082886125a2565b9150612c3b82612985565b9150612c478287612a16565b9150612c5282612abe565b9150612c5e82866125a2565b9150612c6982612b08565b9150612c7582856125a2565b9150612c8082612b52565b9150612c8c8284612a16565b9150612c9782612b9c565b91508190509a9950505050505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f612cde601d83612490565b9150612ce982612caa565b601d82019050919050565b5f612cfe82612cd2565b9150612d0a82846125a2565b915081905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612d4c826120e0565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612d7e57612d7d612d15565b5b600182019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612dc0826120e0565b9150612dcb836120e0565b925082612ddb57612dda612d89565b5b828204905092915050565b5f612df0826120e0565b9150612dfb836120e0565b9250828203905081811115612e1357612e12612d15565b5b92915050565b5f612e23826120e0565b9150612e2e836120e0565b9250828202612e3c816120e0565b91508282048414831517612e5357612e52612d15565b5b5092915050565b5f60ff82169050919050565b5f612e7082612e5a565b9150612e7b83612e5a565b9250828201905060ff811115612e9457612e93612d15565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f7b226e616d65223a20224d657461646174652f612000000000000000000000005f82015250565b5f612efb601583612490565b9150612f0682612ec7565b601582019050919050565b7f222c20226465736372697074696f6e223a2022416e20696d6d657273697665205f8201527f61727420696e7374616c6c6174696f6e207265636f7264696e6720746865206360208201527f6f6e76657267656e6365206f6620646174612e222c202261747472696275746560408201527f73223a205b000000000000000000000000000000000000000000000000000000606082015250565b5f612fb7606583612490565b9150612fc282612f11565b606582019050919050565b5f81519050919050565b5f81905092915050565b5f612feb82612fcd565b612ff58185612fd7565b93506130058185602086016123b6565b80840191505092915050565b7f5d2c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b5f8201527f6261736536342c00000000000000000000000000000000000000000000000000602082015250565b5f61306b602783612490565b915061307682613011565b602782019050919050565b7f227d0000000000000000000000000000000000000000000000000000000000005f82015250565b5f6130b5600283612490565b91506130c082613081565b600282019050919050565b5f6130d582612eef565b91506130e182866125a2565b91506130ec82612fab565b91506130f88285612fe1565b91506131038261305f565b915061310f82846125a2565b915061311a826130a9565b9150819050949350505050565b5f613131826120e0565b915061313c836120e0565b925082820190508082111561315457613153612d15565b5b92915050565b7f22000000000000000000000000000000000000000000000000000000000000005f82015250565b5f61318e600183612490565b91506131998261315a565b600182019050919050565b5f6131ae82613182565b91506131ba8284612a16565b91506131c582613182565b915081905092915050565b5f6131da82613182565b91506131e682846125a2565b91506131f182613182565b915081905092915050565b5f613207828f6125a2565b9150613213828e6125a2565b915061321f828d6125a2565b915061322b828c6125a2565b9150613237828b6125a2565b9150613243828a6125a2565b915061324f82896125a2565b915061325b82886125a2565b915061326782876125a2565b915061327382866125a2565b915061327f82856125a2565b915061328b82846125a2565b91508190509d9c50505050505050505050505050565b5f6132ac82846125a2565b915081905092915050565b7f7b000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6132eb600183612490565b91506132f6826132b7565b600182019050919050565b7f2274726169745f74797065223a202200000000000000000000000000000000005f82015250565b5f613335600f83612490565b915061334082613301565b600f82019050919050565b7f222c2276616c7565223a200000000000000000000000000000000000000000005f82015250565b5f61337f600b83612490565b915061338a8261334b565b600b82019050919050565b5f61339f826132df565b91506133aa82613329565b91506133b682866125a2565b91506133c182613373565b91506133cd82856125a2565b91506133d882612b52565b91506133e482846125a2565b915081905094935050505056fe3c7061746820643d224d3920394c392031302e31324c32362e33322031302e313256394c3920395a222f3e3c7061746820643d224d392031302e38344c392031312e33324c32362e33322031312e33325631302e38344c392031302e38345a222f3e3c7061746820643d224d392031322e37374c392031332e32354c32362e33322031332e32355631322e37374c392031322e37375a222f3e3c7061746820643d224d392031342e30354c392031342e35334c32362e33322031342e35335631342e30354c392031342e30355a222f3e3c7061746820643d224d392031352e394c392031382e334c32362e33322031382e335631352e394c392031352e395a222f3e3c7061746820643d224d392031392e37354c392032302e32334c32362e33322032302e32335631392e37354c392031392e37355a222f3e3c7061746820643d224d392032312e30334c392032322e30374c32362e33322032322e30375632312e30334c392032312e30335a222f3e3c7061746820643d224d392032332e35324c392032344c32362e33322032345632332e35324c392032332e35325a222f3e3c7061746820643d224d392032362e36354c392032372e31334832362e33325632362e363548395a222f3e3c7061746820643d224d392032392e37384c392033302e32364832362e33325632392e373848395a222f3e3c7061746820643d224d392033312e37314c392033322e38334832362e33325633312e373148395a222f3e3c7061746820643d224d392033332e36334c392033342e31314832362e33325633332e363348395a222f3e3c7061746820643d224d392033362e37364c392033372e38384832362e33325633362e373648395a222f3e3c7061746820643d224d392033382e36394c392033392e31374832362e33325633382e363948395a222f3e3c7061746820643d224d392034302e35374c392034312e30314832362e33324c32362e33322034302e353748395a222f3e3c7061746820643d224d392034322e34364c392034322e39344832362e33325634322e343648395a222f3e3c7061746820643d224d392034332e37344c392034342e38364832362e33325634332e373448395a222f3e3c7061746820643d224d392034372e35314c392034372e39394832362e33325634372e353148395a222f3e3c7061746820643d224d392034382e384c392035312e31324832362e33325634382e3848395a222f3e3c7061746820643d224d392035312e39334c392035332e36394832362e33325635312e393348395a222f3e3c7061746820643d224d392035342e34394c392035352e36314832362e33325635342e343948395a222f3e3c7061746820643d224d392035372e36324c392035392e33384832362e33325635372e363248395a222f3e3c7061746820643d224d392036302e31314c392036302e35394832362e33325636302e313148395a222f3e3c7061746820643d224d392036312e344c392036322e35324832362e33325636312e3448395a222f3e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f3c7061746820643d224d392032362e33324831302e3132563948395632362e33325a222f3e3c7061746820643d224d31302e38342032362e33324831312e333256394831302e38345632362e33325a222f3e3c7061746820643d224d31322e37372032362e33324831332e323556394831322e37375632362e33325a222f3e3c7061746820643d224d31342e30352032362e33324831342e353356394831342e30355632362e33325a222f3e3c7061746820643d224d31352e392032362e33324831382e3356394831352e395632362e33325a222f3e3c7061746820643d224d31392e37352032362e33324832302e323356394831392e37355632362e33325a222f3e3c7061746820643d224d32312e30332032362e33324832322e303756394832312e30335632362e33325a222f3e3c7061746820643d224d32332e35322032362e333248323456394832332e35325632362e33325a222f3e3c7061746820643d224d32362e36352032362e33324832372e313356394832362e36355632362e33325a222f3e3c7061746820643d224d32392e37382032362e33324833302e323656394832392e37385632362e33325a222f3e3c7061746820643d224d33312e37312032362e33324833322e383356394833312e37315632362e33325a222f3e3c7061746820643d224d33332e36332032362e33324833342e313156394833332e36335632362e33325a222f3e3c7061746820643d224d33362e37362032362e33324833372e383856394833362e37365632362e33325a222f3e3c7061746820643d224d33382e36392032362e33324833392e313756394833382e36395632362e33325a222f3e3c7061746820643d224d34302e35372032362e33324834312e303156394834302e35375632362e33325a222f3e3c7061746820643d224d34322e34362032362e33324834322e393456394834322e34365632362e33325a222f3e3c7061746820643d224d34332e37342032362e33324834342e383656394834332e37345632362e33325a222f3e3c7061746820643d224d34372e35312032362e33324834372e393956394834372e35315632362e33325a222f3e3c7061746820643d224d34382e382032362e33324835312e313256394834382e385632362e33325a222f3e3c7061746820643d224d35312e39332032362e33324835332e363956394835312e39335632362e33325a222f3e3c7061746820643d224d35342e34392032362e33324835352e363156394835342e34395632362e33325a222f3e3c7061746820643d224d35372e36322032362e33324835392e333856394835372e36325632362e33325a222f3e3c7061746820643d224d36302e31312032362e33324836302e353956394836302e31315632362e33325a222f3e3c7061746820643d224d36312e342032362e33324836322e353256394836312e345632362e33325a222f3ea264697066735822122017ee73f3e74ea938da135dc6576e352914b004314d647d04c1c182a4bd187aa864736f6c634300081700332363317b66696c6c3a234632364436313b6f7061636974793a3830253b7d2363327b66696c6c3a234632364436313b6f7061636974793a313030253b7d2363337b66696c6c3a234133433745393b6f7061636974793a3830253b7d2363347b66696c6c3a234133433745393b6f7061636974793a313030253b7d2363357b66696c6c3a233636393036303b6f7061636974793a3830253b7d2363367b66696c6c3a233636393036303b6f7061636974793a313030253b7d2363317b66696c6c3a234545323032453b6f7061636974793a3830253b7d2363327b66696c6c3a234545323032453b6f7061636974793a313030253b7d2363337b66696c6c3a234635453144333b6f7061636974793a3830253b7d2363347b66696c6c3a234635453144333b6f7061636974793a313030253b7d2363357b66696c6c3a233333333133323b6f7061636974793a3830253b7d2363367b66696c6c3a233333333133323b6f7061636974793a313030253b7d2363317b66696c6c3a234536303032303b6f7061636974793a3135253b7d2363327b66696c6c3a234536303032303b6f7061636974793a3330253b7d2363337b66696c6c3a234536303032303b6f7061636974793a3435253b7d2363347b66696c6c3a234536303032303b6f7061636974793a3630253b7d2363357b66696c6c3a234536303032303b6f7061636974793a3735253b7d2363367b66696c6c3a234536303032303b6f7061636974793a3930253b7d2363317b66696c6c3a234646463033323b6f7061636974793a313030253b7d2363327b66696c6c3a233030334536413b6f7061636974793a313030253b7d2363337b66696c6c3a233445344534393b6f7061636974793a313030253b7d2363347b66696c6c3a233445344534393b6f7061636974793a313030253b7d2363357b66696c6c3a233030334536413b6f7061636974793a313030253b7d2363367b66696c6c3a234646463033323b6f7061636974793a313030253b7d2363317b66696c6c3a234231374535343b6f7061636974793a3135253b7d2363327b66696c6c3a234132364334313b6f7061636974793a3330253b7d2363337b66696c6c3a233935354433313b6f7061636974793a3435253b7d2363347b66696c6c3a233837344431463b6f7061636974793a3630253b7d2363357b66696c6c3a233738334530433b6f7061636974793a3735253b7d2363367b66696c6c3a233641333130303b6f7061636974793a3930253b7d2363317b66696c6c3a234642384330353b6f7061636974793a313030253b7d2363327b66696c6c3a233939303033373b6f7061636974793a313030253b7d2363337b66696c6c3a233030333135453b6f7061636974793a313030253b7d2363347b66696c6c3a233030333135453b6f7061636974793a313030253b7d2363357b66696c6c3a233939303033373b6f7061636974793a313030253b7d2363367b66696c6c3a234642384330353b6f7061636974793a313030253b7d2363317b66696c6c3a234631363639303b6f7061636974793a3830253b7d2363327b66696c6c3a234631363639303b6f7061636974793a313030253b7d2363337b66696c6c3a234546433341333b6f7061636974793a3830253b7d2363347b66696c6c3a234546433341333b6f7061636974793a313030253b7d2363357b66696c6c3a234646434630313b6f7061636974793a3830253b7d2363367b66696c6c3a234646434630313b6f7061636974793a313030253b7d2363317b66696c6c3a234235384237463b6f7061636974793a313030253b7d2363327b66696c6c3a233141313831383b6f7061636974793a313030253b7d2363337b66696c6c3a233030413441353b6f7061636974793a313030253b7d2363347b66696c6c3a233030413441353b6f7061636974793a313030253b7d2363357b66696c6c3a233141313831383b6f7061636974793a313030253b7d2363367b66696c6c3a234235384237463b6f7061636974793a313030253b7d2363317b66696c6c3a233233314632303b6f7061636974793a3135253b7d2363327b66696c6c3a233233314632303b6f7061636974793a3330253b7d2363337b66696c6c3a233233314632303b6f7061636974793a3435253b7d2363347b66696c6c3a233233314632303b6f7061636974793a3630253b7d2363357b66696c6c3a233233314632303b6f7061636974793a3735253b7d2363367b66696c6c3a233233314632303b6f7061636974793a3930253b7d2363317b66696c6c3a234546343237373b6f7061636974793a3830253b7d2363327b66696c6c3a234546343237373b6f7061636974793a313030253b7d2363337b66696c6c3a233236413139313b6f7061636974793a3830253b7d2363347b66696c6c3a233236413139313b6f7061636974793a313030253b7d2363357b66696c6c3a234646434630313b6f7061636974793a3830253b7d2363367b66696c6c3a234646434630313b6f7061636974793a313030253b7d2363317b66696c6c3a234641384132343b6f7061636974793a313030253b7d2363327b66696c6c3a233141313831383b6f7061636974793a313030253b7d2363337b66696c6c3a234536303032303b6f7061636974793a313030253b7d2363347b66696c6c3a234536303032303b6f7061636974793a313030253b7d2363357b66696c6c3a233141313831383b6f7061636974793a313030253b7d2363367b66696c6c3a234641384132343b6f7061636974793a313030253b7d2363317b66696c6c3a234631354432413b6f7061636974793a3830253b7d2363327b66696c6c3a234631354432413b6f7061636974793a313030253b7d2363337b66696c6c3a234232413941373b6f7061636974793a3830253b7d2363347b66696c6c3a234232413941373b6f7061636974793a313030253b7d2363357b66696c6c3a233244364342353b6f7061636974793a3830253b7d2363367b66696c6c3a233244364342353b6f7061636974793a313030253b7d2363317b66696c6c3a233536383836313b6f7061636974793a313030253b7d2363327b66696c6c3a233435374235333b6f7061636974793a313030253b7d2363337b66696c6c3a233332364534333b6f7061636974793a313030253b7d2363347b66696c6c3a233230363133343b6f7061636974793a313030253b7d2363357b66696c6c3a233030353532363b6f7061636974793a313030253b7d2363367b66696c6c3a233030344231433b6f7061636974793a313030253b7d2363317b66696c6c3a234646434630313b6f7061636974793a3135253b7d2363327b66696c6c3a234646434630313b6f7061636974793a3330253b7d2363337b66696c6c3a234646434630313b6f7061636974793a3435253b7d2363347b66696c6c3a234646434630313b6f7061636974793a3630253b7d2363357b66696c6c3a234646434630313b6f7061636974793a3735253b7d2363367b66696c6c3a234646434630313b6f7061636974793a3930253b7d2363317b66696c6c3a233030323835303b6f7061636974793a3135253b7d2363327b66696c6c3a233030323835303b6f7061636974793a3330253b7d2363337b66696c6c3a233030323835303b6f7061636974793a3435253b7d2363347b66696c6c3a233030323835303b6f7061636974793a3630253b7d2363357b66696c6c3a233030323835303b6f7061636974793a3735253b7d2363367b66696c6c3a233030323835303b6f7061636974793a3930253b7d

Deployed Bytecode

0x60806040526004361061020e575f3560e01c80638462151c11610117578063bd296d231161009f578063d89135cd1161006e578063d89135cd1461078a578063d9e54e24146107b4578063dac2e804146107de578063e985e9c514610808578063f2fde38b146108445761020e565b8063bd296d23146106c2578063c23dc68f146106ea578063c87b56dd14610726578063d1f7a9c5146107625761020e565b806399a2557a116100e657806399a2557a146105ea578063a0712d6814610626578063a22cb46514610642578063b0dc78fa1461066a578063b88d4fde146106a65761020e565b80638462151c146105305780638a0275fe1461056c5780638da5cb5b1461059657806395d89b41146105c05761020e565b806342842e0e1161019a5780635bbb2177116101695780635bbb21771461042a5780636352211e146104665780636511cc77146104a257806370a08231146104de578063715018a61461051a5761020e565b806342842e0e1461036a57806342966c68146103865780634f64b2be146103ae5780635a72bfa9146103ee5761020e565b806318160ddd116101e157806318160ddd146102d057806323b872dd146102fa578063379607f5146103165780633ccfd60b1461033e5780634063151d146103545761020e565b806301ffc9a71461021257806306fdde031461024e578063081812fc14610278578063095ea7b3146102b4575b5f80fd5b34801561021d575f80fd5b5061023860048036038101906102339190613732565b61086c565b6040516102459190613777565b60405180910390f35b348015610259575f80fd5b506102626108fd565b60405161026f919061381a565b60405180910390f35b348015610283575f80fd5b5061029e6004803603810190610299919061386d565b61098d565b6040516102ab91906138d7565b60405180910390f35b6102ce60048036038101906102c9919061391a565b610a07565b005b3480156102db575f80fd5b506102e4610b46565b6040516102f19190613967565b60405180910390f35b610314600480360381019061030f9190613980565b610b5b565b005b348015610321575f80fd5b5061033c6004803603810190610337919061386d565b610e69565b005b348015610349575f80fd5b50610352610fe1565b005b34801561035f575f80fd5b506103686110ea565b005b610384600480360381019061037f9190613980565b611261565b005b348015610391575f80fd5b506103ac60048036038101906103a7919061386d565b611280565b005b3480156103b9575f80fd5b506103d460048036038101906103cf919061386d565b61128e565b6040516103e5959493929190613acf565b60405180910390f35b3480156103f9575f80fd5b50610414600480360381019061040f919061386d565b611457565b6040516104219190613777565b60405180910390f35b348015610435575f80fd5b50610450600480360381019061044b9190613b8f565b611474565b60405161045d9190613d23565b60405180910390f35b348015610471575f80fd5b5061048c6004803603810190610487919061386d565b611534565b60405161049991906138d7565b60405180910390f35b3480156104ad575f80fd5b506104c860048036038101906104c39190613d43565b611545565b6040516104d59190613777565b60405180910390f35b3480156104e9575f80fd5b5061050460048036038101906104ff9190613d43565b611562565b6040516105119190613967565b60405180910390f35b348015610525575f80fd5b5061052e611617565b005b34801561053b575f80fd5b5061055660048036038101906105519190613d43565b61162a565b6040516105639190613e16565b60405180910390f35b348015610577575f80fd5b50610580611766565b60405161058d9190613967565b60405180910390f35b3480156105a1575f80fd5b506105aa61176c565b6040516105b791906138d7565b60405180910390f35b3480156105cb575f80fd5b506105d4611794565b6040516105e1919061381a565b60405180910390f35b3480156105f5575f80fd5b50610610600480360381019061060b9190613e36565b611824565b60405161061d9190613e16565b60405180910390f35b610640600480360381019061063b919061386d565b611a23565b005b34801561064d575f80fd5b5061066860048036038101906106639190613eb0565b611bf8565b005b348015610675575f80fd5b50610690600480360381019061068b919061386d565b611cfe565b60405161069d919061381a565b60405180910390f35b6106c060048036038101906106bb9190614016565b611db3565b005b3480156106cd575f80fd5b506106e860048036038101906106e39190614209565b611e25565b005b3480156106f5575f80fd5b50610710600480360381019061070b919061386d565b6122d9565b60405161071d9190614305565b60405180910390f35b348015610731575f80fd5b5061074c6004803603810190610747919061386d565b612343565b604051610759919061381a565b60405180910390f35b34801561076d575f80fd5b5061078860048036038101906107839190614373565b6123fa565b005b348015610795575f80fd5b5061079e6124de565b6040516107ab9190613967565b60405180910390f35b3480156107bf575f80fd5b506107c86124ec565b6040516107d59190613967565b60405180910390f35b3480156107e9575f80fd5b506107f2612560565b6040516107ff9190613967565b60405180910390f35b348015610813575f80fd5b5061082e600480360381019061082991906143be565b612566565b60405161083b9190613777565b60405180910390f35b34801561084f575f80fd5b5061086a60048036038101906108659190613d43565b6125f4565b005b5f6301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108c657506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806108f65750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60606002805461090c90614429565b80601f016020809104026020016040519081016040528092919081815260200182805461093890614429565b80156109835780601f1061095a57610100808354040283529160200191610983565b820191905f5260205f20905b81548152906001019060200180831161096657829003601f168201915b5050505050905090565b5f61099782612678565b6109cd576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60065f8381526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f610a1182611534565b90508073ffffffffffffffffffffffffffffffffffffffff16610a326126d2565b73ffffffffffffffffffffffffffffffffffffffff1614610a9557610a5e81610a596126d2565b612566565b610a94576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b8260065f8481526020019081526020015f205f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b5f610b4f6126d9565b6001545f540303905090565b5f610b65826126e1565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610bcc576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80610bd7846127a4565b91509150610bed8187610be86126d2565b6127c7565b610c3957610c0286610bfd6126d2565b612566565b610c38576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610c9e576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cab868686600161280a565b8015610cb5575f82555b60055f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154600190039190508190555060055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815460010191905081905550610d7d85610d5988888761286a565b7c020000000000000000000000000000000000000000000000000000000017612891565b60045f8681526020019081526020015f20819055505f7c0200000000000000000000000000000000000000000000000000000000841603610df9575f6001850190505f60045f8381526020019081526020015f205403610df7575f548114610df6578360045f8381526020019081526020015f20819055505b5b505b838573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4610e6186868660016128bb565b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1673f9f27aa7718dccf4b4306e0321c2ce85215fa90273ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610ecd9190613967565b602060405180830381865afa158015610ee8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f0c919061446d565b73ffffffffffffffffffffffffffffffffffffffff16148015610f4a5750600d5f8281526020019081526020015f205f9054906101000a900460ff16155b8015610f5c57505f610f5a6124ec565b115b8015610f6f57506004610f6d6124ec565b105b15610fac57610f7e60016128c1565b6001600d5f8381526020019081526020015f205f6101000a81548160ff021916908315150217905550610fde565b6040517f3c21f90f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b610fe96129c2565b5f4790505f8103611026576040517f669567ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60028261103491906144f2565b90505f81836110439190614522565b9050739390333197446ec19b1b4dc7dc7fc5ae4957ebba73ffffffffffffffffffffffffffffffffffffffff166108fc8390811502906040515f60405180830381858888f1935050505080156110dd57507338f0dbba41258639ba0b2cddc753e46157ce14d073ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f193505050505b6110e5575f80fd5b505050565b6110f26129c2565b60046110fc6124ec565b10806111145750600960149054906101000a900460ff165b1561114b576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b60c8811015611201575f6111846107e8836111689190614555565b60016103e86111779190614555565b61117f612a49565b612a5a565b9050600c5f8281526020019081526020015f205f015f9054906101000a900460ff161580156111c857506007600c5f8381526020019081526020015f206002015414155b156111f3576111da826008600a612a5a565b600c5f8381526020019081526020015f20600201819055505b50808060010191505061114d565b506001600960146101000a81548160ff0219169083151502179055507f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c6103e8611249612a49565b604051611257929190614588565b60405180910390a1565b61127b83838360405180602001604052805f815250611db3565b505050565b61128b816001612abf565b50565b600c602052805f5260405f205f91509050805f015f9054906101000a900460ff16908060010154908060020154908060030180546112cb90614429565b80601f01602080910402602001604051908101604052809291908181526020018280546112f790614429565b80156113425780601f1061131957610100808354040283529160200191611342565b820191905f5260205f20905b81548152906001019060200180831161132557829003601f168201915b505050505090806004016040518060e00160405290815f82015f9054906101000a900460ff161515151581526020015f820160019054906101000a900460ff161515151581526020015f820160029054906101000a900460ff161515151581526020016001820180546113b490614429565b80601f01602080910402602001604051908101604052809291908181526020018280546113e090614429565b801561142b5780601f106114025761010080835404028352916020019161142b565b820191905f5260205f20905b81548152906001019060200180831161140e57829003601f168201915b505050505081526020016002820154815260200160038201548152602001600482015481525050905085565b600d602052805f5260405f205f915054906101000a900460ff1681565b60605f8383905090505f8167ffffffffffffffff81111561149857611497613ef2565b5b6040519080825280602002602001820160405280156114d157816020015b6114be613681565b8152602001906001900390816114b65790505b5090505f5b828114611528576114ff8686838181106114f3576114f26145af565b5b905060200201356122d9565b828281518110611512576115116145af565b5b60200260200101819052508060010190506114d6565b50809250505092915050565b5f61153e826126e1565b9050919050565b600e602052805f5260405f205f915054906101000a900460ff1681565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036115c8576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054169050919050565b61161f6129c2565b6116285f612cfb565b565b60605f805f61163885611562565b90505f8167ffffffffffffffff81111561165557611654613ef2565b5b6040519080825280602002602001820160405280156116835781602001602082028036833780820191505090505b50905061168e613681565b5f6116976126d9565b90505b838614611758576116aa81612dbe565b9150816040015161174d575f73ffffffffffffffffffffffffffffffffffffffff16825f015173ffffffffffffffffffffffffffffffffffffffff16146116f257815f015194505b8773ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361174c578083878060010198508151811061173f5761173e6145af565b5b6020026020010181815250505b5b80600101905061169a565b508195505050505050919050565b600b5481565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600380546117a390614429565b80601f01602080910402602001604051908101604052809291908181526020018280546117cf90614429565b801561181a5780601f106117f15761010080835404028352916020019161181a565b820191905f5260205f20905b8154815290600101906020018083116117fd57829003601f168201915b5050505050905090565b606081831061185f576040517f32c1995a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80611869612de7565b90506118736126d9565b851015611885576118826126d9565b94505b80841115611891578093505b5f61189b87611562565b9050848610156118bd575f8686039050818110156118b7578091505b506118c1565b5f90505b5f8167ffffffffffffffff8111156118dc576118db613ef2565b5b60405190808252806020026020018201604052801561190a5781602001602082028036833780820191505090505b5090505f82036119205780945050505050611a1c565b5f61192a886122d9565b90505f816040015161193d57815f015190505b5f8990505b8881141580156119525750848714155b15611a0e5761196081612dbe565b92508260400151611a03575f73ffffffffffffffffffffffffffffffffffffffff16835f015173ffffffffffffffffffffffffffffffffffffffff16146119a857825f015191505b8a73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611a0257808488806001019950815181106119f5576119f46145af565b5b6020026020010181815250505b5b806001019050611942565b508583528296505050505050505b9392505050565b5f611a2c6124ec565b90506611c37937e0800082611a4191906145dc565b341015611a7a576040517ff14a42b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028103611bab57600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1680611b6157505f73f9f27aa7718dccf4b4306e0321c2ce85215fa90273ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b8152600401611b2091906138d7565b602060405180830381865afa158015611b3b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b5f9190614631565b115b15611b7457611b6f826128c1565b611ba6565b6040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611bf4565b60038103611bc157611bbc826128c1565b611bf3565b6040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b5050565b8060075f611c046126d2565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611cad6126d2565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611cf29190613777565b60405180910390a35050565b606060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663489320a4600c5f8581526020019081526020015f206040518263ffffffff1660e01b8152600401611d6a91906148f4565b5f60405180830381865afa158015611d84573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611dac9190614982565b9050919050565b611dbe848484610b5b565b5f8373ffffffffffffffffffffffffffffffffffffffff163b14611e1f57611de884848484612def565b611e1e576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b5f84845f818110611e3957611e386145af565b5b905060200201359050611e4d858533612f3a565b611e83576040517f97792c3200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185859050036120c1576007600c5f8381526020019081526020015f2060020154118015611ec65750600b600c5f8381526020019081526020015f2060020154105b1561201657611edd83606001518460c00151612fc2565b611f13576040517f7a2a029c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6064611f1e8361306b565b1115611f56576040517f69ed1ea500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260600151600c5f8381526020019081526020015f206004016001019081611f7e9190614b54565b508260c00151600c5f8381526020019081526020015f206004016004018190555081600c5f8381526020019081526020015f206003019081611fc09190614b54565b50600c5f8281526020019081526020015f205f015f9054906101000a900460ff16612011576001600c5f8381526020019081526020015f205f015f6101000a81548160ff0219169083151502179055505b612085565b6103e88111806120425750600c5f8281526020019081526020015f205f015f9054906101000a900460ff165b15612079576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120848184846130d5565b5b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7816040516120b49190613967565b60405180910390a16122bb565b6005858590500361228857600c5f8281526020019081526020015f205f015f9054906101000a900460ff1615612123576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b600581101561228257612164600c5f888885818110612147576121466145af565b5b9050602002013581526020019081526020015f2060020154613369565b1561219b576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818686838181106121af576121ae6145af565b5b9050602002013503612202576121c68285856130d5565b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7826040516121f59190613967565b60405180910390a1612275565b612224868683818110612218576122176145af565b5b90506020020135611280565b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7868683818110612258576122576145af565b5b9050602002013560405161226c9190613967565b60405180910390a15b8080600101915050612125565b506122ba565b6040517f524f409b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b600b5f8154809291906122cd90614c23565b91905055505050505050565b6122e1613681565b6122e9613681565b6122f16126d9565b8310806123055750612301612de7565b8310155b15612313578091505061233e565b61231c83612dbe565b9050806040015115612331578091505061233e565b61233a836133a1565b9150505b919050565b606060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a3915e6583600c5f8681526020019081526020015f206040518363ffffffff1660e01b81526004016123b1929190614c6a565b5f60405180830381865afa1580156123cb573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906123f39190614982565b9050919050565b6124026129c2565b5f61240b6124ec565b1115612443576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b828290508110156124d9576001600e5f858585818110612468576124676145af565b5b905060200201602081019061247d9190613d43565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508080600101915050612445565b505050565b5f6124e76133c1565b905090565b5f6365ae74e0421015612501575f905061255d565b612a306365ae74e06125139190614555565b421015612523576001905061255d565b6162706365ae74e06125359190614555565b421015612545576002905061255d565b600a54421015612558576003905061255d565b600490505b90565b600a5481565b5f60075f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6125fc6129c2565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361266c575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161266391906138d7565b60405180910390fd5b61267581612cfb565b50565b5f816126826126d9565b1115801561269057505f5482105b80156126cb57505f7c010000000000000000000000000000000000000000000000000000000060045f8581526020019081526020015f205416145b9050919050565b5f33905090565b5f6001905090565b5f80829050806126ef6126d9565b1161276d575f5481101561276c575f60045f8381526020019081526020015f205490505f7c010000000000000000000000000000000000000000000000000000000082160361276a575b5f81036127605760045f836001900393508381526020019081526020015f20549050612739565b809250505061279f565b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b5f805f60065f8581526020019081526020015f2090508092508254915050915091565b5f73ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b612816848484846133ca565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612864576007600c5f8481526020019081526020015f20600201819055505b50505050565b5f8060e883901c905060e86128808686846133d0565b62ffffff16901b9150509392505050565b5f73ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b5f5b8181101561294c575f816128d5612de7565b6128df9190614555565b90506103e88111156129145761290f8161290742846128fe9190614555565b60016006612a5a565b60ff166133d8565b61293e565b6103e88103612933576203f4804261292c9190614555565b600a819055505b61293d815f6133d8565b5b5080806001019150506128c3565b50600a81116129645761295f338261340e565b6129bf565b5f5b600a8261297391906144f2565b8110156129925761298533600a61340e565b8080600101915050612966565b505f600a826129a19190614c98565b11156129be576129bd33600a836129b89190614c98565b61340e565b5b5b50565b6129ca6135b7565b73ffffffffffffffffffffffffffffffffffffffff166129e861176c565b73ffffffffffffffffffffffffffffffffffffffff1614612a4757612a0b6135b7565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401612a3e91906138d7565b60405180910390fd5b565b5f612a526126d9565b5f5403905090565b5f8060018484612a6a9190614522565b612a749190614555565b90508085604051602001612a889190614ce8565b604051602081830303815290604052805190602001205f1c612aaa9190614c98565b84612ab59190614555565b9150509392505050565b5f612ac9836126e1565b90505f8190505f80612ada866127a4565b915091508415612b4357612af68184612af16126d2565b6127c7565b612b4257612b0b83612b066126d2565b612566565b612b41576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b5b612b50835f88600161280a565b8015612b5a575f82555b600160806001901b0360055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282540192505081905550612bfe83612bbb855f8861286a565b7c02000000000000000000000000000000000000000000000000000000007c01000000000000000000000000000000000000000000000000000000001717612891565b60045f8881526020019081526020015f20819055505f7c0200000000000000000000000000000000000000000000000000000000851603612c7a575f6001870190505f60045f8381526020019081526020015f205403612c78575f548114612c77578460045f8381526020019081526020015f20819055505b5b505b855f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612ce2835f8860016128bb565b60015f8154809291906001019190505550505050505050565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612dc6613681565b612de060045f8481526020019081526020015f20546135be565b9050919050565b5f8054905090565b5f8373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612e146126d2565b8786866040518563ffffffff1660e01b8152600401612e369493929190614d54565b6020604051808303815f875af1925050508015612e7157506040513d601f19601f82011682018060405250810190612e6e9190614db2565b60015b612ee7573d805f8114612e9f576040519150601f19603f3d011682016040523d82523d5f602084013e612ea4565b606091505b505f815103612edf576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b5f805f90505b84849050811015612fb5578273ffffffffffffffffffffffffffffffffffffffff16612f84868684818110612f7857612f776145af565b5b90506020020135611534565b73ffffffffffffffffffffffffffffffffffffffff1614612fa8575f915050612fbb565b8080600101915050612f40565b50600190505b9392505050565b5f6006821080612fd25750601d82115b15612fdf575f9050613065565b5f612fe98461306b565b90505f60078211612ffd57601d905061305c565b6010821161300e57600b905061305b565b6016821161301f576009905061305a565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161305190614e27565b60405180910390fd5b5b5b80841115925050505b92915050565b5f805f90505f5b83518110156130cb57608060c0858381518110613092576130916145af565b5b602001015160f81c60f81b60f81c1660ff16146130b85781806130b490614c23565b9250505b80806130c390614c23565b915050613072565b8192505050919050565b600f82608001511115613114576040517f02e14b0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60078260a001511115613153576040517f3d36cb8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61316582606001518360c00151612fc2565b61319b576040517f7a2a029c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60646131a68261306b565b11156131de576040517f69ed1ea500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600c5f8581526020019081526020015f2060030190816131ff9190614b54565b506040518060e00160405280835f01511515815260200183602001511515815260200183604001511515815260200183606001518152602001836080015181526020018360a0015181526020018360c00151815250600c5f8581526020019081526020015f206004015f820151815f015f6101000a81548160ff0219169083151502179055506020820151815f0160016101000a81548160ff0219169083151502179055506040820151815f0160026101000a81548160ff02191690831515021790555060608201518160010190816132d89190614b54565b506080820151816002015560a0820151816003015560c08201518160040155905050600c5f8481526020019081526020015f205f015f9054906101000a900460ff16613364576001600c5f8581526020019081526020015f205f015f6101000a81548160ff021916908315150217905550600b600c5f8581526020019081526020015f20600201819055505b505050565b5f80820361337a576001905061339c565b60078211801561338a5750600b82105b15613398576001905061339c565b5f90505b919050565b6133a9613681565b6133ba6133b5836126e1565b6135be565b9050919050565b5f600154905090565b50505050565b5f9392505050565b80600c5f8481526020019081526020015f206001018190555080600c5f8481526020019081526020015f20600201819055505050565b5f805490505f820361344c576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6134585f84838561280a565b600160406001901b17820260055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055506134ca836134bb5f865f61286a565b6134c485613672565b17612891565b60045f8381526020019081526020015f20819055505f80838301905073ffffffffffffffffffffffffffffffffffffffff8516915082825f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4600183015b8181146135645780835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a460018101905061352b565b505f820361359e576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f8190555050506135b25f8483856128bb565b505050565b5f33905090565b6135c6613681565b81815f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060a082901c816020019067ffffffffffffffff16908167ffffffffffffffff16815250505f7c01000000000000000000000000000000000000000000000000000000008316141581604001901515908115158152505060e882901c816060019062ffffff16908162ffffff1681525050919050565b5f6001821460e11b9050919050565b60405180608001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f67ffffffffffffffff1681526020015f151581526020015f62ffffff1681525090565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613711816136dd565b811461371b575f80fd5b50565b5f8135905061372c81613708565b92915050565b5f60208284031215613747576137466136d5565b5b5f6137548482850161371e565b91505092915050565b5f8115159050919050565b6137718161375d565b82525050565b5f60208201905061378a5f830184613768565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156137c75780820151818401526020810190506137ac565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6137ec82613790565b6137f6818561379a565b93506138068185602086016137aa565b61380f816137d2565b840191505092915050565b5f6020820190508181035f83015261383281846137e2565b905092915050565b5f819050919050565b61384c8161383a565b8114613856575f80fd5b50565b5f8135905061386781613843565b92915050565b5f60208284031215613882576138816136d5565b5b5f61388f84828501613859565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6138c182613898565b9050919050565b6138d1816138b7565b82525050565b5f6020820190506138ea5f8301846138c8565b92915050565b6138f9816138b7565b8114613903575f80fd5b50565b5f81359050613914816138f0565b92915050565b5f80604083850312156139305761392f6136d5565b5b5f61393d85828601613906565b925050602061394e85828601613859565b9150509250929050565b6139618161383a565b82525050565b5f60208201905061397a5f830184613958565b92915050565b5f805f60608486031215613997576139966136d5565b5b5f6139a486828701613906565b93505060206139b586828701613906565b92505060406139c686828701613859565b9150509250925092565b6139d98161375d565b82525050565b5f82825260208201905092915050565b5f6139f982613790565b613a0381856139df565b9350613a138185602086016137aa565b613a1c816137d2565b840191505092915050565b613a308161383a565b82525050565b5f60e083015f830151613a4b5f8601826139d0565b506020830151613a5e60208601826139d0565b506040830151613a7160408601826139d0565b5060608301518482036060860152613a8982826139ef565b9150506080830151613a9e6080860182613a27565b5060a0830151613ab160a0860182613a27565b5060c0830151613ac460c0860182613a27565b508091505092915050565b5f60a082019050613ae25f830188613768565b613aef6020830187613958565b613afc6040830186613958565b8181036060830152613b0e81856137e2565b90508181036080830152613b228184613a36565b90509695505050505050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f840112613b4f57613b4e613b2e565b5b8235905067ffffffffffffffff811115613b6c57613b6b613b32565b5b602083019150836020820283011115613b8857613b87613b36565b5b9250929050565b5f8060208385031215613ba557613ba46136d5565b5b5f83013567ffffffffffffffff811115613bc257613bc16136d9565b5b613bce85828601613b3a565b92509250509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b613c0c816138b7565b82525050565b5f67ffffffffffffffff82169050919050565b613c2e81613c12565b82525050565b5f62ffffff82169050919050565b613c4b81613c34565b82525050565b608082015f820151613c655f850182613c03565b506020820151613c786020850182613c25565b506040820151613c8b60408501826139d0565b506060820151613c9e6060850182613c42565b50505050565b5f613caf8383613c51565b60808301905092915050565b5f602082019050919050565b5f613cd182613bda565b613cdb8185613be4565b9350613ce683613bf4565b805f5b83811015613d16578151613cfd8882613ca4565b9750613d0883613cbb565b925050600181019050613ce9565b5085935050505092915050565b5f6020820190508181035f830152613d3b8184613cc7565b905092915050565b5f60208284031215613d5857613d576136d5565b5b5f613d6584828501613906565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f613da28383613a27565b60208301905092915050565b5f602082019050919050565b5f613dc482613d6e565b613dce8185613d78565b9350613dd983613d88565b805f5b83811015613e09578151613df08882613d97565b9750613dfb83613dae565b925050600181019050613ddc565b5085935050505092915050565b5f6020820190508181035f830152613e2e8184613dba565b905092915050565b5f805f60608486031215613e4d57613e4c6136d5565b5b5f613e5a86828701613906565b9350506020613e6b86828701613859565b9250506040613e7c86828701613859565b9150509250925092565b613e8f8161375d565b8114613e99575f80fd5b50565b5f81359050613eaa81613e86565b92915050565b5f8060408385031215613ec657613ec56136d5565b5b5f613ed385828601613906565b9250506020613ee485828601613e9c565b9150509250929050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b613f28826137d2565b810181811067ffffffffffffffff82111715613f4757613f46613ef2565b5b80604052505050565b5f613f596136cc565b9050613f658282613f1f565b919050565b5f67ffffffffffffffff821115613f8457613f83613ef2565b5b613f8d826137d2565b9050602081019050919050565b828183375f83830152505050565b5f613fba613fb584613f6a565b613f50565b905082815260208101848484011115613fd657613fd5613eee565b5b613fe1848285613f9a565b509392505050565b5f82601f830112613ffd57613ffc613b2e565b5b813561400d848260208601613fa8565b91505092915050565b5f805f806080858703121561402e5761402d6136d5565b5b5f61403b87828801613906565b945050602061404c87828801613906565b935050604061405d87828801613859565b925050606085013567ffffffffffffffff81111561407e5761407d6136d9565b5b61408a87828801613fe9565b91505092959194509250565b5f80fd5b5f80fd5b5f67ffffffffffffffff8211156140b8576140b7613ef2565b5b6140c1826137d2565b9050602081019050919050565b5f6140e06140db8461409e565b613f50565b9050828152602081018484840111156140fc576140fb613eee565b5b614107848285613f9a565b509392505050565b5f82601f83011261412357614122613b2e565b5b81356141338482602086016140ce565b91505092915050565b5f60e0828403121561415157614150614096565b5b61415b60e0613f50565b90505f61416a84828501613e9c565b5f83015250602061417d84828501613e9c565b602083015250604061419184828501613e9c565b604083015250606082013567ffffffffffffffff8111156141b5576141b461409a565b5b6141c18482850161410f565b60608301525060806141d584828501613859565b60808301525060a06141e984828501613859565b60a08301525060c06141fd84828501613859565b60c08301525092915050565b5f805f8060608587031215614221576142206136d5565b5b5f85013567ffffffffffffffff81111561423e5761423d6136d9565b5b61424a87828801613b3a565b9450945050602085013567ffffffffffffffff81111561426d5761426c6136d9565b5b6142798782880161413c565b925050604085013567ffffffffffffffff81111561429a576142996136d9565b5b6142a68782880161410f565b91505092959194509250565b608082015f8201516142c65f850182613c03565b5060208201516142d96020850182613c25565b5060408201516142ec60408501826139d0565b5060608201516142ff6060850182613c42565b50505050565b5f6080820190506143185f8301846142b2565b92915050565b5f8083601f84011261433357614332613b2e565b5b8235905067ffffffffffffffff8111156143505761434f613b32565b5b60208301915083602082028301111561436c5761436b613b36565b5b9250929050565b5f8060208385031215614389576143886136d5565b5b5f83013567ffffffffffffffff8111156143a6576143a56136d9565b5b6143b28582860161431e565b92509250509250929050565b5f80604083850312156143d4576143d36136d5565b5b5f6143e185828601613906565b92505060206143f285828601613906565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061444057607f821691505b602082108103614453576144526143fc565b5b50919050565b5f81519050614467816138f0565b92915050565b5f60208284031215614482576144816136d5565b5b5f61448f84828501614459565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6144fc8261383a565b91506145078361383a565b92508261451757614516614498565b5b828204905092915050565b5f61452c8261383a565b91506145378361383a565b925082820390508181111561454f5761454e6144c5565b5b92915050565b5f61455f8261383a565b915061456a8361383a565b9250828201905080821115614582576145816144c5565b5b92915050565b5f60408201905061459b5f830185613958565b6145a86020830184613958565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6145e68261383a565b91506145f18361383a565b92508282026145ff8161383a565b91508282048414831517614616576146156144c5565b5b5092915050565b5f8151905061462b81613843565b92915050565b5f60208284031215614646576146456136d5565b5b5f6146538482850161461d565b91505092915050565b5f815f1c9050919050565b5f60ff82169050919050565b5f6146856146808361465c565b614667565b9050919050565b5f819050919050565b5f6146a76146a28361465c565b61468c565b9050919050565b5f819050815f5260205f209050919050565b5f81546146cc81614429565b6146d681866139df565b9450600182165f81146146f0576001811461470657614738565b60ff198316865281151560200286019350614738565b61470f856146ae565b5f5b8381101561473057815481890152600182019150602081019050614711565b808801955050505b50505092915050565b5f8160081c9050919050565b5f61475f61475a83614741565b614667565b9050919050565b5f8160101c9050919050565b5f61478461477f83614766565b614667565b9050919050565b5f60e083015f8084015490506147a081614673565b6147ac5f8701826139d0565b506147b68161474d565b6147c360208701826139d0565b506147cd81614772565b6147da60408701826139d0565b506001840185830360608701526147f183826146c0565b9250506002840154905061480481614695565b6148116080870182613a27565b506003840154905061482281614695565b61482f60a0870182613a27565b506004840154905061484081614695565b61484d60c0870182613a27565b50819250505092915050565b5f60a083015f80840154905061486e81614673565b61487a5f8701826139d0565b506001840154905061488b81614695565b6148986020870182613a27565b50600284015490506148a981614695565b6148b66040870182613a27565b506003840185830360608701526148cd83826146c0565b9250506004840185830360808701526148e6838261478b565b925050819250505092915050565b5f6020820190508181035f83015261490c8184614859565b905092915050565b5f6149266149218461409e565b613f50565b90508281526020810184848401111561494257614941613eee565b5b61494d8482856137aa565b509392505050565b5f82601f83011261496957614968613b2e565b5b8151614979848260208601614914565b91505092915050565b5f60208284031215614997576149966136d5565b5b5f82015167ffffffffffffffff8111156149b4576149b36136d9565b5b6149c084828501614955565b91505092915050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302614a137fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826149d8565b614a1d86836149d8565b95508019841693508086168417925050509392505050565b5f819050919050565b5f614a58614a53614a4e8461383a565b614a35565b61383a565b9050919050565b5f819050919050565b614a7183614a3e565b614a85614a7d82614a5f565b8484546149e4565b825550505050565b5f90565b614a99614a8d565b614aa4818484614a68565b505050565b5b81811015614ac757614abc5f82614a91565b600181019050614aaa565b5050565b601f821115614b0c57614add816146ae565b614ae6846149c9565b81016020851015614af5578190505b614b09614b01856149c9565b830182614aa9565b50505b505050565b5f82821c905092915050565b5f614b2c5f1984600802614b11565b1980831691505092915050565b5f614b448383614b1d565b9150826002028217905092915050565b614b5d82613790565b67ffffffffffffffff811115614b7657614b75613ef2565b5b614b808254614429565b614b8b828285614acb565b5f60209050601f831160018114614bbc575f8415614baa578287015190505b614bb48582614b39565b865550614c1b565b601f198416614bca866146ae565b5f5b82811015614bf157848901518255600182019150602085019450602081019050614bcc565b86831015614c0e5784890151614c0a601f891682614b1d565b8355505b6001600288020188555050505b505050505050565b5f614c2d8261383a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614c5f57614c5e6144c5565b5b600182019050919050565b5f604082019050614c7d5f830185613958565b8181036020830152614c8f8184614859565b90509392505050565b5f614ca28261383a565b9150614cad8361383a565b925082614cbd57614cbc614498565b5b828206905092915050565b5f819050919050565b614ce2614cdd8261383a565b614cc8565b82525050565b5f614cf38284614cd1565b60208201915081905092915050565b5f81519050919050565b5f82825260208201905092915050565b5f614d2682614d02565b614d308185614d0c565b9350614d408185602086016137aa565b614d49816137d2565b840191505092915050565b5f608082019050614d675f8301876138c8565b614d7460208301866138c8565b614d816040830185613958565b8181036060830152614d938184614d1c565b905095945050505050565b5f81519050614dac81613708565b92915050565b5f60208284031215614dc757614dc66136d5565b5b5f614dd484828501614d9e565b91505092915050565b7f696e76616c6964206c656e6774680000000000000000000000000000000000005f82015250565b5f614e11600e8361379a565b9150614e1c82614ddd565b602082019050919050565b5f6020820190508181035f830152614e3e81614e05565b905091905056fea2646970667358221220372f96efb9bf8fd2c063fd42d3ae70e20116b2a331f1377a5970c58b7675af5064736f6c63430008170033

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

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