ETH Price: $2,289.15 (-3.53%)

Token

CosmicWorlds (CWS)
 

Overview

Max Total Supply

223 CWS

Holders

0

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 0 Decimals)

Balance
1 CWS

Value
$0.00
0xac7e8d9b835e57c04fbeea049186f2d9a80ad026
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:
CosmicWorlds

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 13 : CosmicWorlds.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "erc721a/contracts/ERC721A.sol";
import "erc721a/contracts/extensions/ERC721AQueryable.sol";
import "./StringUtils.sol";
import "./WorldBuilder.sol";
import "hardhat/console.sol";
import "./ERC2981/ERC2981Royalties.sol";

contract CosmicWorlds is ERC721AQueryable, ERC2981Royalties {
    uint16 public constant TOKEN_LIMIT = 512;
    mapping(uint256 => uint24) private seedMapping;
    mapping(uint24 => bool) private usedSeeds;

    constructor() ERC721A("CosmicWorlds", "CWS") {}

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721A, IERC721A, ERC2981Royalties)
        returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    function mint(uint24 _seed) public payable {
        require(_totalMinted() <= TOKEN_LIMIT, "TOKEN_LIMIT_HIT");
        require(usedSeeds[_seed] == false, "SEED_USED");

        uint256 tokenID = _nextTokenId();
        seedMapping[tokenID] = _seed;
        usedSeeds[_seed] = true;
        _mint(msg.sender, 1);
    }

    function mintMany(uint24[] memory seeds) external payable {
        require(_totalMinted() <= TOKEN_LIMIT, "TOKEN_LIMIT_HIT");

        // uint256 tokenID = _nextTokenId();
        // _mint(msg.sender, seeds.length);

        // for (uint i = 0; i < seeds.length; i++) {
        //     seedMapping[tokenID + i] = seeds[i];
        //     usedSeeds[seeds[i]] = true;
        // }

        uint validCount = 0;
        
        for (uint i = 0; i < seeds.length; i++) {
            if (usedSeeds[seeds[i]] == false) {
                validCount = validCount + 1;
            } else {
                delete seeds[i];
            }
            if (_totalMinted() + validCount >= TOKEN_LIMIT || validCount >= 10) {
                break;
            }
        }

        uint256 startTokenID = _nextTokenId();
        _mint(msg.sender, validCount);

        uint j = 0;
        while (validCount > 0) { 
            uint currentTokenID = startTokenID + j;
            if (seeds[j] != 0) {
                seedMapping[currentTokenID] = seeds[j];
                usedSeeds[seeds[j]] = true;
                validCount = validCount - 1;
            }
            j = j + 1;
        }
    }

    function tokenURI(uint256 _tokenId) public view override(ERC721A, IERC721A) returns (string memory) {
        require(_exists(_tokenId), "BAD_ID");
    
        // TODO: Consider if base64 encoding is necessary.. which chain to use?
        // Base64 encode because OpenSea does not interpret data properly as plaintext served from Polygon
        return string(abi.encodePacked(
            'data:application/json,{"name":"CWS #',  StringUtils.uintToString(_tokenId), ': a stunning Cosmic World",'
                '"description": "https://cosmicworlds.xyz", ', 
                WorldBuilder.getTraits(seedMapping[_tokenId]), ', '
                '"image": "data:image/svg+xml,', 
                generateSvg(_tokenId), 
                '"}'
            )); 
    }

    function generateSvg(uint256 _tokenId) public view returns (string memory) {
        require(_exists(_tokenId) && _tokenId < TOKEN_LIMIT, "BAD_ID");
        return WorldBuilder.build(seedMapping[_tokenId]);
    }    

// FOR OPENSEA
    function contractURI() public pure returns (string memory) {
        return "https://www.cosmicworlds.xyz/storefront-metadata";
    }

}

File 2 of 13 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

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

pragma solidity ^0.8.0;

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

File 4 of 13 : ERC2981Royalties.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/utils/introspection/ERC165.sol';
import './IERC2981Royalties.sol';

abstract contract ERC2981Royalties is ERC165, IERC2981Royalties {
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override
        returns (bool) {
        return interfaceId == type(IERC2981Royalties).interfaceId || super.supportsInterface(interfaceId);
    }

    function royaltyInfo(uint256, uint256 value)
        public
        pure
        override
        returns (address receiver, uint256 royaltyAmount) {
        return (address(0x8c0E2ac43de845116E6c70319c4B6DB9463399C8), (value * 250) / 10000);
    }
}

File 5 of 13 : IERC2981Royalties.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @title IERC2981Royalties
/// @dev Interface for the ERC2981 - Token Royalty standard
interface IERC2981Royalties {
    /// @notice Called with the sale price to determine how much royalty
    //          is owed and to whom.
    /// @param _tokenId - the NFT asset queried for royalty information
    /// @param _value - the sale price of the NFT asset specified by _tokenId
    /// @return _receiver - address of who should be sent the royalty payment
    /// @return _royaltyAmount - the royalty payment amount for value sale price
    function royaltyInfo(uint256 _tokenId, uint256 _value)
        external
        view
        returns (address _receiver, uint256 _royaltyAmount);
}

File 6 of 13 : Random.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "./StringUtils.sol";

library Random {

    function randomIntStr(uint randomSeed, uint min, uint max) internal pure returns (string memory) {
        return StringUtils.uintToString(randomInt(randomSeed, min, max));
    }

    function randomInt(uint randomSeed, uint min, uint max) internal pure returns (uint) {
        if (max <= min) {
            return min;
        }

        uint seed = uint(keccak256(abi.encode(randomSeed)));
        return uint(seed % (max - min + 1)) + min;
    }

    function randomColour(uint randomSeed) internal pure returns (string memory) {
        return StringUtils.rgbString(randomInt(randomSeed, 0, 255), randomInt(randomSeed + 2, 0, 255), randomInt(randomSeed + 1, 0, 255));        
    }
}

File 7 of 13 : StringUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

library StringUtils {
    function uintToString(uint _i) internal pure returns (string memory str) {
        unchecked {
            if (_i == 0) {
                return "0";
            }

            uint j = _i;
            uint length;
            while (j != 0) {
                length++;
                j /= 10;
            }

            bytes memory bstr = new bytes(length);
            uint k = length;
            j = _i;
            while (j != 0) {
                bstr[--k] = bytes1(uint8(48 + j % 10));
                j /= 10;
            }
            
            str = string(bstr);
        }
    }

    function rgbString(uint red, uint green, uint blue) internal pure returns (string memory) {
        // return string(abi.encodePacked("rgb(", StringUtils.smallUintToString(red), ", ", StringUtils.smallUintToString(green), ", ", StringUtils.smallUintToString(blue), ")"));
        return string(abi.encodePacked("rgb(", StringUtils.uintToString(red), ", ", StringUtils.uintToString(green), ", ", StringUtils.uintToString(blue), ")"));
    }
}

File 8 of 13 : WorldBuilder.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "./StringUtils.sol";
import "./Random.sol";

library WorldBuilder {
    struct PlanetDetails {
        uint i;
        string iStr;
        uint radius;
        uint randomSeed;
    } 
    
    function build(uint randomSeed) internal pure returns (string memory) {
        string memory bgGradient = string(abi.encodePacked(
            "linear-gradient(", 
            Random.randomIntStr(randomSeed, 0, 360), 
            "deg, ", Random.randomColour(randomSeed + 1), " 0%, ", 
            Random.randomColour(randomSeed + 2), " 35%, ", 
            Random.randomColour(randomSeed + 3), " 100%)"));

        string memory defs = string(abi.encodePacked("<defs><clipPath id='mcp'><rect x='0' y='0' width='1e3' height='1e3'/></clipPath></defs>"));
        string memory shapes = string(abi.encodePacked(
            getStars(randomSeed),
            getPlanets(randomSeed), 
            getMountains(randomSeed), 
            getWater(randomSeed),
            getClouds(randomSeed)
        ));

        return string(abi.encodePacked("<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1e3 1e3' style='background-image:", bgGradient, "'>", defs, "<g clip-path='url(#mcp)'>", shapes, "</g></svg>"));
    }

// STARS 

    function getStars(uint randomSeed) private pure returns (string memory) {
        return string(abi.encodePacked(
            "<filter id='sf'>"
                "<feTurbulence baseFrequency='0.", Random.randomIntStr(randomSeed, 15, 40), "' seed='", StringUtils.uintToString(randomSeed), "'/>"
                "<feColorMatrix values='0 0 0 9 -4 "
                    "0 0 0 9 -4 "
                    "0 0 0 9 -4 "
                    "0 0 0 0 1'/>"
            "</filter>"
            "<rect width='100%' height='100%' opacity='50%' filter='url(#sf)'/>"
        ));
    }

// PLANETS

    function getPlanetCount(uint planetSeed) private pure returns (uint)  {
        uint percent = Random.randomInt(planetSeed * 2, 0, 100);

        if (percent < 5) {
            return 0;
        } else if (percent < 15) {
            return 1;
        } else if (percent < 40) {
            return 2;
        } else if (percent < 85) {
            return 3;
        } else if (percent < 95) {
            return 4;
        } else {
            return 5;
        }
    }

    function getPlanets(uint planetSeed) private pure returns (string memory) {
        string memory planets = "";

        for (uint i = 0; i < getPlanetCount(planetSeed); i++) {
            PlanetDetails memory details = PlanetDetails(i, StringUtils.uintToString(i), Random.randomInt(planetSeed * 2 + i, 20, 200), planetSeed * 2 + i);

            planets = string(abi.encodePacked(planets,
                                    getPlanetGradient(details),
                                    getPlanetFilter(details),
                                    getPlanetCircle(details)
            )); 
        }

        return planets;
    }

    function getPlanetGradient(PlanetDetails memory details) private pure returns (string memory) {
        return string(abi.encodePacked(
            "<defs><radialGradient id='pg", details.iStr, "' fx='50%' fy='50%'>",
                stopOffset(Random.randomIntStr(details.randomSeed, 3, 25), Random.randomColour(details.randomSeed + details.i)),
                stopOffset(Random.randomIntStr(details.randomSeed, 75, 97), Random.randomColour(details.randomSeed + details.i + 10)),
            "</radialGradient></defs>"));
    }

    function getPlanetFilter(PlanetDetails memory details) private pure returns (string memory) {
            return string(abi.encodePacked(
                "<filter id='pf", details.iStr, "' x='-25%' y='-25%' width='150%' height='150%'>", 
                    getTurbulence(details), 
                    getLighting(details),
                    "<feComposite result='p' operator='in' in2='SourceGraphic'/>"
                    "<feGaussianBlur stdDeviation='8' result='cb'/>"
                    "<feMerge>"
                        "<feMergeNode in='cb'/>"
                        "<feMergeNode in='p'/>"
                    "</feMerge>"
                "</filter>"
            ));
    }

    function getTurbulence(PlanetDetails memory details) private pure returns (string memory) {
        string memory turbulenceType = Random.randomInt(details.randomSeed, 0, 10) > 5 ? 'fractalNoise' : 'turbulence';
        return string(abi.encodePacked(
            "<feTurbulence type='", turbulenceType,"' baseFrequency='", getBaseFrequency(details),"' seed='", StringUtils.uintToString(details.randomSeed), "' numOctaves='", Random.randomIntStr(details.randomSeed, 3, 10), "'/>"
        ));
    }
    
    function getBaseFrequency(PlanetDetails memory details) private pure returns (string memory) {
        // Intentionally make the baseFrequency y value larger than the x value
        // to create horizontal striping patterns
        return string(abi.encodePacked(
            "0.00",  StringUtils.uintToString(Random.randomInt(details.randomSeed, 1, 3) * 1e3 / (details.radius * 2)), 
            " 0.0", StringUtils.uintToString(Random.randomInt(details.randomSeed, 2, 3) * 1e3 / details.radius)
        ));
    }    

    function getLighting(PlanetDetails memory details) private pure returns (string memory) {
        return string(abi.encodePacked(
            "<feDiffuseLighting lighting-color='", Random.randomColour(details.randomSeed + details.i), "' surfaceScale='", Random.randomIntStr(details.randomSeed, 5, 10), "'>"
                "<feDistantLight elevation='", Random.randomIntStr(details.randomSeed, 30, 100), "'/>"
            "</feDiffuseLighting>"        
        ));
    }

    function getPlanetCircle(PlanetDetails memory details) private pure returns (string memory) {
        string memory x = Random.randomIntStr(details.randomSeed, 50, 950);
        string memory y = Random.randomIntStr(details.randomSeed, 0, 500);

        return string(abi.encodePacked(
            getTextureCircle(x, y, details),
            getGradientCircle(x, y, details)
        ));
    }
    function getTextureCircle(string memory x, string memory y, PlanetDetails memory details) private pure returns (string memory) {
        return string(abi.encodePacked(
            "<circle cx='", x, "' cy='", y, "' r='", StringUtils.uintToString(details.radius), "' filter='url(#pf", details.iStr, ")'/>"
        ));

    }
    function getGradientCircle(string memory x, string memory y, PlanetDetails memory details) private pure returns (string memory) {
        return string(abi.encodePacked(
            "<circle cx='", x, "' cy='", y, "' r='", StringUtils.uintToString(details.radius),  "' fill='url(#pg", details.iStr, ")' opacity='40%'/>"                                
        ));        
    }

// MOUNTAINS

    function getMountains(uint randomSeed) private pure returns (string memory) {
        uint[2][51] memory polygonPoints = buildLine(randomSeed, 1e3, 51);
        string memory polygonPointsStr;

        for (uint i; i < 51; i++) {
            uint[2] memory point = polygonPoints[i];
            polygonPointsStr = string(abi.encodePacked(polygonPointsStr, " ", StringUtils.uintToString(point[0]), ",", StringUtils.uintToString(point[1])));    
        }
        polygonPointsStr = string(abi.encodePacked(polygonPointsStr, " 1e3,1e3 -1,1e3"));    

        string memory filter = string(abi.encodePacked(
                "<filter id='mf'>"
                        "<feTurbulence type='fractalNoise' baseFrequency='0.0", Random.randomIntStr(randomSeed, 10, 30), "' numOctaves='15'/>"
                        "<feDiffuseLighting lighting-color='white' surfaceScale='", Random.randomIntStr(randomSeed, 1, 3), "'>"
                            "<feDistantLight azimuth='45' elevation='10'/>"
                        "</feDiffuseLighting>"
                    "<feComposite result='m' operator='in' in2='SourceGraphic'/>"
                    "<feGaussianBlur stdDeviation='8'/>"
                    "<feColorMatrix type='matrix' values='"
                        "0 0 0 0 0 "
                        "0 0 0 0 0 "
                        "0 0 0 0 0 "
                        "0 0 0 0.5 0' "
                        "result='b'"
                        "/>"
                    "<feMerge>"
                        "<feMergeNode in='m'/>"
                        "<feMergeNode in='b'/>"
                    "</feMerge>"
                "</filter>"));

        string memory mountainColour = Random.randomColour(randomSeed + 3);
        string memory gradient = string(abi.encodePacked(
            "<defs>"
                "<linearGradient id='mg'>",
                    stopOffset('5', mountainColour),
                    stopOffset(Random.randomIntStr(randomSeed, 20, 80), Random.randomColour(randomSeed + 5)),
                    stopOffset('95', mountainColour),
                "</linearGradient>"
            "</defs>"));
        string memory opacity = Random.randomIntStr(randomSeed, 30, 60);    

        string memory shadingFilter = string(abi.encodePacked(
             "<filter id='msf'>"
                "<feTurbulence type='fractalNoise' baseFrequency='0.004 0.01' numOctaves='2' seed='", StringUtils.uintToString(randomSeed), "'/>"
                "<feColorMatrix values='0 1 0 0 -4 "
                                        "1 1 0 0 -4 "
                                        "1 0 0 0 -4 "
                                        "0 1 1 0 -1'/>"
                "<feComposite operator='in' in2='SourceGraphic'/>"
                "</filter>"
        ));

        return string(abi.encodePacked(
            filter, 
            gradient, 
            shadingFilter,
            "<polygon points='", polygonPointsStr, "' filter='url(#mf)'/>"
            "<polygon points='", polygonPointsStr, "' fill='url(#mg)' opacity='", opacity, "%'/>"
            "<polygon points='", polygonPointsStr, "' filter='url(#msf)'/>"
        )); 
    }
    
    function stopOffset(string memory offset, string memory color)  private pure returns (string memory) {
        return string(abi.encodePacked("<stop offset='", offset, "%' stop-color='", color, "'/>"));
    }

    function buildLine(uint randomSeed, uint width, uint pointCount) private pure returns (uint[2][51] memory) {
        uint interval = width / (pointCount - 1);
        uint[2][51] memory points;
        uint currentY = 500; // starting currentY is yOffset

        for (uint i = 0; i < pointCount; i++) {
            uint x = i * interval;
            uint pointSeed = (randomSeed + i) + 1e3;
            uint yChange = Random.randomInt(pointSeed, 0, 20);
            bool up = Random.randomInt(pointSeed, 0, 100) > 50;

            currentY = up ? currentY + yChange : currentY - yChange;

            points[i] = [x, currentY];
        }
        // console.log("POINTS: " + points);
        return points;
    }

// CLOUDS

    function getClouds(uint randomSeed) private pure returns (string memory) {
        string memory baseFrequency1 = Random.randomIntStr(randomSeed * 2, 1, 8);
        string memory r = Random.randomIntStr(randomSeed + 10, 0, 9);
        string memory g = Random.randomIntStr(randomSeed + 20, 0, 9);
        string memory b = Random.randomIntStr(randomSeed + 30, 0, 9);
    
        return string(abi.encodePacked(
            "<filter id='cf'>",
                "<feTurbulence type='fractalNoise' baseFrequency='0.00", baseFrequency1, " 0.02' numOctaves='2' seed='", StringUtils.uintToString(randomSeed), "'/>"
                "<feColorMatrix type='matrix' values='"
                          "0 0 0 0.", r, " 0 "
                          "0 0 0 0.", g, " 0 "
                          "0 0 0 0.", b, " 0 "
                          "0 0 0 1 0'"
            "/>"
            "</filter>"
            "<rect width='100%' height='100%' opacity='", Random.randomIntStr(randomSeed * 5, 60, 80), "%' filter='url(#cf)'/>"));
    }

// WATER

    function getWater(uint randomSeed) private pure returns (string memory) {
        string memory shorelineCurves = "";
        uint xPos;
        bool up = Random.randomInt(randomSeed, 0, 1) > 0;

        while (xPos < 1e3) {
            uint segmentWidth = Random.randomInt(randomSeed + xPos, 150, 300);
            
            if (segmentWidth > 1e3 - xPos) {
                segmentWidth = 1e3 - xPos;
            } else if ((1e3 - xPos) - segmentWidth < 100) {
                segmentWidth += (1e3 - xPos) - segmentWidth;
            }

            uint yDelta = Random.randomInt(randomSeed + xPos, 10, 30);
            uint yPos = (up ? 800 - yDelta : 800 + yDelta);
            
            shorelineCurves = string(abi.encodePacked(shorelineCurves,
                "C ", StringUtils.uintToString(xPos), " 800, ", 
                StringUtils.uintToString(xPos + segmentWidth / 2), " ", StringUtils.uintToString(yPos), ", ", 
                StringUtils.uintToString(xPos + segmentWidth), " 800 "
            ));
            
            xPos += segmentWidth;
            up = !up;
        }
        // // console.log("SHORELINE CURVES: " + shorelineCurves);

        string memory floodColor = Random.randomColour(randomSeed * 4);
        string memory waterBlur = Random.randomIntStr(randomSeed, 1, 3);

        return string(abi.encodePacked(
            "<filter id='wf'>"
                "<feTurbulence baseFrequency='0.00", Random.randomIntStr(randomSeed * 2, 2, 9), " .11' numOctaves='4' seed='", StringUtils.uintToString(randomSeed), "'/>"
                "<feComponentTransfer result='wave'>"
                    "<feFuncR type='linear' slope='0.1' intercept='-0.05'/>"
                    "<feFuncG type='gamma' amplitude='0.75' exponent='0.6' offset='0.05'/>"
                    "<feFuncB type='gamma' amplitude='0.8' exponent='0.4' offset='0.05'/>"
                    "<feFuncA type='linear' slope='", Random.randomIntStr(randomSeed, 1, 10), "'/>"
                "</feComponentTransfer>"
                "<feFlood flood-color='", floodColor, "'/>"
                "<feComposite in='wave'/>"
                "<feComposite in2='SourceAlpha' operator='in'/>"
                "<feGaussianBlur stdDeviation='", waterBlur, "' result='glow'/>"
                "<feComposite in2='glow' operator='atop' result='g' />"
                "<feMerge>"
                    "<feMergeNode/>"
                    "<feMergeNode/>"
                "</feMerge>"

            "</filter>"
            "<path d='M 0 1e3 L 0 800 ", shorelineCurves, " L 1e3 800 L 1e3 1e3' filter='url(#wf)' fill-opacity='70%'/>"
        )); 
    }
 
    function getTraits(uint seed) internal pure returns (string memory) {
        return string(abi.encodePacked('"attributes": '
            '[{"trait_type": "seed", "value": ', StringUtils.uintToString(seed), '},'
            '{"trait_type": "stars", "value": "', getStarType(seed),'"},'
            '{"trait_type": "planets", "value": ', StringUtils.uintToString(getPlanetCount(seed)), '},'
            '{"trait_type": "mountains", "value": "', getMountainType(seed),'"},'
            '{"trait_type": "water", "value": "', getWaterType(seed),'"},'
            '{"trait_type": "clouds", "value": "', getCloudType(seed),'"}'
            ']'));
    }

    function getStarType(uint seed) internal pure returns (string memory) {
        uint density = Random.randomInt(seed, 15, 40);
        if (density < 22) {
            return "sparse";
        } else if (density > 33) {
            return "dense";
        } else {
            return "distributed";
        }
    }
    
    function getMountainType(uint seed) internal pure returns (string memory) {
        uint mountainFrequency = Random.randomInt(seed, 10, 30);
        uint mountainScale = Random.randomInt(seed, 1, 3);
        if (mountainFrequency < 20 && mountainScale < 2) {
            return "soft";
        } else if (mountainFrequency > 20 && mountainScale > 2) {
            return "rocky";
        } else {
            return "rugged";
        }
    }

    function getWaterType(uint seed) internal pure returns (string memory) {
        uint choppiness = Random.randomInt(seed * 2, 2, 9);
        if (choppiness < 4) {
            return "calm";
        } else if (choppiness > 6) {
            return "rough";
        } else {
            return "choppy";
        }
    }

    function getCloudType(uint seed) internal pure returns (string memory) {
        uint cloud = Random.randomInt(seed * 2, 1, 8);
        if (cloud < 3) {
            return "stratus";
        } else if ( cloud > 6) {
            return "cumulus";
        } else {
            return "stratocumulus";
        }
    }
}

File 9 of 13 : 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 10 of 13 : 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 11 of 13 : 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 13 : 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 13 of 13 : console.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 <0.9.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

}

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

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":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"TOKEN_LIMIT","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"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":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","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":"generateSvg","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"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":"uint24","name":"_seed","type":"uint24"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint24[]","name":"seeds","type":"uint24[]"}],"name":"mintMany","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"pure","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":"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":"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"}]

60806040523480156200001157600080fd5b506040518060400160405280600c81526020016b436f736d6963576f726c647360a01b8152506040518060400160405280600381526020016243575360e81b815250816002908162000064919062000125565b50600362000073828262000125565b50506000805550620001f1565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620000ab57607f821691505b602082108103620000cc57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200012057600081815260208120601f850160051c81016020861015620000fb5750805b601f850160051c820191505b818110156200011c5782815560010162000107565b5050505b505050565b81516001600160401b0381111562000141576200014162000080565b620001598162000152845462000096565b84620000d2565b602080601f831160018114620001915760008415620001785750858301515b600019600386901b1c1916600185901b1785556200011c565b600085815260208120601f198616915b82811015620001c257888601518255948401946001909101908401620001a1565b5085821015620001e15787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61466180620002016000396000f3fe60806040526004361061014b5760003560e01c80638462151c116100b6578063bc921dc21161006f578063bc921dc2146103ba578063c23dc68f146103da578063c87b56dd14610407578063e8a3d48514610427578063e985e9c51461043c578063eaef4d8f1461048557600080fd5b80638462151c146103125780639197898f1461033f57806395d89b411461035257806399a2557a14610367578063a22cb46514610387578063b88d4fde146103a757600080fd5b806323b872dd1161010857806323b872dd146102405780632a55205a1461025357806342842e0e146102925780635bbb2177146102a55780636352211e146102d257806370a08231146102f257600080fd5b806301ffc9a714610150578063031bd4c41461018557806306fdde03146101ae578063081812fc146101d0578063095ea7b31461020857806318160ddd1461021d575b600080fd5b34801561015c57600080fd5b5061017061016b366004612530565b610498565b60405190151581526020015b60405180910390f35b34801561019157600080fd5b5061019b61020081565b60405161ffff909116815260200161017c565b3480156101ba57600080fd5b506101c36104a9565b60405161017c919061259d565b3480156101dc57600080fd5b506101f06101eb3660046125b0565b61053b565b6040516001600160a01b03909116815260200161017c565b61021b6102163660046125e5565b61057f565b005b34801561022957600080fd5b50600154600054035b60405190815260200161017c565b61021b61024e36600461260f565b61061f565b34801561025f57600080fd5b5061027361026e36600461264b565b6107b7565b604080516001600160a01b03909316835260208301919091520161017c565b61021b6102a036600461260f565b6107f2565b3480156102b157600080fd5b506102c56102c036600461266d565b610812565b60405161017c919061271f565b3480156102de57600080fd5b506101f06102ed3660046125b0565b6108de565b3480156102fe57600080fd5b5061023261030d366004612761565b6108e9565b34801561031e57600080fd5b5061033261032d366004612761565b610938565b60405161017c919061277c565b61021b61034d36600461280e565b610a41565b34801561035e57600080fd5b506101c3610c54565b34801561037357600080fd5b506103326103823660046128bb565b610c63565b34801561039357600080fd5b5061021b6103a23660046128ee565b610ddd565b61021b6103b536600461292a565b610e49565b3480156103c657600080fd5b506101c36103d53660046125b0565b610e8d565b3480156103e657600080fd5b506103fa6103f53660046125b0565b610ef7565b60405161017c91906129ea565b34801561041357600080fd5b506101c36104223660046125b0565b610f6f565b34801561043357600080fd5b506101c3611006565b34801561044857600080fd5b506101706104573660046129f8565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b61021b610493366004612a2b565b611026565b60006104a382611111565b92915050565b6060600280546104b890612a46565b80601f01602080910402602001604051908101604052809291908181526020018280546104e490612a46565b80156105315780601f1061050657610100808354040283529160200191610531565b820191906000526020600020905b81548152906001019060200180831161051457829003601f168201915b5050505050905090565b600061054682611146565b610563576040516333d1c03960e21b815260040160405180910390fd5b506000908152600660205260409020546001600160a01b031690565b600061058a826108de565b9050336001600160a01b038216146105c3576105a68133610457565b6105c3576040516367d9dca160e11b815260040160405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600061062a8261116d565b9050836001600160a01b0316816001600160a01b03161461065d5760405162a1148160e81b815260040160405180910390fd5b60008281526006602052604090208054338082146001600160a01b038816909114176106aa5761068d8633610457565b6106aa57604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b0385166106d157604051633a954ecd60e21b815260040160405180910390fd5b80156106dc57600082555b6001600160a01b038681166000908152600560205260408082208054600019019055918716808252919020805460010190554260a01b17600160e11b17600085815260046020526040812091909155600160e11b8416900361076e5760018401600081815260046020526040812054900361076c57600054811461076c5760008181526004602052604090208490555b505b83856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050505050565b600080738c0e2ac43de845116e6c70319c4b6db9463399c86127106107dd8560fa612a90565b6107e79190612abd565b915091509250929050565b61080d83838360405180602001604052806000815250610e49565b505050565b60608160008167ffffffffffffffff811115610830576108306127b4565b60405190808252806020026020018201604052801561088257816020015b60408051608081018252600080825260208083018290529282018190526060820152825260001990920191018161084e5790505b50905060005b8281146108d5576108b08686838181106108a4576108a4612ad1565b90506020020135610ef7565b8282815181106108c2576108c2612ad1565b6020908102919091010152600101610888565b50949350505050565b60006104a38261116d565b60006001600160a01b038216610912576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b031660009081526005602052604090205467ffffffffffffffff1690565b60606000806000610948856108e9565b905060008167ffffffffffffffff811115610965576109656127b4565b60405190808252806020026020018201604052801561098e578160200160208202803683370190505b5090506109bb60408051608081018252600080825260208201819052918101829052606081019190915290565b60005b838614610a35576109ce816111d4565b91508160400151610a2d5781516001600160a01b0316156109ee57815194505b876001600160a01b0316856001600160a01b031603610a2d5780838780600101985081518110610a2057610a20612ad1565b6020026020010181815250505b6001016109be565b50909695505050505050565b610200610a4d60005490565b1115610a925760405162461bcd60e51b815260206004820152600f60248201526e1513d2d15397d31253525517d21255608a1b60448201526064015b60405180910390fd5b6000805b8251811015610b535760096000848381518110610ab557610ab5612ad1565b60209081029190910181015162ffffff16825281019190915260400160009081205460ff1615159003610af457610aed826001612ae7565b9150610b18565b828181518110610b0657610b06612ad1565b60200260200101600062ffffff168152505b61020082610b2560005490565b610b2f9190612ae7565b101580610b3d5750600a8210155b610b535780610b4b81612afa565b915050610a96565b50600054610b613383611210565b60005b8215610c4e576000610b768284612ae7565b9050848281518110610b8a57610b8a612ad1565b602002602001015162ffffff16600014610c3b57848281518110610bb057610bb0612ad1565b60200260200101516008600083815260200190815260200160002060006101000a81548162ffffff021916908362ffffff160217905550600160096000878581518110610bff57610bff612ad1565b60209081029190910181015162ffffff168252810191909152604001600020805460ff1916911515919091179055610c38600185612b13565b93505b610c46826001612ae7565b915050610b64565b50505050565b6060600380546104b890612a46565b6060818310610c8557604051631960ccad60e11b815260040160405180910390fd5b600080610c9160005490565b905080841115610c9f578093505b6000610caa876108e9565b905084861015610cc95785850381811015610cc3578091505b50610ccd565b5060005b60008167ffffffffffffffff811115610ce857610ce86127b4565b604051908082528060200260200182016040528015610d11578160200160208202803683370190505b50905081600003610d27579350610dd692505050565b6000610d3288610ef7565b905060008160400151610d43575080515b885b888114158015610d555750848714155b15610dca57610d63816111d4565b92508260400151610dc25782516001600160a01b031615610d8357825191505b8a6001600160a01b0316826001600160a01b031603610dc25780848880600101995081518110610db557610db5612ad1565b6020026020010181815250505b600101610d45565b50505092835250909150505b9392505050565b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610e5484848461061f565b6001600160a01b0383163b15610c4e57610e708484848461130e565b610c4e576040516368d2bf6b60e11b815260040160405180910390fd5b6060610e9882611146565b8015610ea5575061020082105b610eda5760405162461bcd60e51b815260206004820152600660248201526510905117d25160d21b6044820152606401610a89565b6000828152600860205260409020546104a39062ffffff166113f9565b6040805160808082018352600080835260208084018290528385018290526060808501839052855193840186528284529083018290529382018190529281018390529091506000548310610f4b5792915050565b610f54836111d4565b9050806040015115610f665792915050565b610dd683611572565b6060610f7a82611146565b610faf5760405162461bcd60e51b815260206004820152600660248201526510905117d25160d21b6044820152606401610a89565b610fb8826115a7565b600083815260086020526040902054610fd59062ffffff1661167e565b610fde84610e8d565b604051602001610ff093929190612b42565b6040516020818303038152906040529050919050565b60606040518060600160405280603081526020016145fc60309139905090565b61020061103260005490565b11156110725760405162461bcd60e51b815260206004820152600f60248201526e1513d2d15397d31253525517d21255608a1b6044820152606401610a89565b62ffffff811660009081526009602052604090205460ff16156110c35760405162461bcd60e51b815260206004820152600960248201526814d1515117d554d15160ba1b6044820152606401610a89565b60008054808252600860209081526040808420805462ffffff191662ffffff871690811790915584526009909152909120805460ff1916600190811790915561110d903390611210565b5050565b60006001600160e01b0319821663152a902d60e11b14806104a357506301ffc9a760e01b6001600160e01b03198316146104a3565b60008054821080156104a3575050600090815260046020526040902054600160e01b161590565b6000816000548110156111bb5760008181526004602052604081205490600160e01b821690036111b9575b80600003610dd6575060001901600081815260046020526040902054611198565b505b604051636f96cda160e11b815260040160405180910390fd5b6040805160808101825260008082526020820181905291810182905260608101919091526000828152600460205260409020546104a3906116d3565b60008054908290036112355760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b03831660008181526005602090815260408083208054680100000000000000018802019055848352600490915281206001851460e11b4260a01b178317905582840190839083907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4600183015b8181146112e457808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a46001016112ac565b508160000361130557604051622e076360e81b815260040160405180910390fd5b60005550505050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290611343903390899088908890600401612c53565b6020604051808303816000875af192505050801561137e575060408051601f3d908101601f1916820190925261137b91810190612c90565b60015b6113dc573d8080156113ac576040519150601f19603f3d011682016040523d82523d6000602084013e6113b1565b606091505b5080516000036113d4576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b6060600061140b83600061016861171b565b61141e611419856001612ae7565b611733565b61142c611419866002612ae7565b61143a611419876003612ae7565b60405160200161144d9493929190612cad565b604051602081830303815290604052905060006040516020016114df907f3c646566733e3c636c6970506174682069643d276d6370273e3c72656374207881527f3d27302720793d2730272077696474683d2731653327206865696768743d273160208201527f6533272f3e3c2f636c6970506174683e3c2f646566733e000000000000000000604082015260570190565b604051602081830303815290604052905060006114fb8561176f565b61150486611798565b61150d8761187a565b61151688611a85565b61151f89611c72565b604051602001611533959493929190612d67565b604051602081830303815290604052905082828260405160200161155993929190612dd2565b6040516020818303038152906040529350505050919050565b6040805160808101825260008082526020820181905291810182905260608101919091526104a36115a28361116d565b6116d3565b6060816000036115ce5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156115e657600101600a820491506115d2565b60008167ffffffffffffffff811115611601576116016127b4565b6040519080825280601f01601f19166020018201604052801561162b576020820181803683370190505b508593509050815b83156108d557600a840660300160f81b8282600190039250828151811061165c5761165c612ad1565b60200101906001600160f81b031916908160001a905350600a84049350611633565b6060611689826115a7565b61169283611d21565b6116a361169e85611dbc565b6115a7565b6116ac85611e3b565b6116b586611ef5565b6116be87611f8d565b604051602001610ff096959493929190612ed3565b604080516080810182526001600160a01b038316815260a083901c67ffffffffffffffff166020820152600160e01b831615159181019190915260e89190911c606082015290565b606061172b61169e858585612031565b949350505050565b60606104a361174583600060ff612031565b61175c611753856002612ae7565b600060ff612031565b61176a611753866001612ae7565b6120a3565b606061177e82600f602861171b565b611787836115a7565b604051602001610ff09291906130ad565b60408051602081019091526000808252606091905b6117b684611dbc565b81101561187357600060405180608001604052808381526020016117d9846115a7565b8152602001611800846117ed896002612a90565b6117f79190612ae7565b601460c8612031565b815260200183611811886002612a90565b61181b9190612ae7565b9052905082611829826120ea565b6118328361215e565b61183b84612189565b60405160200161184e94939291906131e8565b604051602081830303815290604052925050808061186b90612afa565b9150506117ad565b5092915050565b6060600061188c836103e860336121f6565b9050606060005b603381101561190b5760008382603381106118b0576118b0612ad1565b60200201519050826118c98260005b60200201516115a7565b6118d48360016118bf565b6040516020016118e69392919061323f565b604051602081830303815290604052925050808061190390612afa565b915050611893565b508060405160200161191d919061329e565b6040516020818303038152906040529050600061193d85600a601e61171b565b61194a866001600361171b565b60405160200161195b9291906132d1565b60408051601f198184030181529190529050600061197d611419876003612ae7565b905060006119a4604051806040016040528060018152602001603560f81b815250836122df565b6119c76119b4896014605061171b565b6119c26114198b6005612ae7565b6122df565b6119eb60405180604001604052806002815260200161393560f01b815250856122df565b6040516020016119fd93929190613552565b60405160208183030381529060405290506000611a1d88601e603c61171b565b90506000611a2a896115a7565b604051602001611a3a91906135ee565b60405160208183030381529060405290508483828889868b604051602001611a68979695949392919061372e565b604051602081830303815290604052975050505050505050919050565b60408051602081019091526000808252606091908080611aa786826001612031565b1190505b6103e8821015611bef576000611ace611ac48488612ae7565b609661012c612031565b9050611adc836103e8612b13565b811115611af657611aef836103e8612b13565b9050611b39565b606481611b05856103e8612b13565b611b0f9190612b13565b1015611b395780611b22846103e8612b13565b611b2c9190612b13565b611b369082612ae7565b90505b6000611b51611b488589612ae7565b600a601e612031565b9050600083611b6b57611b6682610320612ae7565b611b77565b611b7782610320612b13565b905085611b83866115a7565b611b9b611b91600287612abd565b61169e9089612ae7565b611ba4846115a7565b611bb161169e888b612ae7565b604051602001611bc5959493929190613883565b60408051601f198184030181529190529550611be18386612ae7565b945083159350505050611aab565b6000611bff611419876004612a90565b90506000611c10876001600361171b565b9050611c29611c20886002612a90565b6002600961171b565b611c32886115a7565b611c3f896001600a61171b565b848489604051602001611c5796959493929190613941565b60405160208183030381529060405295505050505050919050565b60606000611c8d611c84846002612a90565b6001600861171b565b90506000611ca8611c9f85600a612ae7565b6000600961171b565b90506000611cba611c9f866014612ae7565b90506000611ccc611c9f87601e612ae7565b905083611cd8876115a7565b848484611cf2611ce98c6005612a90565b603c605061171b565b604051602001611d0796959493929190613d2c565b604051602081830303815290604052945050505050919050565b60606000611d3283600f6028612031565b90506016811015611d6157505060408051808201909152600681526573706172736560d01b6020820152919050565b6021811115611d8d57505060408051808201909152600581526464656e736560d81b6020820152919050565b505060408051808201909152600b81526a191a5cdd1c9a589d5d195960aa1b6020820152919050565b50919050565b600080611dd6611dcd846002612a90565b60006064612031565b90506005811015611dea5750600092915050565b600f811015611dfc5750600192915050565b6028811015611e0e5750600292915050565b6055811015611e205750600392915050565b605f811015611e325750600492915050565b50600592915050565b60606000611e4c83600a601e612031565b90506000611e5d8460016003612031565b9050601482108015611e6f5750600281105b15611e975750506040805180820190915260048152631cdbd99d60e21b602082015292915050565b601482118015611ea75750600281115b15611ed0575050604080518082019091526005815264726f636b7960d81b602082015292915050565b50506040805180820190915260068152651c9d59d9d95960d21b602082015292915050565b60606000611f10611f07846002612a90565b60026009612031565b90506004811015611f3d57505060408051808201909152600481526363616c6d60e01b6020820152919050565b6006811115611f695750506040805180820190915260058152640e4deeaced60db1b6020820152919050565b505060408051808201909152600681526563686f70707960d01b6020820152919050565b60606000611fa8611f9f846002612a90565b60016008612031565b90506003811015611fd85750506040805180820190915260078152667374726174757360c81b6020820152919050565b600681111561200657505060408051808201909152600781526663756d756c757360c81b6020820152919050565b505060408051808201909152600d81526c73747261746f63756d756c757360981b6020820152919050565b6000828211612041575081610dd6565b60008460405160200161205691815260200190565b60408051601f19818403018152919052805160209091012090508361207b8185612b13565b612086906001612ae7565b6120909083613ef4565b61209a9190612ae7565b95945050505050565b60606120ae846115a7565b6120b7846115a7565b6120c0846115a7565b6040516020016120d293929190613f08565b60405160208183030381529060405290509392505050565b6060816020015161211961210584606001516003601961171b565b845160608601516119c29161141991612ae7565b61214c61212d8560600151604b606161171b565b855160608701516119c29161214191612ae7565b61141990600a612ae7565b604051602001610ff093929190613f81565b6060816020015161216e8361230b565b612177846123c9565b604051602001610ff09392919061403a565b6060600061219f836060015160326103b661171b565b905060006121b5846060015160006101f461171b565b90506121c2828286612416565b6121cd83838761243d565b6040516020016121de9291906141b6565b60405160208183030381529060405292505050919050565b6121fe6124cb565b600061220b600184612b13565b6122159085612abd565b905061221f6124cb565b6101f460005b85811015610a355760006122398583612a90565b90506000612247838b612ae7565b612253906103e8612ae7565b905060006122648260006014612031565b9050600060326122778460006064612031565b1190508061228e576122898287612b13565b612298565b6122988287612ae7565b95506040518060400160405280858152602001878152508786603381106122c1576122c1612ad1565b6020020152508392506122d79150829050612afa565b915050612225565b606082826040516020016122f49291906141e5565b604051602081830303815290604052905092915050565b60606000600561232284606001516000600a612031565b1161234f576040518060400160405280600a81526020016974757262756c656e636560b01b815250612375565b6040518060400160405280600c81526020016b6672616374616c4e6f69736560a01b8152505b90508061238184612464565b61238e85606001516115a7565b61239f86606001516003600a61171b565b6040516020016123b29493929190614259565b604051602081830303815290604052915050919050565b60606123e2826000015183606001516114199190612ae7565b6123f383606001516005600a61171b565b6124048460600151601e606461171b565b604051602001610ff09392919061432f565b6060838361242784604001516115a7565b6020808601516040516120d29594939201614418565b6060838361244e84604001516115a7565b6020808601516040516120d295949392016144dc565b60606124a18260400151600261247a9190612a90565b61248b846060015160016003612031565b612497906103e8612a90565b61169e9190612abd565b6124ba836040015161248b856060015160026003612031565b604051602001610ff09291906145ac565b6040518061066001604052806033905b6124e36124f9565b8152602001906001900390816124db5790505090565b60405180604001604052806002906020820280368337509192915050565b6001600160e01b03198116811461252d57600080fd5b50565b60006020828403121561254257600080fd5b8135610dd681612517565b60005b83811015612568578181015183820152602001612550565b50506000910152565b6000815180845261258981602086016020860161254d565b601f01601f19169290920160200192915050565b602081526000610dd66020830184612571565b6000602082840312156125c257600080fd5b5035919050565b80356001600160a01b03811681146125e057600080fd5b919050565b600080604083850312156125f857600080fd5b612601836125c9565b946020939093013593505050565b60008060006060848603121561262457600080fd5b61262d846125c9565b925061263b602085016125c9565b9150604084013590509250925092565b6000806040838503121561265e57600080fd5b50508035926020909101359150565b6000806020838503121561268057600080fd5b823567ffffffffffffffff8082111561269857600080fd5b818501915085601f8301126126ac57600080fd5b8135818111156126bb57600080fd5b8660208260051b85010111156126d057600080fd5b60209290920196919550909350505050565b80516001600160a01b0316825260208082015167ffffffffffffffff169083015260408082015115159083015260609081015162ffffff16910152565b6020808252825182820181905260009190848201906040850190845b81811015610a355761274e8385516126e2565b928401926080929092019160010161273b565b60006020828403121561277357600080fd5b610dd6826125c9565b6020808252825182820181905260009190848201906040850190845b81811015610a3557835183529284019291840191600101612798565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156127f3576127f36127b4565b604052919050565b803562ffffff811681146125e057600080fd5b6000602080838503121561282157600080fd5b823567ffffffffffffffff8082111561283957600080fd5b818501915085601f83011261284d57600080fd5b81358181111561285f5761285f6127b4565b8060051b91506128708483016127ca565b818152918301840191848101908884111561288a57600080fd5b938501935b838510156128af576128a0856127fb565b8252938501939085019061288f565b98975050505050505050565b6000806000606084860312156128d057600080fd5b6128d9846125c9565b95602085013595506040909401359392505050565b6000806040838503121561290157600080fd5b61290a836125c9565b91506020830135801515811461291f57600080fd5b809150509250929050565b6000806000806080858703121561294057600080fd5b612949856125c9565b935060206129588187016125c9565b935060408601359250606086013567ffffffffffffffff8082111561297c57600080fd5b818801915088601f83011261299057600080fd5b8135818111156129a2576129a26127b4565b6129b4601f8201601f191685016127ca565b915080825289848285010111156129ca57600080fd5b808484018584013760008482840101525080935050505092959194509250565b608081016104a382846126e2565b60008060408385031215612a0b57600080fd5b612a14836125c9565b9150612a22602084016125c9565b90509250929050565b600060208284031215612a3d57600080fd5b610dd6826127fb565b600181811c90821680612a5a57607f821691505b602082108103611db657634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176104a3576104a3612a7a565b634e487b7160e01b600052601260045260246000fd5b600082612acc57612acc612aa7565b500490565b634e487b7160e01b600052603260045260246000fd5b808201808211156104a3576104a3612a7a565b600060018201612b0c57612b0c612a7a565b5060010190565b818103818111156104a3576104a3612a7a565b60008151612b3881856020860161254d565b9290920192915050565b7f646174613a6170706c69636174696f6e2f6a736f6e2c7b226e616d65223a22438152635753202360e01b602082015260008451612b8781602485016020890161254d565b7f3a2061207374756e6e696e6720436f736d696320576f726c64222c22646573636024918401918201527f72697074696f6e223a202268747470733a2f2f636f736d6963776f726c64732e60448201526503c3cbd1116160d51b60648201528451612bf981606a84016020890161254d565b7f2c2022696d616765223a2022646174613a696d6167652f7376672b786d6c2c00606a92909101918201528351612c3781608984016020880161254d565b61227d60f01b60899290910191820152608b0195945050505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612c8690830184612571565b9695505050505050565b600060208284031215612ca257600080fd5b8151610dd681612517565b6f0d8d2dccac2e45acee4c2c8d2cadce8560831b8152600085516020612cd98260108601838b0161254d565b6403232b396160dd1b6010928501928301528651612cfd8160158501848b0161254d565b64010181296160dd1b601593909101928301528551612d2281601a8501848a0161254d565b65010199a9296160d51b601a93909101928301528451612d478183850184890161254d565b6520313030252960d01b9201908101919091526026019695505050505050565b60008651612d79818460208b0161254d565b865190830190612d8d818360208b0161254d565b8651910190612da0818360208a0161254d565b8551910190612db381836020890161254d565b8451910190612dc681836020880161254d565b01979650505050505050565b7f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323081527f30302f737667272076696577426f783d273020302031653320316533272073746020820152753cb6329e93b130b1b5b3b937bab73216b4b6b0b3b29d60511b604082015260008451612e4f81605685016020890161254d565b61139f60f11b6056918401918201528451612e7181605884016020890161254d565b7f3c6720636c69702d706174683d2775726c28236d637029273e00000000000000605892909101918201528351612eaf81607184016020880161254d565b691e17b39f1e17b9bb339f60b11b60719290910191820152607b0195945050505050565b7f2261747472696275746573223a205b7b2274726169745f74797065223a20227381526e032b2b2111610113b30b63ab2911d1608d1b602082015260008751612f2381602f850160208c0161254d565b7f7d2c7b2274726169745f74797065223a20227374617273222c202276616c7565602f9184019182015263111d101160e11b604f8201528751612f6d816053840160208c0161254d565b7f227d2c7b2274726169745f74797065223a2022706c616e657473222c2022766160539290910191820152650363ab2911d160d51b60738201528651612fba816079840160208b0161254d565b61309f61309061308a61305261304c61301561300f6079888a01017f7d2c7b2274726169745f74797065223a20226d6f756e7461696e73222c20227681526730b63ab2911d101160c11b602082015260280190565b8d612b26565b7f227d2c7b2274726169745f74797065223a20227761746572222c202276616c7581526432911d101160d91b602082015260250190565b8a612b26565b7f227d2c7b2274726169745f74797065223a2022636c6f756473222c202276616c8152653ab2911d101160d11b602082015260260190565b87612b26565b62227d5d60e81b815260030190565b9a9950505050505050505050565b7f3c66696c7465722069643d277366273e3c666554757262756c656e636520626181526e39b2a33932b8bab2b731bc9e93981760891b6020820152600083516130fd81602f85016020880161254d565b672720736565643d2760c01b602f91840191820152835161312581603784016020880161254d565b7f272f3e3c6665436f6c6f724d61747269782076616c7565733d27302030203020603792909101918201527f39202d342030203020302039202d342030203020302039202d3420302030203060578201527f20302031272f3e3c2f66696c7465723e3c726563742077696474683d2731303060778201527f2527206865696768743d273130302527206f7061636974793d2735302527206660978201527134b63a32b91e93bab9361411b9b31493979f60711b60b782015260c901949350505050565b600085516131fa818460208a0161254d565b85519083019061320e818360208a0161254d565b855191019061322181836020890161254d565b845191019061323481836020880161254d565b019695505050505050565b6000845161325181846020890161254d565b600160fd1b908301908152845161326f81600184016020890161254d565b600b60fa1b60019290910191820152835161329181600284016020880161254d565b0160020195945050505050565b600082516132b081846020870161254d565b6e203165332c316533202d312c31653360881b920191825250600f01919050565b7f3c66696c7465722069643d276d66273e3c666554757262756c656e636520747981527f70653d276672616374616c4e6f6973652720626173654672657175656e63793d602082015263027302e360e41b60408201526000835161333c81604485016020880161254d565b7f27206e756d4f6374617665733d273135272f3e3c6665446966667573654c69676044918401918201527f6874696e67206c69676874696e672d636f6c6f723d277768697465272073757260648201526a666163655363616c653d2760a81b608482015283516133b381608f84016020880161254d565b7f273e3c666544697374616e744c6967687420617a696d7574683d273435272065608f92909101918201527f6c65766174696f6e3d273130272f3e3c2f6665446966667573654c696768746960af8201527f6e673e3c6665436f6d706f7369746520726573756c743d276d27206f7065726160cf8201527f746f723d27696e2720696e323d27536f7572636547726170686963272f3e3c6660ef8201527f65476175737369616e426c757220737464446576696174696f6e3d2738272f3e61010f8201527f3c6665436f6c6f724d617472697820747970653d276d6174726978272076616c61012f8201527f7565733d2730203020302030203020302030203020302030203020302030203061014f8201527f203020302030203020302e3520302720726573756c743d2762272f3e3c66654d61016f8201527f657267653e3c66654d657267654e6f646520696e3d276d272f3e3c66654d657261018f8201527f67654e6f646520696e3d2762272f3e3c2f66654d657267653e3c2f66696c74656101af82015261391f60f11b6101cf8201526101d101949350505050565b7f3c646566733e3c6c696e6561724772616469656e742069643d276d67273e000081526000845161358a81601e85016020890161254d565b8451908301906135a181601e84016020890161254d565b84519101906135b781601e84016020880161254d565b7f3c2f6c696e6561724772616469656e743e3c2f646566733e0000000000000000601e929091019182015260360195945050505050565b7f3c66696c7465722069643d276d7366273e3c666554757262756c656e6365207481527f7970653d276672616374616c4e6f6973652720626173654672657175656e637960208201527f3d27302e30303420302e303127206e756d4f6374617665733d27322720736565604082015262643d2760e81b60608201526000825161367e81606385016020870161254d565b7f272f3e3c6665436f6c6f724d61747269782076616c7565733d2730203120302060639390910192830152507f30202d342031203120302030202d342031203020302030202d3420302031203160838201527f2030202d31272f3e3c6665436f6d706f73697465206f70657261746f723d276960a38201527f6e2720696e323d27536f7572636547726170686963272f3e3c2f66696c74657260c3820152601f60f91b60e382015260e401919050565b6000885160206137418285838e0161254d565b8951918401916137548184848e0161254d565b89519201916137668184848d0161254d565b703c706f6c79676f6e20706f696e74733d2760781b920191825287516137928160118501848c0161254d565b7f272066696c7465723d2775726c28236d6629272f3e3c706f6c79676f6e20706f6011939091019283015265696e74733d2760d01b603183015286516137de8160378501848b0161254d565b7f272066696c6c3d2775726c28236d672927206f7061636974793d27000000000060379390910192830152855161381b8160528501848a0161254d565b61387361385161384b6052848701017425272f3e3c706f6c79676f6e20706f696e74733d2760581b815260150190565b88612b26565b7513903334b63a32b91e93bab9361411b6b9b31493979f60511b815260160190565b9c9b505050505050505050505050565b60008651613895818460208b0161254d565b61021960f51b90830190815286516138b4816002840160208b0161254d565b650101c181816160d51b6002929091019182015285516138db816008840160208a0161254d565b600160fd1b6008929091019182015284516138fd81600984016020890161254d565b61016160f51b60099290910191820152835161392081600b84016020880161254d565b640101c1818160dd1b600b9290910191820152601001979650505050505050565b7f3c66696c7465722069643d277766273e3c666554757262756c656e6365206261815270073654672657175656e63793d27302e303607c1b602082015260008751613993816031850160208c0161254d565b7f202e313127206e756d4f6374617665733d27342720736565643d27000000000060319184019182015287516139d081604c840160208c0161254d565b7f272f3e3c6665436f6d706f6e656e745472616e7366657220726573756c743d27604c92909101918201527f77617665273e3c666546756e635220747970653d276c696e6561722720736c6f606c8201527f70653d27302e312720696e746572636570743d272d302e3035272f3e3c666546608c8201527f756e634720747970653d2767616d6d612720616d706c69747564653d27302e3760ac8201527f3527206578706f6e656e743d27302e3627206f66667365743d27302e3035272f60cc8201527f3e3c666546756e634220747970653d2767616d6d612720616d706c697475646560ec8201527f3d27302e3827206578706f6e656e743d27302e3427206f66667365743d27302e61010c8201527f3035272f3e3c666546756e634120747970653d276c696e6561722720736c6f7061012c82015262653d2760e81b61014c820152613d1f613cd0613cca613c09613c03613b7e613b78613b3761014f89018f612b26565b7f272f3e3c2f6665436f6d706f6e656e745472616e736665723e3c6665466c6f6f81526e6420666c6f6f642d636f6c6f723d2760881b6020820152602f0190565b8c612b26565b7f272f3e3c6665436f6d706f7369746520696e3d2777617665272f3e3c6665436f81527f6d706f7369746520696e323d27536f75726365416c70686127206f706572617460208201527f6f723d27696e272f3e3c6665476175737369616e426c757220737464446576696040820152666174696f6e3d2760c81b606082015260670190565b89612b26565b7f2720726573756c743d27676c6f77272f3e3c6665436f6d706f7369746520696e81527f323d27676c6f7727206f70657261746f723d2761746f702720726573756c743d60208201527f276727202f3e3c66654d657267653e3c66654d657267654e6f64652f3e3c666560408201527f4d657267654e6f64652f3e3c2f66654d657267653e3c2f66696c7465723e3c7060608201527f61746820643d274d203020316533204c20302038303020000000000000000000608082015260970190565b86612b26565b7f204c2031653320383030204c2031653320316533272066696c7465723d27757281527f6c2823776629272066696c6c2d6f7061636974793d27373025272f3e000000006020820152603c0190565b9998505050505050505050565b6f1e3334b63a32b91034b21e93b1b3139f60811b81527f3c666554757262756c656e636520747970653d276672616374616c4e6f69736560108201527402720626173654672657175656e63793d27302e303605c1b603082015260008751613d9b816045850160208c0161254d565b7f20302e303227206e756d4f6374617665733d27322720736565643d27000000006045918401918201528751613dd8816061840160208c0161254d565b7f272f3e3c6665436f6c6f724d617472697820747970653d276d61747269782720606192909101918201526f3b30b63ab2b99e93981018101810181760811b60818201528651613e2f816091840160208b0161254d565b61309f613ed261308a613e7861304c613e6161300f6091888a01016a101810181018101810181760a91b8152600b0190565b6a101810181018101810181760a91b8152600b0190565b7f203020302030203020312030272f3e3c2f66696c7465723e3c7265637420776981527f6474683d273130302527206865696768743d273130302527206f7061636974796020820152613d2760f01b604082015260420190565b751293903334b63a32b91e93bab9361411b1b31493979f60511b815260160190565b600082613f0357613f03612aa7565b500690565b630e4cec4560e31b815260008451613f2781600485016020890161254d565b808301905061016160f51b8060048301528551613f4b816006850160208a0161254d565b60069201918201528351613f6681600884016020880161254d565b602960f81b6008929091019182015260090195945050505050565b7f3c646566733e3c72616469616c4772616469656e742069643d27706700000000815260008451613fb981601c85016020890161254d565b731390333c1e939a98129390333c9e939a9812939f60611b601c918401918201528451613fed81603084016020890161254d565b845191019061400381603084016020880161254d565b7f3c2f72616469616c4772616469656e743e3c2f646566733e00000000000000006030929091019182015260480195945050505050565b6d1e3334b63a32b91034b21e93b83360911b81526000845161406381600e85016020890161254d565b7f2720783d272d3235252720793d272d323525272077696474683d273135302527600e918401918201526e103432b4b3b43a1e93989a9812939f60891b602e82015284516140b881603d84016020890161254d565b84519101906140ce81603d84016020880161254d565b7f3c6665436f6d706f7369746520726573756c743d277027206f70657261746f72603d92909101918201527f3d27696e2720696e323d27536f7572636547726170686963272f3e3c66654761605d8201527f75737369616e426c757220737464446576696174696f6e3d2738272072657375607d8201527f6c743d276362272f3e3c66654d657267653e3c66654d657267654e6f64652069609d8201527f6e3d276362272f3e3c66654d657267654e6f646520696e3d2770272f3e3c2f6660bd8201526f32a6b2b933b29f1e17b334b63a32b91f60811b60dd82015260ed0195945050505050565b600083516141c881846020880161254d565b8351908301906141dc81836020880161254d565b01949350505050565b6d3c73746f70206f66667365743d2760901b81526000835161420e81600e85016020880161254d565b6e25272073746f702d636f6c6f723d2760881b600e91840191820152835161423d81601d84016020880161254d565b6213979f60e91b601d9290910191820152602001949350505050565b733c666554757262756c656e636520747970653d2760601b815260008551614288816014850160208a0161254d565b702720626173654672657175656e63793d2760781b60149184019182015285516142b9816025840160208a0161254d565b672720736565643d2760c01b6025929091019182015284516142e281602d84016020890161254d565b6d27206e756d4f6374617665733d2760901b602d9290910191820152835161431181603b84016020880161254d565b6213979f60e91b603b9290910191820152603e019695505050505050565b7f3c6665446966667573654c69676874696e67206c69676874696e672d636f6c6f815262723d2760e81b60208201526000845161437381602385016020890161254d565b6f2720737572666163655363616c653d2760801b60239184019182015284516143a381603384016020890161254d565b7f273e3c666544697374616e744c6967687420656c65766174696f6e3d270000006033929091019182015283516143e181605084016020880161254d565b7f272f3e3c2f6665446966667573654c69676874696e673e0000000000000000006050929091019182015260670195945050505050565b6b3c636972636c652063783d2760a01b81526000855161443f81600c850160208a0161254d565b65272063793d2760d01b600c918401918201528551614465816012840160208a0161254d565b642720723d2760d81b60129290910191820152845161448b81601784016020890161254d565b7013903334b63a32b91e93bab9361411b83360791b6017929091019182015283516144bd81602884016020880161254d565b631493979f60e11b60289290910191820152602c019695505050505050565b6b3c636972636c652063783d2760a01b81526000855161450381600c850160208a0161254d565b65272063793d2760d01b600c918401918201528551614529816012840160208a0161254d565b642720723d2760d81b60129290910191820152845161454f81601784016020890161254d565b6e272066696c6c3d2775726c2823706760881b60179290910191820152835161457f81602684016020880161254d565b7114939037b830b1b4ba3c9e939a181293979f60711b602692909101918201526038019695505050505050565b630302e30360e41b8152600083516145cb81600485016020880161254d565b63020302e360e41b60049184019182015283516145ef81600884016020880161254d565b0160080194935050505056fe68747470733a2f2f7777772e636f736d6963776f726c64732e78797a2f73746f726566726f6e742d6d65746164617461a26469706673582212207fcd02845f4259497a863952fae1e71d2784946fdb2e35becf294d6500c15f0b64736f6c63430008110033

Deployed Bytecode

0x60806040526004361061014b5760003560e01c80638462151c116100b6578063bc921dc21161006f578063bc921dc2146103ba578063c23dc68f146103da578063c87b56dd14610407578063e8a3d48514610427578063e985e9c51461043c578063eaef4d8f1461048557600080fd5b80638462151c146103125780639197898f1461033f57806395d89b411461035257806399a2557a14610367578063a22cb46514610387578063b88d4fde146103a757600080fd5b806323b872dd1161010857806323b872dd146102405780632a55205a1461025357806342842e0e146102925780635bbb2177146102a55780636352211e146102d257806370a08231146102f257600080fd5b806301ffc9a714610150578063031bd4c41461018557806306fdde03146101ae578063081812fc146101d0578063095ea7b31461020857806318160ddd1461021d575b600080fd5b34801561015c57600080fd5b5061017061016b366004612530565b610498565b60405190151581526020015b60405180910390f35b34801561019157600080fd5b5061019b61020081565b60405161ffff909116815260200161017c565b3480156101ba57600080fd5b506101c36104a9565b60405161017c919061259d565b3480156101dc57600080fd5b506101f06101eb3660046125b0565b61053b565b6040516001600160a01b03909116815260200161017c565b61021b6102163660046125e5565b61057f565b005b34801561022957600080fd5b50600154600054035b60405190815260200161017c565b61021b61024e36600461260f565b61061f565b34801561025f57600080fd5b5061027361026e36600461264b565b6107b7565b604080516001600160a01b03909316835260208301919091520161017c565b61021b6102a036600461260f565b6107f2565b3480156102b157600080fd5b506102c56102c036600461266d565b610812565b60405161017c919061271f565b3480156102de57600080fd5b506101f06102ed3660046125b0565b6108de565b3480156102fe57600080fd5b5061023261030d366004612761565b6108e9565b34801561031e57600080fd5b5061033261032d366004612761565b610938565b60405161017c919061277c565b61021b61034d36600461280e565b610a41565b34801561035e57600080fd5b506101c3610c54565b34801561037357600080fd5b506103326103823660046128bb565b610c63565b34801561039357600080fd5b5061021b6103a23660046128ee565b610ddd565b61021b6103b536600461292a565b610e49565b3480156103c657600080fd5b506101c36103d53660046125b0565b610e8d565b3480156103e657600080fd5b506103fa6103f53660046125b0565b610ef7565b60405161017c91906129ea565b34801561041357600080fd5b506101c36104223660046125b0565b610f6f565b34801561043357600080fd5b506101c3611006565b34801561044857600080fd5b506101706104573660046129f8565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b61021b610493366004612a2b565b611026565b60006104a382611111565b92915050565b6060600280546104b890612a46565b80601f01602080910402602001604051908101604052809291908181526020018280546104e490612a46565b80156105315780601f1061050657610100808354040283529160200191610531565b820191906000526020600020905b81548152906001019060200180831161051457829003601f168201915b5050505050905090565b600061054682611146565b610563576040516333d1c03960e21b815260040160405180910390fd5b506000908152600660205260409020546001600160a01b031690565b600061058a826108de565b9050336001600160a01b038216146105c3576105a68133610457565b6105c3576040516367d9dca160e11b815260040160405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600061062a8261116d565b9050836001600160a01b0316816001600160a01b03161461065d5760405162a1148160e81b815260040160405180910390fd5b60008281526006602052604090208054338082146001600160a01b038816909114176106aa5761068d8633610457565b6106aa57604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b0385166106d157604051633a954ecd60e21b815260040160405180910390fd5b80156106dc57600082555b6001600160a01b038681166000908152600560205260408082208054600019019055918716808252919020805460010190554260a01b17600160e11b17600085815260046020526040812091909155600160e11b8416900361076e5760018401600081815260046020526040812054900361076c57600054811461076c5760008181526004602052604090208490555b505b83856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050505050565b600080738c0e2ac43de845116e6c70319c4b6db9463399c86127106107dd8560fa612a90565b6107e79190612abd565b915091509250929050565b61080d83838360405180602001604052806000815250610e49565b505050565b60608160008167ffffffffffffffff811115610830576108306127b4565b60405190808252806020026020018201604052801561088257816020015b60408051608081018252600080825260208083018290529282018190526060820152825260001990920191018161084e5790505b50905060005b8281146108d5576108b08686838181106108a4576108a4612ad1565b90506020020135610ef7565b8282815181106108c2576108c2612ad1565b6020908102919091010152600101610888565b50949350505050565b60006104a38261116d565b60006001600160a01b038216610912576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b031660009081526005602052604090205467ffffffffffffffff1690565b60606000806000610948856108e9565b905060008167ffffffffffffffff811115610965576109656127b4565b60405190808252806020026020018201604052801561098e578160200160208202803683370190505b5090506109bb60408051608081018252600080825260208201819052918101829052606081019190915290565b60005b838614610a35576109ce816111d4565b91508160400151610a2d5781516001600160a01b0316156109ee57815194505b876001600160a01b0316856001600160a01b031603610a2d5780838780600101985081518110610a2057610a20612ad1565b6020026020010181815250505b6001016109be565b50909695505050505050565b610200610a4d60005490565b1115610a925760405162461bcd60e51b815260206004820152600f60248201526e1513d2d15397d31253525517d21255608a1b60448201526064015b60405180910390fd5b6000805b8251811015610b535760096000848381518110610ab557610ab5612ad1565b60209081029190910181015162ffffff16825281019190915260400160009081205460ff1615159003610af457610aed826001612ae7565b9150610b18565b828181518110610b0657610b06612ad1565b60200260200101600062ffffff168152505b61020082610b2560005490565b610b2f9190612ae7565b101580610b3d5750600a8210155b610b535780610b4b81612afa565b915050610a96565b50600054610b613383611210565b60005b8215610c4e576000610b768284612ae7565b9050848281518110610b8a57610b8a612ad1565b602002602001015162ffffff16600014610c3b57848281518110610bb057610bb0612ad1565b60200260200101516008600083815260200190815260200160002060006101000a81548162ffffff021916908362ffffff160217905550600160096000878581518110610bff57610bff612ad1565b60209081029190910181015162ffffff168252810191909152604001600020805460ff1916911515919091179055610c38600185612b13565b93505b610c46826001612ae7565b915050610b64565b50505050565b6060600380546104b890612a46565b6060818310610c8557604051631960ccad60e11b815260040160405180910390fd5b600080610c9160005490565b905080841115610c9f578093505b6000610caa876108e9565b905084861015610cc95785850381811015610cc3578091505b50610ccd565b5060005b60008167ffffffffffffffff811115610ce857610ce86127b4565b604051908082528060200260200182016040528015610d11578160200160208202803683370190505b50905081600003610d27579350610dd692505050565b6000610d3288610ef7565b905060008160400151610d43575080515b885b888114158015610d555750848714155b15610dca57610d63816111d4565b92508260400151610dc25782516001600160a01b031615610d8357825191505b8a6001600160a01b0316826001600160a01b031603610dc25780848880600101995081518110610db557610db5612ad1565b6020026020010181815250505b600101610d45565b50505092835250909150505b9392505050565b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610e5484848461061f565b6001600160a01b0383163b15610c4e57610e708484848461130e565b610c4e576040516368d2bf6b60e11b815260040160405180910390fd5b6060610e9882611146565b8015610ea5575061020082105b610eda5760405162461bcd60e51b815260206004820152600660248201526510905117d25160d21b6044820152606401610a89565b6000828152600860205260409020546104a39062ffffff166113f9565b6040805160808082018352600080835260208084018290528385018290526060808501839052855193840186528284529083018290529382018190529281018390529091506000548310610f4b5792915050565b610f54836111d4565b9050806040015115610f665792915050565b610dd683611572565b6060610f7a82611146565b610faf5760405162461bcd60e51b815260206004820152600660248201526510905117d25160d21b6044820152606401610a89565b610fb8826115a7565b600083815260086020526040902054610fd59062ffffff1661167e565b610fde84610e8d565b604051602001610ff093929190612b42565b6040516020818303038152906040529050919050565b60606040518060600160405280603081526020016145fc60309139905090565b61020061103260005490565b11156110725760405162461bcd60e51b815260206004820152600f60248201526e1513d2d15397d31253525517d21255608a1b6044820152606401610a89565b62ffffff811660009081526009602052604090205460ff16156110c35760405162461bcd60e51b815260206004820152600960248201526814d1515117d554d15160ba1b6044820152606401610a89565b60008054808252600860209081526040808420805462ffffff191662ffffff871690811790915584526009909152909120805460ff1916600190811790915561110d903390611210565b5050565b60006001600160e01b0319821663152a902d60e11b14806104a357506301ffc9a760e01b6001600160e01b03198316146104a3565b60008054821080156104a3575050600090815260046020526040902054600160e01b161590565b6000816000548110156111bb5760008181526004602052604081205490600160e01b821690036111b9575b80600003610dd6575060001901600081815260046020526040902054611198565b505b604051636f96cda160e11b815260040160405180910390fd5b6040805160808101825260008082526020820181905291810182905260608101919091526000828152600460205260409020546104a3906116d3565b60008054908290036112355760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b03831660008181526005602090815260408083208054680100000000000000018802019055848352600490915281206001851460e11b4260a01b178317905582840190839083907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4600183015b8181146112e457808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a46001016112ac565b508160000361130557604051622e076360e81b815260040160405180910390fd5b60005550505050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290611343903390899088908890600401612c53565b6020604051808303816000875af192505050801561137e575060408051601f3d908101601f1916820190925261137b91810190612c90565b60015b6113dc573d8080156113ac576040519150601f19603f3d011682016040523d82523d6000602084013e6113b1565b606091505b5080516000036113d4576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b6060600061140b83600061016861171b565b61141e611419856001612ae7565b611733565b61142c611419866002612ae7565b61143a611419876003612ae7565b60405160200161144d9493929190612cad565b604051602081830303815290604052905060006040516020016114df907f3c646566733e3c636c6970506174682069643d276d6370273e3c72656374207881527f3d27302720793d2730272077696474683d2731653327206865696768743d273160208201527f6533272f3e3c2f636c6970506174683e3c2f646566733e000000000000000000604082015260570190565b604051602081830303815290604052905060006114fb8561176f565b61150486611798565b61150d8761187a565b61151688611a85565b61151f89611c72565b604051602001611533959493929190612d67565b604051602081830303815290604052905082828260405160200161155993929190612dd2565b6040516020818303038152906040529350505050919050565b6040805160808101825260008082526020820181905291810182905260608101919091526104a36115a28361116d565b6116d3565b6060816000036115ce5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156115e657600101600a820491506115d2565b60008167ffffffffffffffff811115611601576116016127b4565b6040519080825280601f01601f19166020018201604052801561162b576020820181803683370190505b508593509050815b83156108d557600a840660300160f81b8282600190039250828151811061165c5761165c612ad1565b60200101906001600160f81b031916908160001a905350600a84049350611633565b6060611689826115a7565b61169283611d21565b6116a361169e85611dbc565b6115a7565b6116ac85611e3b565b6116b586611ef5565b6116be87611f8d565b604051602001610ff096959493929190612ed3565b604080516080810182526001600160a01b038316815260a083901c67ffffffffffffffff166020820152600160e01b831615159181019190915260e89190911c606082015290565b606061172b61169e858585612031565b949350505050565b60606104a361174583600060ff612031565b61175c611753856002612ae7565b600060ff612031565b61176a611753866001612ae7565b6120a3565b606061177e82600f602861171b565b611787836115a7565b604051602001610ff09291906130ad565b60408051602081019091526000808252606091905b6117b684611dbc565b81101561187357600060405180608001604052808381526020016117d9846115a7565b8152602001611800846117ed896002612a90565b6117f79190612ae7565b601460c8612031565b815260200183611811886002612a90565b61181b9190612ae7565b9052905082611829826120ea565b6118328361215e565b61183b84612189565b60405160200161184e94939291906131e8565b604051602081830303815290604052925050808061186b90612afa565b9150506117ad565b5092915050565b6060600061188c836103e860336121f6565b9050606060005b603381101561190b5760008382603381106118b0576118b0612ad1565b60200201519050826118c98260005b60200201516115a7565b6118d48360016118bf565b6040516020016118e69392919061323f565b604051602081830303815290604052925050808061190390612afa565b915050611893565b508060405160200161191d919061329e565b6040516020818303038152906040529050600061193d85600a601e61171b565b61194a866001600361171b565b60405160200161195b9291906132d1565b60408051601f198184030181529190529050600061197d611419876003612ae7565b905060006119a4604051806040016040528060018152602001603560f81b815250836122df565b6119c76119b4896014605061171b565b6119c26114198b6005612ae7565b6122df565b6119eb60405180604001604052806002815260200161393560f01b815250856122df565b6040516020016119fd93929190613552565b60405160208183030381529060405290506000611a1d88601e603c61171b565b90506000611a2a896115a7565b604051602001611a3a91906135ee565b60405160208183030381529060405290508483828889868b604051602001611a68979695949392919061372e565b604051602081830303815290604052975050505050505050919050565b60408051602081019091526000808252606091908080611aa786826001612031565b1190505b6103e8821015611bef576000611ace611ac48488612ae7565b609661012c612031565b9050611adc836103e8612b13565b811115611af657611aef836103e8612b13565b9050611b39565b606481611b05856103e8612b13565b611b0f9190612b13565b1015611b395780611b22846103e8612b13565b611b2c9190612b13565b611b369082612ae7565b90505b6000611b51611b488589612ae7565b600a601e612031565b9050600083611b6b57611b6682610320612ae7565b611b77565b611b7782610320612b13565b905085611b83866115a7565b611b9b611b91600287612abd565b61169e9089612ae7565b611ba4846115a7565b611bb161169e888b612ae7565b604051602001611bc5959493929190613883565b60408051601f198184030181529190529550611be18386612ae7565b945083159350505050611aab565b6000611bff611419876004612a90565b90506000611c10876001600361171b565b9050611c29611c20886002612a90565b6002600961171b565b611c32886115a7565b611c3f896001600a61171b565b848489604051602001611c5796959493929190613941565b60405160208183030381529060405295505050505050919050565b60606000611c8d611c84846002612a90565b6001600861171b565b90506000611ca8611c9f85600a612ae7565b6000600961171b565b90506000611cba611c9f866014612ae7565b90506000611ccc611c9f87601e612ae7565b905083611cd8876115a7565b848484611cf2611ce98c6005612a90565b603c605061171b565b604051602001611d0796959493929190613d2c565b604051602081830303815290604052945050505050919050565b60606000611d3283600f6028612031565b90506016811015611d6157505060408051808201909152600681526573706172736560d01b6020820152919050565b6021811115611d8d57505060408051808201909152600581526464656e736560d81b6020820152919050565b505060408051808201909152600b81526a191a5cdd1c9a589d5d195960aa1b6020820152919050565b50919050565b600080611dd6611dcd846002612a90565b60006064612031565b90506005811015611dea5750600092915050565b600f811015611dfc5750600192915050565b6028811015611e0e5750600292915050565b6055811015611e205750600392915050565b605f811015611e325750600492915050565b50600592915050565b60606000611e4c83600a601e612031565b90506000611e5d8460016003612031565b9050601482108015611e6f5750600281105b15611e975750506040805180820190915260048152631cdbd99d60e21b602082015292915050565b601482118015611ea75750600281115b15611ed0575050604080518082019091526005815264726f636b7960d81b602082015292915050565b50506040805180820190915260068152651c9d59d9d95960d21b602082015292915050565b60606000611f10611f07846002612a90565b60026009612031565b90506004811015611f3d57505060408051808201909152600481526363616c6d60e01b6020820152919050565b6006811115611f695750506040805180820190915260058152640e4deeaced60db1b6020820152919050565b505060408051808201909152600681526563686f70707960d01b6020820152919050565b60606000611fa8611f9f846002612a90565b60016008612031565b90506003811015611fd85750506040805180820190915260078152667374726174757360c81b6020820152919050565b600681111561200657505060408051808201909152600781526663756d756c757360c81b6020820152919050565b505060408051808201909152600d81526c73747261746f63756d756c757360981b6020820152919050565b6000828211612041575081610dd6565b60008460405160200161205691815260200190565b60408051601f19818403018152919052805160209091012090508361207b8185612b13565b612086906001612ae7565b6120909083613ef4565b61209a9190612ae7565b95945050505050565b60606120ae846115a7565b6120b7846115a7565b6120c0846115a7565b6040516020016120d293929190613f08565b60405160208183030381529060405290509392505050565b6060816020015161211961210584606001516003601961171b565b845160608601516119c29161141991612ae7565b61214c61212d8560600151604b606161171b565b855160608701516119c29161214191612ae7565b61141990600a612ae7565b604051602001610ff093929190613f81565b6060816020015161216e8361230b565b612177846123c9565b604051602001610ff09392919061403a565b6060600061219f836060015160326103b661171b565b905060006121b5846060015160006101f461171b565b90506121c2828286612416565b6121cd83838761243d565b6040516020016121de9291906141b6565b60405160208183030381529060405292505050919050565b6121fe6124cb565b600061220b600184612b13565b6122159085612abd565b905061221f6124cb565b6101f460005b85811015610a355760006122398583612a90565b90506000612247838b612ae7565b612253906103e8612ae7565b905060006122648260006014612031565b9050600060326122778460006064612031565b1190508061228e576122898287612b13565b612298565b6122988287612ae7565b95506040518060400160405280858152602001878152508786603381106122c1576122c1612ad1565b6020020152508392506122d79150829050612afa565b915050612225565b606082826040516020016122f49291906141e5565b604051602081830303815290604052905092915050565b60606000600561232284606001516000600a612031565b1161234f576040518060400160405280600a81526020016974757262756c656e636560b01b815250612375565b6040518060400160405280600c81526020016b6672616374616c4e6f69736560a01b8152505b90508061238184612464565b61238e85606001516115a7565b61239f86606001516003600a61171b565b6040516020016123b29493929190614259565b604051602081830303815290604052915050919050565b60606123e2826000015183606001516114199190612ae7565b6123f383606001516005600a61171b565b6124048460600151601e606461171b565b604051602001610ff09392919061432f565b6060838361242784604001516115a7565b6020808601516040516120d29594939201614418565b6060838361244e84604001516115a7565b6020808601516040516120d295949392016144dc565b60606124a18260400151600261247a9190612a90565b61248b846060015160016003612031565b612497906103e8612a90565b61169e9190612abd565b6124ba836040015161248b856060015160026003612031565b604051602001610ff09291906145ac565b6040518061066001604052806033905b6124e36124f9565b8152602001906001900390816124db5790505090565b60405180604001604052806002906020820280368337509192915050565b6001600160e01b03198116811461252d57600080fd5b50565b60006020828403121561254257600080fd5b8135610dd681612517565b60005b83811015612568578181015183820152602001612550565b50506000910152565b6000815180845261258981602086016020860161254d565b601f01601f19169290920160200192915050565b602081526000610dd66020830184612571565b6000602082840312156125c257600080fd5b5035919050565b80356001600160a01b03811681146125e057600080fd5b919050565b600080604083850312156125f857600080fd5b612601836125c9565b946020939093013593505050565b60008060006060848603121561262457600080fd5b61262d846125c9565b925061263b602085016125c9565b9150604084013590509250925092565b6000806040838503121561265e57600080fd5b50508035926020909101359150565b6000806020838503121561268057600080fd5b823567ffffffffffffffff8082111561269857600080fd5b818501915085601f8301126126ac57600080fd5b8135818111156126bb57600080fd5b8660208260051b85010111156126d057600080fd5b60209290920196919550909350505050565b80516001600160a01b0316825260208082015167ffffffffffffffff169083015260408082015115159083015260609081015162ffffff16910152565b6020808252825182820181905260009190848201906040850190845b81811015610a355761274e8385516126e2565b928401926080929092019160010161273b565b60006020828403121561277357600080fd5b610dd6826125c9565b6020808252825182820181905260009190848201906040850190845b81811015610a3557835183529284019291840191600101612798565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156127f3576127f36127b4565b604052919050565b803562ffffff811681146125e057600080fd5b6000602080838503121561282157600080fd5b823567ffffffffffffffff8082111561283957600080fd5b818501915085601f83011261284d57600080fd5b81358181111561285f5761285f6127b4565b8060051b91506128708483016127ca565b818152918301840191848101908884111561288a57600080fd5b938501935b838510156128af576128a0856127fb565b8252938501939085019061288f565b98975050505050505050565b6000806000606084860312156128d057600080fd5b6128d9846125c9565b95602085013595506040909401359392505050565b6000806040838503121561290157600080fd5b61290a836125c9565b91506020830135801515811461291f57600080fd5b809150509250929050565b6000806000806080858703121561294057600080fd5b612949856125c9565b935060206129588187016125c9565b935060408601359250606086013567ffffffffffffffff8082111561297c57600080fd5b818801915088601f83011261299057600080fd5b8135818111156129a2576129a26127b4565b6129b4601f8201601f191685016127ca565b915080825289848285010111156129ca57600080fd5b808484018584013760008482840101525080935050505092959194509250565b608081016104a382846126e2565b60008060408385031215612a0b57600080fd5b612a14836125c9565b9150612a22602084016125c9565b90509250929050565b600060208284031215612a3d57600080fd5b610dd6826127fb565b600181811c90821680612a5a57607f821691505b602082108103611db657634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176104a3576104a3612a7a565b634e487b7160e01b600052601260045260246000fd5b600082612acc57612acc612aa7565b500490565b634e487b7160e01b600052603260045260246000fd5b808201808211156104a3576104a3612a7a565b600060018201612b0c57612b0c612a7a565b5060010190565b818103818111156104a3576104a3612a7a565b60008151612b3881856020860161254d565b9290920192915050565b7f646174613a6170706c69636174696f6e2f6a736f6e2c7b226e616d65223a22438152635753202360e01b602082015260008451612b8781602485016020890161254d565b7f3a2061207374756e6e696e6720436f736d696320576f726c64222c22646573636024918401918201527f72697074696f6e223a202268747470733a2f2f636f736d6963776f726c64732e60448201526503c3cbd1116160d51b60648201528451612bf981606a84016020890161254d565b7f2c2022696d616765223a2022646174613a696d6167652f7376672b786d6c2c00606a92909101918201528351612c3781608984016020880161254d565b61227d60f01b60899290910191820152608b0195945050505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612c8690830184612571565b9695505050505050565b600060208284031215612ca257600080fd5b8151610dd681612517565b6f0d8d2dccac2e45acee4c2c8d2cadce8560831b8152600085516020612cd98260108601838b0161254d565b6403232b396160dd1b6010928501928301528651612cfd8160158501848b0161254d565b64010181296160dd1b601593909101928301528551612d2281601a8501848a0161254d565b65010199a9296160d51b601a93909101928301528451612d478183850184890161254d565b6520313030252960d01b9201908101919091526026019695505050505050565b60008651612d79818460208b0161254d565b865190830190612d8d818360208b0161254d565b8651910190612da0818360208a0161254d565b8551910190612db381836020890161254d565b8451910190612dc681836020880161254d565b01979650505050505050565b7f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323081527f30302f737667272076696577426f783d273020302031653320316533272073746020820152753cb6329e93b130b1b5b3b937bab73216b4b6b0b3b29d60511b604082015260008451612e4f81605685016020890161254d565b61139f60f11b6056918401918201528451612e7181605884016020890161254d565b7f3c6720636c69702d706174683d2775726c28236d637029273e00000000000000605892909101918201528351612eaf81607184016020880161254d565b691e17b39f1e17b9bb339f60b11b60719290910191820152607b0195945050505050565b7f2261747472696275746573223a205b7b2274726169745f74797065223a20227381526e032b2b2111610113b30b63ab2911d1608d1b602082015260008751612f2381602f850160208c0161254d565b7f7d2c7b2274726169745f74797065223a20227374617273222c202276616c7565602f9184019182015263111d101160e11b604f8201528751612f6d816053840160208c0161254d565b7f227d2c7b2274726169745f74797065223a2022706c616e657473222c2022766160539290910191820152650363ab2911d160d51b60738201528651612fba816079840160208b0161254d565b61309f61309061308a61305261304c61301561300f6079888a01017f7d2c7b2274726169745f74797065223a20226d6f756e7461696e73222c20227681526730b63ab2911d101160c11b602082015260280190565b8d612b26565b7f227d2c7b2274726169745f74797065223a20227761746572222c202276616c7581526432911d101160d91b602082015260250190565b8a612b26565b7f227d2c7b2274726169745f74797065223a2022636c6f756473222c202276616c8152653ab2911d101160d11b602082015260260190565b87612b26565b62227d5d60e81b815260030190565b9a9950505050505050505050565b7f3c66696c7465722069643d277366273e3c666554757262756c656e636520626181526e39b2a33932b8bab2b731bc9e93981760891b6020820152600083516130fd81602f85016020880161254d565b672720736565643d2760c01b602f91840191820152835161312581603784016020880161254d565b7f272f3e3c6665436f6c6f724d61747269782076616c7565733d27302030203020603792909101918201527f39202d342030203020302039202d342030203020302039202d3420302030203060578201527f20302031272f3e3c2f66696c7465723e3c726563742077696474683d2731303060778201527f2527206865696768743d273130302527206f7061636974793d2735302527206660978201527134b63a32b91e93bab9361411b9b31493979f60711b60b782015260c901949350505050565b600085516131fa818460208a0161254d565b85519083019061320e818360208a0161254d565b855191019061322181836020890161254d565b845191019061323481836020880161254d565b019695505050505050565b6000845161325181846020890161254d565b600160fd1b908301908152845161326f81600184016020890161254d565b600b60fa1b60019290910191820152835161329181600284016020880161254d565b0160020195945050505050565b600082516132b081846020870161254d565b6e203165332c316533202d312c31653360881b920191825250600f01919050565b7f3c66696c7465722069643d276d66273e3c666554757262756c656e636520747981527f70653d276672616374616c4e6f6973652720626173654672657175656e63793d602082015263027302e360e41b60408201526000835161333c81604485016020880161254d565b7f27206e756d4f6374617665733d273135272f3e3c6665446966667573654c69676044918401918201527f6874696e67206c69676874696e672d636f6c6f723d277768697465272073757260648201526a666163655363616c653d2760a81b608482015283516133b381608f84016020880161254d565b7f273e3c666544697374616e744c6967687420617a696d7574683d273435272065608f92909101918201527f6c65766174696f6e3d273130272f3e3c2f6665446966667573654c696768746960af8201527f6e673e3c6665436f6d706f7369746520726573756c743d276d27206f7065726160cf8201527f746f723d27696e2720696e323d27536f7572636547726170686963272f3e3c6660ef8201527f65476175737369616e426c757220737464446576696174696f6e3d2738272f3e61010f8201527f3c6665436f6c6f724d617472697820747970653d276d6174726978272076616c61012f8201527f7565733d2730203020302030203020302030203020302030203020302030203061014f8201527f203020302030203020302e3520302720726573756c743d2762272f3e3c66654d61016f8201527f657267653e3c66654d657267654e6f646520696e3d276d272f3e3c66654d657261018f8201527f67654e6f646520696e3d2762272f3e3c2f66654d657267653e3c2f66696c74656101af82015261391f60f11b6101cf8201526101d101949350505050565b7f3c646566733e3c6c696e6561724772616469656e742069643d276d67273e000081526000845161358a81601e85016020890161254d565b8451908301906135a181601e84016020890161254d565b84519101906135b781601e84016020880161254d565b7f3c2f6c696e6561724772616469656e743e3c2f646566733e0000000000000000601e929091019182015260360195945050505050565b7f3c66696c7465722069643d276d7366273e3c666554757262756c656e6365207481527f7970653d276672616374616c4e6f6973652720626173654672657175656e637960208201527f3d27302e30303420302e303127206e756d4f6374617665733d27322720736565604082015262643d2760e81b60608201526000825161367e81606385016020870161254d565b7f272f3e3c6665436f6c6f724d61747269782076616c7565733d2730203120302060639390910192830152507f30202d342031203120302030202d342031203020302030202d3420302031203160838201527f2030202d31272f3e3c6665436f6d706f73697465206f70657261746f723d276960a38201527f6e2720696e323d27536f7572636547726170686963272f3e3c2f66696c74657260c3820152601f60f91b60e382015260e401919050565b6000885160206137418285838e0161254d565b8951918401916137548184848e0161254d565b89519201916137668184848d0161254d565b703c706f6c79676f6e20706f696e74733d2760781b920191825287516137928160118501848c0161254d565b7f272066696c7465723d2775726c28236d6629272f3e3c706f6c79676f6e20706f6011939091019283015265696e74733d2760d01b603183015286516137de8160378501848b0161254d565b7f272066696c6c3d2775726c28236d672927206f7061636974793d27000000000060379390910192830152855161381b8160528501848a0161254d565b61387361385161384b6052848701017425272f3e3c706f6c79676f6e20706f696e74733d2760581b815260150190565b88612b26565b7513903334b63a32b91e93bab9361411b6b9b31493979f60511b815260160190565b9c9b505050505050505050505050565b60008651613895818460208b0161254d565b61021960f51b90830190815286516138b4816002840160208b0161254d565b650101c181816160d51b6002929091019182015285516138db816008840160208a0161254d565b600160fd1b6008929091019182015284516138fd81600984016020890161254d565b61016160f51b60099290910191820152835161392081600b84016020880161254d565b640101c1818160dd1b600b9290910191820152601001979650505050505050565b7f3c66696c7465722069643d277766273e3c666554757262756c656e6365206261815270073654672657175656e63793d27302e303607c1b602082015260008751613993816031850160208c0161254d565b7f202e313127206e756d4f6374617665733d27342720736565643d27000000000060319184019182015287516139d081604c840160208c0161254d565b7f272f3e3c6665436f6d706f6e656e745472616e7366657220726573756c743d27604c92909101918201527f77617665273e3c666546756e635220747970653d276c696e6561722720736c6f606c8201527f70653d27302e312720696e746572636570743d272d302e3035272f3e3c666546608c8201527f756e634720747970653d2767616d6d612720616d706c69747564653d27302e3760ac8201527f3527206578706f6e656e743d27302e3627206f66667365743d27302e3035272f60cc8201527f3e3c666546756e634220747970653d2767616d6d612720616d706c697475646560ec8201527f3d27302e3827206578706f6e656e743d27302e3427206f66667365743d27302e61010c8201527f3035272f3e3c666546756e634120747970653d276c696e6561722720736c6f7061012c82015262653d2760e81b61014c820152613d1f613cd0613cca613c09613c03613b7e613b78613b3761014f89018f612b26565b7f272f3e3c2f6665436f6d706f6e656e745472616e736665723e3c6665466c6f6f81526e6420666c6f6f642d636f6c6f723d2760881b6020820152602f0190565b8c612b26565b7f272f3e3c6665436f6d706f7369746520696e3d2777617665272f3e3c6665436f81527f6d706f7369746520696e323d27536f75726365416c70686127206f706572617460208201527f6f723d27696e272f3e3c6665476175737369616e426c757220737464446576696040820152666174696f6e3d2760c81b606082015260670190565b89612b26565b7f2720726573756c743d27676c6f77272f3e3c6665436f6d706f7369746520696e81527f323d27676c6f7727206f70657261746f723d2761746f702720726573756c743d60208201527f276727202f3e3c66654d657267653e3c66654d657267654e6f64652f3e3c666560408201527f4d657267654e6f64652f3e3c2f66654d657267653e3c2f66696c7465723e3c7060608201527f61746820643d274d203020316533204c20302038303020000000000000000000608082015260970190565b86612b26565b7f204c2031653320383030204c2031653320316533272066696c7465723d27757281527f6c2823776629272066696c6c2d6f7061636974793d27373025272f3e000000006020820152603c0190565b9998505050505050505050565b6f1e3334b63a32b91034b21e93b1b3139f60811b81527f3c666554757262756c656e636520747970653d276672616374616c4e6f69736560108201527402720626173654672657175656e63793d27302e303605c1b603082015260008751613d9b816045850160208c0161254d565b7f20302e303227206e756d4f6374617665733d27322720736565643d27000000006045918401918201528751613dd8816061840160208c0161254d565b7f272f3e3c6665436f6c6f724d617472697820747970653d276d61747269782720606192909101918201526f3b30b63ab2b99e93981018101810181760811b60818201528651613e2f816091840160208b0161254d565b61309f613ed261308a613e7861304c613e6161300f6091888a01016a101810181018101810181760a91b8152600b0190565b6a101810181018101810181760a91b8152600b0190565b7f203020302030203020312030272f3e3c2f66696c7465723e3c7265637420776981527f6474683d273130302527206865696768743d273130302527206f7061636974796020820152613d2760f01b604082015260420190565b751293903334b63a32b91e93bab9361411b1b31493979f60511b815260160190565b600082613f0357613f03612aa7565b500690565b630e4cec4560e31b815260008451613f2781600485016020890161254d565b808301905061016160f51b8060048301528551613f4b816006850160208a0161254d565b60069201918201528351613f6681600884016020880161254d565b602960f81b6008929091019182015260090195945050505050565b7f3c646566733e3c72616469616c4772616469656e742069643d27706700000000815260008451613fb981601c85016020890161254d565b731390333c1e939a98129390333c9e939a9812939f60611b601c918401918201528451613fed81603084016020890161254d565b845191019061400381603084016020880161254d565b7f3c2f72616469616c4772616469656e743e3c2f646566733e00000000000000006030929091019182015260480195945050505050565b6d1e3334b63a32b91034b21e93b83360911b81526000845161406381600e85016020890161254d565b7f2720783d272d3235252720793d272d323525272077696474683d273135302527600e918401918201526e103432b4b3b43a1e93989a9812939f60891b602e82015284516140b881603d84016020890161254d565b84519101906140ce81603d84016020880161254d565b7f3c6665436f6d706f7369746520726573756c743d277027206f70657261746f72603d92909101918201527f3d27696e2720696e323d27536f7572636547726170686963272f3e3c66654761605d8201527f75737369616e426c757220737464446576696174696f6e3d2738272072657375607d8201527f6c743d276362272f3e3c66654d657267653e3c66654d657267654e6f64652069609d8201527f6e3d276362272f3e3c66654d657267654e6f646520696e3d2770272f3e3c2f6660bd8201526f32a6b2b933b29f1e17b334b63a32b91f60811b60dd82015260ed0195945050505050565b600083516141c881846020880161254d565b8351908301906141dc81836020880161254d565b01949350505050565b6d3c73746f70206f66667365743d2760901b81526000835161420e81600e85016020880161254d565b6e25272073746f702d636f6c6f723d2760881b600e91840191820152835161423d81601d84016020880161254d565b6213979f60e91b601d9290910191820152602001949350505050565b733c666554757262756c656e636520747970653d2760601b815260008551614288816014850160208a0161254d565b702720626173654672657175656e63793d2760781b60149184019182015285516142b9816025840160208a0161254d565b672720736565643d2760c01b6025929091019182015284516142e281602d84016020890161254d565b6d27206e756d4f6374617665733d2760901b602d9290910191820152835161431181603b84016020880161254d565b6213979f60e91b603b9290910191820152603e019695505050505050565b7f3c6665446966667573654c69676874696e67206c69676874696e672d636f6c6f815262723d2760e81b60208201526000845161437381602385016020890161254d565b6f2720737572666163655363616c653d2760801b60239184019182015284516143a381603384016020890161254d565b7f273e3c666544697374616e744c6967687420656c65766174696f6e3d270000006033929091019182015283516143e181605084016020880161254d565b7f272f3e3c2f6665446966667573654c69676874696e673e0000000000000000006050929091019182015260670195945050505050565b6b3c636972636c652063783d2760a01b81526000855161443f81600c850160208a0161254d565b65272063793d2760d01b600c918401918201528551614465816012840160208a0161254d565b642720723d2760d81b60129290910191820152845161448b81601784016020890161254d565b7013903334b63a32b91e93bab9361411b83360791b6017929091019182015283516144bd81602884016020880161254d565b631493979f60e11b60289290910191820152602c019695505050505050565b6b3c636972636c652063783d2760a01b81526000855161450381600c850160208a0161254d565b65272063793d2760d01b600c918401918201528551614529816012840160208a0161254d565b642720723d2760d81b60129290910191820152845161454f81601784016020890161254d565b6e272066696c6c3d2775726c2823706760881b60179290910191820152835161457f81602684016020880161254d565b7114939037b830b1b4ba3c9e939a181293979f60711b602692909101918201526038019695505050505050565b630302e30360e41b8152600083516145cb81600485016020880161254d565b63020302e360e41b60049184019182015283516145ef81600884016020880161254d565b0160080194935050505056fe68747470733a2f2f7777772e636f736d6963776f726c64732e78797a2f73746f726566726f6e742d6d65746164617461a26469706673582212207fcd02845f4259497a863952fae1e71d2784946fdb2e35becf294d6500c15f0b64736f6c63430008110033

Loading...
Loading
Loading...
Loading
[ 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.