ETH Price: $3,339.62 (-2.51%)

Contract

0xa48b5c37eCd555354aE27F85902298Ff1aDD7e4B
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0x60046101132330212021-09-15 22:31:371168 days ago1631745097IN
 Create: MoonCatLootprintsMetadata
0 ETH0.5526801680

Advanced mode:
Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MoonCatLootprintsMetadata

Compiler Version
v0.8.1+commit.df193b15

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU AGPLv3 license
File 1 of 2 : MoonCatLootprintsMetadata.sol
// SPDX-License-Identifier: AGPL-3.0

pragma solidity 0.8.1;

/**
 * @dev On-chain art generation for MoonCatLootprints
 * Takes individual trait values as parameters, and outputs complete representations of them.
 */
contract MoonCatLootprintsMetadata {

    string[5] internal class_names =
        [
         "Mech",
         "Sub",
         "Tank",
         "Cruiser",
         "Unknown"
         ];

    /**
     * @dev Convert a Classification ID number into a string name
     */
    function getClassName(uint8 classId) public view returns (string memory) {
        return class_names[classId];
    }

    string[15] internal color_names =
        ["Hero Silver",
         "Genesis White",
         "Genesis Black",
         "Red",
         "Orange",
         "Yellow",
         "Chartreuse",
         "Green",
         "Teal",
         "Cyan",
         "SkyBlue",
         "Blue",
         "Purple",
         "Magenta",
         "Fuchsia"];

    /**
     * @dev Convert a Color ID number into a string name
     */
    function getColorName(uint8 colorId) public view returns (string memory) {
        return color_names[colorId];
    }

    // Color codes used for the background color of an image representation
    string[15] internal color_codes =
        ["#777777", // Silver
         "#cccccc", // White
         "#111111", // Black
         "hsl(0,60%,38%)", // Red
         "hsl(30,60%,38%)", // Orange
         "hsl(60,60%,38%)", // Yellow
         "hsl(80,60%,38%)", // Chartreuse
         "hsl(120,60%,38%)", // Green
         "hsl(150,60%,38%)", // Teal
         "hsl(180,60%,38%)", // Cyan
         "hsl(210,60%,38%)", // SkyBlue
         "hsl(240,60%,38%)", // Blue
         "hsl(270,60%,38%)", // Purple
         "hsl(300,60%,38%)", // Magenta
         "hsl(330,60%,38%)"]; // Fuchsia

    // SVG codes for the different icons for each ship classification
    string[4] public ship_images =
        ["<path class=\"s\" d=\"M-61.74,77.79h-12.61V32.32h12.61V77.79z M-28.03,26.64l-7.58-12.63v44.12h7.58V26.64z M-0.65,52.52h10.99 L41.41,1.36L24.74-12.66H-0.65h-25.39L-42.72,1.36l31.07,51.16H-0.65z M60.43,77.79h12.61V32.32H60.43V77.79z M26.73,58.14h7.58 V14.02l-7.58,12.63V58.14z\"/><path class=\"s\" d=\"M-23.89,32.56v4.77h-44.15V8.75h29.81 M-58.76,13.76h-18.55v18.55h18.55V13.76z M22.59,32.56v4.77h44.15V8.75 H36.92 M57.46,32.32h18.55V13.76H57.46V32.32z M5.79,46.98L5.79,46.98c0-1.07-0.87-1.94-1.94-1.94h-9c-1.07,0-1.94,0.87-1.94,1.94 v0c0,1.07,0.87,1.94,1.94,1.94h9C4.92,48.93,5.79,48.06,5.79,46.98z\"/><path class=\"s s1\" d=\"M-79.92,94.43V86.1 M-56.04,94.43V86.1 M78.61,94.43V86.1 M54.74,94.43V86.1 M-14.48,5.33h28.04 M-9.45,1.1 H8.52\"/><path class=\"s s1\" d=\"M-44.11,94.43h-47.87V82.76c0-2.76,2.24-5,5-5h37.87c2.76,0,5,2.24,5,5V94.43z M-19.88,57.67v-6.18 c0-1.64-1.33-2.97-2.97-2.97h-9.15v12.13h9.15C-21.22,60.65-19.88,59.32-19.88,57.67z M42.8,94.43h47.87V82.76c0-2.76-2.24-5-5-5 H47.8c-2.76,0-5,2.24-5,5V94.43z M-0.65,31.11h14.08L33.42,3.86L25.39,2.2l-8.96,8.83H-0.65h-17.08l-8.96-8.83l-8.04,1.66 l19.99,27.25H-0.65z M21.55,60.65h9.15V48.52h-9.15c-1.64,0-2.97,1.33-2.97,2.97v6.18C18.58,59.32,19.91,60.65,21.55,60.65z\"/><path class=\"s s1\" d=\"M-26.04-12.66l-11.17,9.4v-27.46h7.51l16.17,18.06H-26.04z M24.74-12.66l11.17,9.4v-27.46H28.4L12.23-12.66 H24.74z\"/><path class=\"s s2\" d=\"M-19.88,52.86h-3.79 M-19.88,56.46h-3.79 M22.37,52.86h-3.79 M18.58,56.46h3.79\"/>  <path class=\"s s2\" d=\"M-39.67,8.41l-1.58,33.83h-11.47l-1.58-33.83c0-4.04,3.28-7.32,7.32-7.32C-42.95,1.1-39.67,4.37-39.67,8.41z M-43.38,42.24h-6.9l-1.01,4.74h8.91L-43.38,42.24z M38.37,8.41l1.58,33.83h11.47L53,8.41c0-4.04-3.28-7.32-7.32-7.32 C41.64,1.1,38.37,4.37,38.37,8.41z M41.06,46.98h8.91l-1.01-4.74h-6.9L41.06,46.98z\"/>", // Mech

         "<path class=\"s\" d=\"M55.52,60.62l-125.85,7.15c-13.35,0.76-24.59-9.86-24.59-23.23v0c0-13.37,11.24-23.99,24.59-23.23l125.85,7.15 V60.62z\"/><path class=\"s\" d=\"M48.39,42.2v10.28l-5.47-1.16v-7.96L48.39,42.2z M63.26,21.92L63.26,21.92c-2.75,0-4.82,2.5-4.31,5.2 l3.33,17.61h1.97l3.33-17.61C68.09,24.42,66.01,21.92,63.26,21.92z M63.26,67.55L63.26,67.55c2.75,0,4.82-2.5,4.31-5.2l-3.33-17.61 h-1.97l-3.33,17.61C58.44,65.05,60.51,67.55,63.26,67.55z M-44.97,43.64L-44.97,43.64c0.76,0.76,1.99,0.76,2.75,0l6.36-6.36 c0.76-0.76,0.76-1.99,0-2.75l0,0c-0.76-0.76-1.99-0.76-2.75,0l-6.36,6.36C-45.72,41.65-45.72,42.88-44.97,43.64z M-34.82,43.64 L-34.82,43.64c0.76,0.76,1.99,0.76,2.75,0l6.36-6.36c0.76-0.76,0.76-1.99,0-2.75l0,0c-0.76-0.76-1.99-0.76-2.75,0l-6.36,6.36 C-35.58,41.65-35.58,42.88-34.82,43.64z M63.26,43.33h-7.74v2.81h7.74V43.33z\"/><path class=\"s\" d=\"M-71.47,62.75v15.73 M-65.61,62.75v22.93\"/> <path class=\"s s1\" d=\"M52.24,60.8l1.72,11.04l19.89,4.4v6.21L38.9,88.39c-8.09,1.37-15.55-4.68-15.87-12.88l-0.51-13.03 M51.24,28.2 L67.16,2.56l-80.25-3.16c-6.16-0.24-12.13,2.16-16.4,6.61l-16.03,16.69\"/><path class=\"s s1\" d=\"M3.89,39.09l39.03,1.83v13.24L3.89,55.98c-4.66,0-8.44-3.78-8.44-8.44C-4.56,42.87-0.78,39.09,3.89,39.09z M-42.74,31.11l-31.49-1.26c-5.73,0-10.75,3.81-12.3,9.33l-0.67,5.36h29.01L-42.74,31.11z M30.03,47.53L30.03,47.53 c0-1.07-0.87-1.94-1.94-1.94h-9c-1.07,0-1.94,0.87-1.94,1.94v0c0,1.07,0.87,1.94,1.94,1.94h9C29.16,49.47,30.03,48.6,30.03,47.53z\"/>", // Sub

         "<path class=\"s\" d=\"M-41.05,64.38H-76.3c-9.83,0-17.79-7.98-17.77-17.8l0.02-7.96l53-31.34V64.38z M-33.49,21.94v36.39l12.96,9.64 c7.01,5.22,15.52,8.03,24.26,8.03h50.54V7.29l-12-2.39C27.98,2.05,13.19,3.4-0.34,8.77L-33.49,21.94z\"/> <path class=\"s\" d=\"M-53.74,49.67l93.8-17.28 M-53.74,96.38h99.86 M-60.37,44.65L-60.37,44.65c0-1.07-0.87-1.94-1.94-1.94h-9 c-1.07,0-1.94,0.87-1.94,1.94v0c0,1.07,0.87,1.94,1.94,1.94h9C-61.24,46.59-60.37,45.72-60.37,44.65z M-60.37,37.78L-60.37,37.78 c0-1.07-0.87-1.94-1.94-1.94h-9c-1.07,0-1.94,0.87-1.94,1.94v0c0,1.07,0.87,1.94,1.94,1.94h9C-61.24,39.72-60.37,38.85-60.37,37.78 z M-33.49,26.33h-7.56v27.92h7.56V26.33z\"/><path class=\"s s1\" d=\"M-0.29,30.83v-9c0-1.07,0.87-1.94,1.94-1.94h0c1.07,0,1.94,0.87,1.94,1.94v9c0,1.07-0.87,1.94-1.94,1.94h0 C0.58,32.77-0.29,31.9-0.29,30.83z M1.47-0.14c-4.66,0-8.44,3.78-8.44,8.44l1.83,39.03H8.08L9.91,8.3 C9.91,3.64,6.13-0.14,1.47-0.14z\"/> <path class=\"s s1\" d=\"M42.26,32.38c-17.67,0-32,14.33-32,32s14.33,32,32,32s32-14.33,32-32S59.94,32.38,42.26,32.38z M42.26,89.98 c-14.14,0-25.6-11.46-25.6-25.6s11.46-25.6,25.6-25.6s25.6,11.46,25.6,25.6S56.4,89.98,42.26,89.98z M-51.74,49.57 c-12.93,0-23.4,10.48-23.4,23.41c0,12.93,10.48,23.4,23.4,23.4s23.4-10.48,23.4-23.4C-28.33,60.05-38.81,49.57-51.74,49.57z M-51.74,91.7c-10.34,0-18.72-8.38-18.72-18.72c0-10.34,8.38-18.72,18.72-18.72s18.72,8.38,18.72,18.72 C-33.01,83.32-41.4,91.7-51.74,91.7z M-46.35,29.02h-14.78l14.4-10.61L-46.35,29.02z M6.8,52.81H-3.49l1.16-5.47h7.96L6.8,52.81z M54.26,20.3l9-3v18.97l-9-3.28 M54.26,53.04l9-3v18.97l-9-3.28\"/>", // Tank

         "<path class=\"s\" d=\"M0.26,93.33h14.33c0,0-0.76-11.46-2.27-32s13.64-76.47,19.95-99.97s-2.52-60.03-32-60.03 s-38.31,36.54-32,60.03s21.46,79.43,19.95,99.97s-2.27,32-2.27,32H0.26\"/><path class=\"s\" d=\"M-12.9,76.57l-47.02,6.06l3.03-18.95l43.64-22.42 M-26.38-18.46l-9.09,14.31v19.33l14.78-10.8 M13.42,76.57 l47.02,6.06l-3.03-18.95L13.77,41.25 M21.22,4.37L36,15.17V-4.15l-9.09-14.31\"/><path class=\"s s1\" d=\"M-33.66,46.63l-1.83,39.03h-13.24l-1.83-39.03c0-4.66,3.78-8.44,8.44-8.44 C-37.44,38.18-33.66,41.96-33.66,46.63z M34.19,46.63l1.83,39.03h13.24l1.83-39.03c0-4.66-3.78-8.44-8.44-8.44 C37.97,38.18,34.19,41.96,34.19,46.63z\"/><path class=\"s s1\" d=\"M-19.18-74.83c1.04,1.8,0.95,17.15,3.03,27c1.51,7.14,4.01,15.92,2.38,18.14c-1.43,1.94-7.59,1.24-9.95-1.37 c-3.41-3.78-4.15-10.56-4.93-16.67C-30.13-59.39-22.35-80.31-19.18-74.83z M-37.94,85.66h-7.96l-1.16,5.47h10.28L-37.94,85.66z M-10.65,93.33l-1.33,8.05H0.26h12.24l-1.33-8.05 M0.26-34.67c0,0,1.82,0,6.12,0s7.45-32,7.04-43S9.28-88.66,0.26-88.66 s-12.75-0.01-13.16,10.99c-0.41,11,2.74,43,7.04,43S0.26-34.67,0.26-34.67z M19.71-74.83c-1.04,1.8-0.95,17.15-3.03,27 c-1.51,7.14-4.01,15.92-2.38,18.14c1.43,1.94,7.59,1.24,9.95-1.37c3.41-3.78,4.15-10.56,4.93-16.67 C30.65-59.39,22.88-80.31,19.71-74.83z M37.3,91.13h10.28l-1.16-5.47h-7.96L37.3,91.13z\"/>" // Cruiser
         ];

    /**
     * @dev Render an SVG of a ship with the specified features.
     */
    function getImage (uint256 lootprintId, uint8 classId, uint8 colorId, uint8 bays, string calldata shipName)
        public
        view
        returns (string memory)
    {

        string memory regStr = uint2str(lootprintId);
        string memory baysStr = uint2str(bays);

        string[15] memory parts;
        parts[0] = "<svg xmlns=\"http://www.w3.org/2000/svg\" preserveAspectRatio=\"xMinYMin meet\" viewBox=\"0 0 600 600\"><style> .s{fill:white;stroke:white;stroke-width:2;stroke-miterlimit:10;fill-opacity:0.1;stroke-linecap:round}.s1{fill-opacity:0.3}.s2{stroke-width:1}.t{ fill:white;font-family:serif;font-size:20px;}.k{font-weight:bold;text-anchor:end;fill:#ddd;}.n{font-size:22px;font-weight:bold;text-anchor:middle}.l{fill:none;stroke:rgb(230,230,230,0.5);stroke-width:1;clip-path:url(#c);}.r{fill:rgba(0,0,0,0.5);stroke:white;stroke-width:3;}.r1{stroke-width: 1} .a{fill:#FFFFFF;fill-opacity:0.1;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;}.b{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;} .c{fill:#FFFFFF;fill-opacity:0.2;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;} .d{fill:#FFFFFF;fill-opacity:0.3;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;}</style><defs><clipPath id=\"c\"><rect width=\"600\" height=\"600\" /></clipPath></defs><rect width=\"600\" height=\"600\" fill=\"";
        parts[1] = color_codes[colorId];
        parts[2] = "\"/><polyline class=\"l\" points=\"40,-5 40,605 80,605 80,-5 120,-5 120,605 160,605 160,-5 200,-5 200,605 240,605 240,-5 280,-5 280,605 320,605 320,-5 360,-5 360,605 400,605 400,-5 440,-5 440,605 480,605 480,-5 520,-5 520,605 560,605 560,-5 600,-5 600,605\" /><polyline class=\"l\" points=\"-5,40 605,40 605,80 -5,80 -5,120 605,120 605,160 -5,160 -5,200 605,200 605,240 -5,240 -5,280 605,280 605,320 -5,320 -5,360 605,360 605,400 -5,400 -5,440 605,440 605,480 -5,480 -5,520 605,520 605,560 -5,560 -5,600 605,600\" /><rect class=\"r\" x=\"10\" y=\"10\" width=\"580\" height=\"50\" rx=\"15\" /><rect class=\"l r r1\" x=\"-5\" y=\"80\" width=\"285\" height=\"535\" /><text class=\"t n\" x=\"300\" y=\"42\">";
        parts[3] = shipName;
        parts[4] = "</text><text class=\"t k\" x=\"115\" y=\"147\">Reg:</text><text class=\"t\" x=\"125\" y=\"147\">#";
        parts[5] = regStr;
        parts[6] = "</text><text class=\"t k\" x=\"115\" y=\"187\">Class:</text><text class=\"t\" x=\"125\" y=\"187\">";
        parts[7] = class_names[classId];
        parts[8] = "</text><text class=\"t k\" x=\"115\" y=\"227\">Color:</text><text class=\"t\" x=\"125\" y=\"227\">";
        parts[9] = color_names[colorId];
        parts[10] = "</text><text class=\"t k\" x=\"115\" y=\"267\">Bays:</text><text class=\"t\" x=\"125\" y=\"267\">";
        parts[11] = baysStr;
        parts[12] = "</text><g transform=\"translate(440,440)scale(1.2)\">";
        if (classId < 4) {
            parts[13] = ship_images[classId];
        }
        parts[14] = "</g></svg>";

        bytes memory svg0 = abi.encodePacked(parts[0], parts[1], parts[2],
                                             parts[3], parts[4], parts[5],
                                             parts[6], parts[7], parts[8]);
        bytes memory svg1 = abi.encodePacked(parts[9], parts[10], parts[11],
                                             parts[12], parts[13], parts[14]);

        return string(abi.encodePacked("data:image/svg+xml;base64,", Base64.encode(abi.encodePacked(svg0, svg1))));
    }

    /**
     * @dev Encode a key/value pair as a JSON trait property, where the value is a numeric item (doesn't need quotes)
     */
    function encodeAttribute(string memory key, string memory value) internal pure returns (string memory) {
        return string(abi.encodePacked("{\"trait_type\":\"", key,"\",\"value\":",value,"}"));
    }

    /**
     * @dev Encode a key/value pair as a JSON trait property, where the value is a string item (needs quotes around it)
     */
    function encodeStringAttribute(string memory key, string memory value) internal pure returns (string memory) {
        return string(abi.encodePacked("{\"trait_type\":\"", key,"\",\"value\":\"",value,"\"}"));
    }

    /**
     * @dev Render a JSON metadata object of a ship with the specified features.
     */
    function getJSON(uint256 lootprintId, uint8 classId, uint8 colorId, uint8 bays, string calldata shipName)
        public
        view
        returns (string memory) {
        string memory colorName = color_names[colorId];
        string memory svg = getImage(lootprintId, classId, colorId, bays, shipName);
        bytes memory tokenName = abi.encodePacked("Lootprint #", uint2str(lootprintId), ": ", shipName);
        bytes memory json = abi.encodePacked("{",
                                             "\"attributes\":[",
                                             encodeAttribute("Registration #", uint2str(lootprintId)), ",",
                                             encodeStringAttribute("Class", class_names[classId]), ",",
                                             encodeAttribute("Bays", uint2str(bays)), ",",
                                             encodeStringAttribute("Color", colorName),
                                             "],\"name\":\"", tokenName,
                                             "\",\"description\":\"Build Plans for a MoonCat Spacecraft\",\"image\":\"", svg,
                                             "\"}");
        return string(abi.encodePacked('data:application/json;base64,', Base64.encode(json)));

    }

    /* Utilities */

    function uint2str(uint value) internal pure returns (string memory) {
        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

}

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

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

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

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

        bytes memory table = TABLE;

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

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

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

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

            mstore(resultPtr, out)

            resultPtr := add(resultPtr, 4)
            }

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

            mstore(result, encodedLen)
                }

        return string(result);
    }
}

File 2 of 2 : MoonCatLootprints.sol
// SPDX-License-Identifier: AGPL-3.0

pragma solidity 0.8.1;

interface IMoonCatAcclimator {
    function getApproved(uint256 tokenId) external view returns (address);
    function isApprovedForAll(address owner, address operator) external view returns (bool);
    function ownerOf(uint256 tokenId) external view returns (address);
}

interface IMoonCatRescue {
    function rescueOrder(uint256 tokenId) external view returns (bytes5);
    function catOwners(bytes5 catId) external view returns (address);
}

interface IReverseResolver {
    function claim(address owner) external returns (bytes32);
}

interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

interface IERC721 is IERC165 {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
    function balanceOf(address owner) external view returns (uint256 balance);
    function ownerOf(uint256 tokenId) external view returns (address owner);
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;
    function approve(address to, uint256 tokenId) external;
    function getApproved(uint256 tokenId) external view returns (address operator);
    function setApprovalForAll(address operator, bool _approved) external;
    function isApprovedForAll(address owner, address operator) external view returns (bool);
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

interface IERC721Metadata is IERC721 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

interface IERC721Enumerable is IERC721 {
    function totalSupply() external view returns (uint256);
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
    function tokenByIndex(uint256 index) external view returns (uint256);
}

interface IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
}

interface IMoonCatLootprintsMetadata {
    function getJSON(uint256 lootprintId,
                     uint8 classId,
                     uint8 colorId,
                     uint8 bays,
                     string calldata shipName)
        external view returns (string memory);
    function getImage(uint256 lootprintId,
                      uint8 classId,
                      uint8 colorId,
                      uint8 bays,
                      string calldata shipName)
        external view returns (string memory);
    function getClassName(uint8 classId) external view returns (string memory);
    function getColorName(uint8 classId) external view returns (string memory);
}


/**
 * @dev Derived from OpenZeppelin standard template
 * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/structs/EnumerableSet.sol
 * b0cf6fbb7a70f31527f36579ad644e1cf12fdf4e
 */
library EnumerableSet {
    struct Set {
        uint256[] _values;
        mapping (uint256 => uint256) _indexes;
    }

    function at(Set storage set, uint256 index) internal view returns (uint256) {
        return set._values[index];
    }

    function contains(Set storage set, uint256 value) internal view returns (bool) {
        return set._indexes[value] != 0;
    }

    function length(Set storage set) internal view returns (uint256) {
        return set._values.length;
    }

    function add(Set storage set, uint256 value) internal returns (bool) {
        if (!contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    function remove(Set storage set, uint256 value) internal returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];
        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.
            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;
            if (lastIndex != toDeleteIndex) {
                uint256 lastvalue = set._values[lastIndex];
                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastvalue;
                // Update the index for the moved value
                set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();
            // Delete the index for the deleted slot
            delete set._indexes[value];
            return true;
        } else {
            return false;
        }
    }
}

/**
 * @title MoonCat​Lootprints
 * @dev MoonCats have found some plans for building spaceships
 */
contract MoonCatLootprints is IERC165, IERC721Enumerable, IERC721Metadata {

    /* ERC-165 */

    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165) returns (bool) {
        return (interfaceId == type(IERC721).interfaceId ||
                interfaceId == type(IERC721Metadata).interfaceId ||
                interfaceId == type(IERC721Enumerable).interfaceId);
    }

    /* External Contracts */

    IMoonCatAcclimator MCA = IMoonCatAcclimator(0xc3f733ca98E0daD0386979Eb96fb1722A1A05E69);
    IMoonCatRescue MCR = IMoonCatRescue(0x60cd862c9C687A9dE49aecdC3A99b74A4fc54aB6);
    IMoonCatLootprintsMetadata public Metadata;

    /* Name String Data */

    string[4] internal honorifics =
        [
         "Legendary",
         "Notorious",
         "Distinguished",
         "Renowned"
         ];

    string[32] internal adjectives =
        [
         "Turbo",
         "Tectonic",
         "Rugged",
         "Derelict",
         "Scratchscarred",
         "Purrfect",
         "Rickety",
         "Sparkly",
         "Ethereal",
         "Hissing",
         "Pouncing",
         "Stalking",
         "Standing",
         "Sleeping",
         "Playful",
         "Menancing", // Poor Steve.
         "Cuddly",
         "Neurotic",
         "Skittish",
         "Impulsive",
         "Sly",
         "Ponderous",
         "Prodigal",
         "Hungry",
         "Grumpy",
         "Harmless",
         "Mysterious",
         "Frisky",
         "Furry",
         "Scratchy",
         "Patchy",
         "Hairless"
         ];

    string[15] internal mods =
        [
         "Star",
         "Galaxy",
         "Constellation",
         "World",
         "Moon",
         "Alley",
         "Midnight",
         "Wander",
         "Tuna",
         "Mouse",
         "Catnip",
         "Toy",
         "Kibble",
         "Hairball",
         "Litterbox"
         ];

    string[32] internal mains =
        [
         "Lightning",
         "Wonder",
         "Toebean",
         "Whisker",
         "Paw",
         "Fang",
         "Tail",
         "Purrbox",
         "Meow",
         "Claw",
         "Scratcher",
         "Chomper",
         "Nibbler",
         "Mouser",
         "Racer",
         "Teaser",
         "Chaser",
         "Hunter",
         "Leaper",
         "Sleeper",
         "Pouncer",
         "Stalker",
         "Stander",
         "TopCat",
         "Ambassador",
         "Admiral",
         "Commander",
         "Negotiator",
         "Vandal",
         "Mischief",
         "Ultimatum",
         "Frolic"
         ];

    string[16] internal designations =
        [
         "Alpha",
         "Tau",
         "Pi",
         "I",
         "II",
         "III",
         "IV",
         "V",
         "X",
         "Prime",
         "Proper",
         "1",
         "1701-D",
         "2017",
         "A",
         "Runt"
         ];

    /* Data */

    bytes32[400] ColorTable;

    /* Structs */

    struct Lootprint {
        uint16 index;
        address owner;
    }

    /* State */

    using EnumerableSet for EnumerableSet.Set;

    address payable public contractOwner;

    bool public frozen = true;

    bool public mintingWindowOpen = true;

    uint8 revealCount = 0;

    uint256 public price = 50000000000000000;

    bytes32[100] NoChargeList;

    bytes32[20] revealBlockHashes;

    Lootprint[25600] public Lootprints; // lootprints by lootprintId/rescueOrder

    EnumerableSet.Set internal LootprintIdByIndex;

    mapping(address => EnumerableSet.Set) internal LootprintsByOwner;

    mapping(uint256 => address) private TokenApprovals; // lootprint id -> approved address

    mapping(address => mapping(address => bool)) private OperatorApprovals; // owner address -> operator address -> bool

    /* Modifiers */

    modifier onlyContractOwner () {
        require(msg.sender == contractOwner, "Only Contract Owner");
        _;
    }

    modifier lootprintExists (uint256 lootprintId) {
        require(LootprintIdByIndex.contains(lootprintId), "ERC721: operator query for nonexistent token");
        _;
    }

    modifier onlyOwnerOrApproved(uint256 lootprintId) {
        require(LootprintIdByIndex.contains(lootprintId), "ERC721: query for nonexistent token");
        address owner = ownerOf(lootprintId);
        require(msg.sender == owner || msg.sender == TokenApprovals[lootprintId] || OperatorApprovals[owner][msg.sender],
                "ERC721: transfer caller is not owner nor approved");
        _;
    }

    modifier notFrozen () {
        require(!frozen, "Frozen");
        _;
    }

    /* ERC-721 Helpers */

    function setApprove(address to, uint256 lootprintId) private {
        TokenApprovals[lootprintId] = to;
        emit Approval(msg.sender, to, lootprintId);
    }

    function handleTransfer(address from, address to, uint256 lootprintId) private {
        require(to != address(0), "ERC721: transfer to the zero address");
        setApprove(address(0), lootprintId);
        LootprintsByOwner[from].remove(lootprintId);
        LootprintsByOwner[to].add(lootprintId);
        Lootprints[lootprintId].owner = to;
        emit Transfer(from, to, lootprintId);
    }

    /* ERC-721 */

    function totalSupply() public view override returns (uint256) {
        return LootprintIdByIndex.length();
    }

    function balanceOf(address owner) public view override returns (uint256 balance) {
        return LootprintsByOwner[owner].length();
    }

    function ownerOf(uint256 lootprintId) public view override returns (address owner) {
        return Lootprints[lootprintId].owner;
    }

    function approve(address to, uint256 lootprintId) public override lootprintExists(lootprintId) {
        address owner = ownerOf(lootprintId);
        require(to != owner, "ERC721: approval to current owner");
        require(msg.sender == owner || isApprovedForAll(owner, msg.sender), "ERC721: approve caller is not owner nor approved for all");
        setApprove(to, lootprintId);
    }

    function getApproved(uint256 lootprintId) public view override returns (address operator) {
        return TokenApprovals[lootprintId];
    }

    function setApprovalForAll(address operator, bool approved) public override {
        require(operator != msg.sender, "ERC721: approve to caller");
        OperatorApprovals[msg.sender][operator] = approved;
        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function isApprovedForAll(address owner, address operator) public view override returns (bool) {
        return OperatorApprovals[owner][operator];
    }

    function safeTransferFrom(address from, address to, uint256 lootprintId, bytes memory _data) public override onlyOwnerOrApproved(lootprintId) {
        handleTransfer(from, to, lootprintId);
        uint256 size;
        assembly {
            size := extcodesize(to)
        }
        if (size > 0) {
            try IERC721Receiver(to).onERC721Received(msg.sender, from, lootprintId, _data) returns (bytes4 retval) {
                if (retval != IERC721Receiver.onERC721Received.selector) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                }
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        }
    }

    function safeTransferFrom(address from, address to, uint256 lootprintId) public override {
        safeTransferFrom(from, to, lootprintId, "");
    }

    function transferFrom(address from, address to, uint256 lootprintId) public override onlyOwnerOrApproved(lootprintId) {
        handleTransfer(from, to, lootprintId);
    }

    /* ERC-721 Enumerable */

    function tokenByIndex(uint256 index) public view override returns (uint256) {
        return LootprintIdByIndex.at(index);
    }

    function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
        require(index < balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
        return LootprintsByOwner[owner].at(index);
    }

    /* Reveal */

    bool pendingReveal = false;
    uint256 revealPrepBlock;
    bytes32 revealSeedHash;

    /**
     * @dev How many lootprints are awaiting being revealed?
     */
    function pendingRevealCount() public view returns (uint256) {
        uint256 numRevealed = revealCount * 2560;
        if (numRevealed > LootprintIdByIndex.length()) return 0;
        return LootprintIdByIndex.length() - numRevealed;
    }

    /**
     * @dev Start a reveal action.
     * The hash submitted here must be the keccak256 hash of a secret number that will be submitted to the next function
     */
    function prepReveal(bytes32 seedHash) public onlyContractOwner {
        require(!pendingReveal && seedHash != revealSeedHash && revealCount < 20, "Prep Conditions Not Met");
        revealSeedHash = seedHash;
        revealPrepBlock = block.number;
        pendingReveal = true;
    }

    /**
     * @dev Finalize a reveal action.
     * Must take place at least one block after the `prepReveal` action was taken
     */
    function reveal(uint256 revealSeed) public onlyContractOwner{
        require(pendingReveal
                && block.number > revealPrepBlock
                && keccak256(abi.encodePacked(revealSeed)) == revealSeedHash
                , "Reveal Conditions Not Met");

        if (block.number - revealPrepBlock < 255) {
            bytes32 blockSeed = keccak256(abi.encodePacked(revealSeed, blockhash(revealPrepBlock)));
            revealBlockHashes[revealCount] = blockSeed;
            revealCount++;
        }
        pendingReveal = false;
    }

    /* Minting */

    /**
     * @dev Is the minting of a specific rescueOrder needing payment or is it free?
     */
    function paidMint(uint256 rescueOrder) public view returns (bool) {
        uint256 wordIndex = rescueOrder / 256;
        uint256 bitIndex = rescueOrder % 256;
        return (uint(NoChargeList[wordIndex] >> (255 - bitIndex)) & 1) == 0;
    }

    /**
     * @dev Create the token
     * Checks that the address minting is the current owner of the MoonCat, and ensures that MoonCat is Acclimated
     */
    function handleMint(uint256 rescueOrder, address to) private {
        require(mintingWindowOpen, "Minting Window Closed");
        require(MCR.catOwners(MCR.rescueOrder(rescueOrder)) == 0xc3f733ca98E0daD0386979Eb96fb1722A1A05E69,
                "Not Acclimated");
        address moonCatOwner = MCA.ownerOf(rescueOrder);
        require((msg.sender == moonCatOwner)
            || (msg.sender == MCA.getApproved(rescueOrder))
            || (MCA.isApprovedForAll(moonCatOwner, msg.sender)),
            "Not AMC Owner or Approved"
        );

        require(!LootprintIdByIndex.contains(rescueOrder), "Already Minted");
        Lootprints[rescueOrder] = Lootprint(uint16(LootprintIdByIndex.length()), to);
        LootprintIdByIndex.add(rescueOrder);
        LootprintsByOwner[to].add(rescueOrder);
        emit Transfer(address(0), to, rescueOrder);
    }

    /**
     * @dev Mint a lootprint, and give it to a specific address
     */
    function mint(uint256 rescueOrder, address to) public payable notFrozen {
        if (paidMint(rescueOrder)) {
            require(address(this).balance >= price, "Insufficient Value");
            contractOwner.transfer(price);
        }
        handleMint(rescueOrder, to);
        if (address(this).balance > 0) {
            // The buyer over-paid; transfer their funds back to them
            payable(msg.sender).transfer(address(this).balance);
        }
    }

    /**
     * @dev Mint a lootprint, and give it to the address making the transaction
     */
    function mint(uint256 rescueOrder) public payable {
        mint(rescueOrder, msg.sender);
    }

    /**
     * @dev Mint multiple lootprints, sending them all to a specific address
     */
    function mintMultiple(uint256[] calldata rescueOrders, address to) public payable notFrozen {
        uint256 totalPrice = 0;
        for (uint i = 0; i < rescueOrders.length; i++) {
            if (paidMint(rescueOrders[i])) {
                totalPrice += price;
            }
            handleMint(rescueOrders[i], to);
        }
        require(address(this).balance >= totalPrice, "Insufficient Value");
        if (totalPrice > 0) {
            contractOwner.transfer(totalPrice);
        }
        if (address(this).balance > 0) {
            // The buyer over-paid; transfer their funds back to them
            payable(msg.sender).transfer(address(this).balance);
        }
    }

    /**
     * @dev Mint multiple lootprints, sending them all to the address making the transaction
     */
    function mintMultiple(uint256[] calldata rescueOrders) public payable {
        mintMultiple(rescueOrders, msg.sender);
    }

    /* Contract Owner */

    constructor(address metadataContract) {
        contractOwner = payable(msg.sender);

        Metadata = IMoonCatLootprintsMetadata(metadataContract);

        // https://docs.ens.domains/contract-api-reference/reverseregistrar#claim-address
        IReverseResolver(0x084b1c3C81545d370f3634392De611CaaBFf8148)
            .claim(msg.sender);
    }

    /**
     * @dev Mint the 160 Hero lootprint tokens, and give them to the contract owner
     */
    function setupHeroShips(bool groupTwo) public onlyContractOwner {
        uint startIndex = 25440;
        if (groupTwo) {
             startIndex = 25520;
        }
        require(Lootprints[startIndex].owner == address(0), "Already Set Up");
        for (uint i = startIndex; i < (startIndex+80); i++) {
            Lootprints[i] = Lootprint(uint16(LootprintIdByIndex.length()), contractOwner);
            LootprintIdByIndex.add(i);
            LootprintsByOwner[contractOwner].add(i);
            emit Transfer(address(0), contractOwner, i);
        }
    }

    /**
     * @dev Update the contract used for image/JSON rendering
     */
    function setMetadataContract(address metadataContract) public onlyContractOwner{
        Metadata = IMoonCatLootprintsMetadata(metadataContract);
    }

    /**
     * @dev Set configuration values for which MoonCat creates which color lootprint when minted
     */
    function setColorTable(bytes32[] calldata table, uint startAt) public onlyContractOwner {
        for (uint i = 0; i < table.length; i++) {
            ColorTable[startAt + i] = table[i];
        }
    }

    /**
     * @dev Set configuration values for which MoonCats need to pay for minting a lootprint
     */
    function setNoChargeList (bytes32[100] calldata noChargeList) public onlyContractOwner {
        NoChargeList = noChargeList;
    }

    /**
     * @dev Set configuration values for how much a paid lootprint costs
     */
    function setPrice(uint256 priceWei) public onlyContractOwner {
        price = priceWei;
    }

    /**
     * @dev Allow current `owner` to transfer ownership to another address
     */
    function transferOwnership (address payable newOwner) public onlyContractOwner {
        contractOwner = newOwner;
    }

    /**
     * @dev Prevent creating lootprints
     */
    function freeze () public onlyContractOwner notFrozen {
        frozen = true;
    }

    /**
     * @dev Enable creating lootprints
     */
    function unfreeze () public onlyContractOwner {
        frozen = false;
    }

    /**
     * @dev Prevent any further minting from happening
     * Checks to ensure all have been revealed before allowing locking down the minting process
     */
    function permanentlyCloseMintingWindow() public onlyContractOwner {
        require(revealCount >= 20, "Reveal Pending");
        mintingWindowOpen = false;
    }

    /* Property Decoders */

    function decodeColor(uint256 rescueOrder) public view returns (uint8) {
        uint256 wordIndex = rescueOrder / 64;
        uint256 nibbleIndex = rescueOrder % 64;
        bytes32 word = ColorTable[wordIndex];
        return uint8(uint(word >> (252 - nibbleIndex * 4)) & 15);
    }

    function decodeName(uint32 seed) internal view returns (string memory) {
        seed = seed >> 8;
        uint index;
        string[9] memory parts;
        //honorific
        index = seed & 15;
        if (index < 8) {
            parts[0] = "The ";
            if (index < 4) {
                parts[1] = honorifics[index];
                parts[2] = " ";
            }
        }
        seed >>= 4;
        //adjective
        if ((seed & 1) == 1) {
            index = (seed >> 1) & 31;
            parts[3] = adjectives[index];
            parts[4] = " ";
        }
        seed >>= 6;
        //mod
        index = seed & 15;
        if (index < 15) {
            parts[5] = mods[index];
        }
        seed >>= 4;
        //main
        index = seed & 31;
        parts[6] = mains[index];
        seed >>= 5;
        //designation
        if ((seed & 1) == 1) {
            index = (seed >> 1) & 15;
            parts[7] = " ";
            parts[8] = designations[index];
        }

        return string(abi.encodePacked(parts[0], parts[1], parts[2],
                                       parts[3], parts[4], parts[5],
                                       parts[6], parts[7], parts[8]));

    }

    function decodeClass(uint32 seed) internal pure returns (uint8) {
        uint class_determiner = seed & 15;
        if (class_determiner < 2) {
            return 0;
        } else if (class_determiner < 5) {
            return 1;
        } else if (class_determiner < 9) {
            return 2;
        } else {
            return 3;
        }
    }

    function decodeBays(uint32 seed) internal pure returns (uint8) {
        uint bay_determiner = (seed >> 4) & 15;

        if (bay_determiner < 3) {
            return 5;
        } else if (bay_determiner < 8) {
            return 4;
        } else {
            return 3;
        }
    }

    uint8 constant internal STATUS_NOT_MINTED = 0;
    uint8 constant internal STATUS_NOT_MINTED_FREE = 1;
    uint8 constant internal STATUS_PENDING = 2;
    uint8 constant internal STATUS_MINTED = 3;

    /**
     * @dev Get detailed traits about a lootprint token
     * Provides trait values in native contract return values, which can be used by other contracts
     */
    function getDetails (uint256 lootprintId)
        public
        view
        returns (uint8 status, string memory class, uint8 bays, string memory colorName, string memory shipName, address tokenOwner, uint32 seed)
    {
        Lootprint memory lootprint = Lootprints[lootprintId];
        colorName = Metadata.getColorName(decodeColor(lootprintId));
        tokenOwner = address(0);
        if (LootprintIdByIndex.contains(lootprintId)) {
            if (revealBlockHashes[lootprint.index / 1280] > 0) {
                seed = uint32(uint256(keccak256(abi.encodePacked(lootprintId, revealBlockHashes[lootprint.index / 1280]))));
                return (STATUS_MINTED,
                        Metadata.getClassName(decodeClass(seed)),
                        decodeBays(seed),
                        colorName,
                        decodeName(seed),
                        lootprint.owner,
                        seed);
            }
            status = STATUS_PENDING;
            tokenOwner = lootprint.owner;
        } else if (paidMint(lootprintId)) {
            status = STATUS_NOT_MINTED;
        } else {
            status = STATUS_NOT_MINTED_FREE;
        }
        return (status, "Unknown", 0, colorName, "?", tokenOwner, 0);
    }

    /* ERC-721 Metadata */

    function name() public pure override returns (string memory) {
        return "MoonCatLootprint";
    }

    function symbol() public pure override returns (string memory) {
        return unicode"📜";
    }

    function tokenURI(uint256 lootprintId) public view override lootprintExists(lootprintId) returns (string memory) {
        Lootprint memory lootprint = Lootprints[lootprintId];
        uint8 colorId = decodeColor(lootprintId);
        if (revealBlockHashes[lootprint.index / 1280] > 0) {
            uint32 seed = uint32(uint256(keccak256(abi.encodePacked(lootprintId, revealBlockHashes[lootprint.index / 1280]))));
            uint8 classId = decodeClass(seed);
            string memory shipName = decodeName(seed);
            uint8 bays = decodeBays(seed);
            return Metadata.getJSON(lootprintId, classId, colorId, bays, shipName);
        } else {
            return Metadata.getJSON(lootprintId, 4, colorId, 0, "?");
        }
    }

    function imageURI(uint256 lootprintId) public view lootprintExists(lootprintId) returns (string memory) {
        Lootprint memory lootprint = Lootprints[lootprintId];
        uint8 colorId = decodeColor(lootprintId);
        if (revealBlockHashes[lootprint.index / 1280] > 0) {
            uint32 seed = uint32(uint256(keccak256(abi.encodePacked(lootprintId, revealBlockHashes[lootprint.index / 1280]))));
            uint8 classId = decodeClass(seed);
            string memory shipName = decodeName(seed);
            uint8 bays = decodeBays(seed);
            return Metadata.getImage(lootprintId, classId, colorId, bays, shipName);
        } else {
            return Metadata.getImage(lootprintId, 4, colorId, 0, "?");
        }
    }

    /* Rescue Tokens */

    /**
     * @dev Rescue ERC20 assets sent directly to this contract.
     */
    function withdrawForeignERC20(address tokenContract)
        public
        onlyContractOwner
    {
        IERC20 token = IERC20(tokenContract);
        token.transfer(contractOwner, token.balanceOf(address(this)));
    }

    /**
     * @dev Rescue ERC721 assets sent directly to this contract.
     */
    function withdrawForeignERC721(address tokenContract, uint256 lootprintId)
        public
        onlyContractOwner
    {
        IERC721(tokenContract).safeTransferFrom(address(this), contractOwner, lootprintId);
    }

}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint8","name":"classId","type":"uint8"}],"name":"getClassName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"colorId","type":"uint8"}],"name":"getColorName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lootprintId","type":"uint256"},{"internalType":"uint8","name":"classId","type":"uint8"},{"internalType":"uint8","name":"colorId","type":"uint8"},{"internalType":"uint8","name":"bays","type":"uint8"},{"internalType":"string","name":"shipName","type":"string"}],"name":"getImage","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lootprintId","type":"uint256"},{"internalType":"uint8","name":"classId","type":"uint8"},{"internalType":"uint8","name":"colorId","type":"uint8"},{"internalType":"uint8","name":"bays","type":"uint8"},{"internalType":"string","name":"shipName","type":"string"}],"name":"getJSON","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ship_images","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]

60046101208181526309acac6d60e31b61014052608090815260036101609081526229bab160e91b6101805260a0526101a09182526354616e6b60e01b6101c05260c09190915260076101e08181526621b93ab4b9b2b960c91b6102005260e052610260604052610220908152662ab735b737bbb760c91b61024052610100526200008f906000906005620005eb565b50604051806101e001604052806040518060400160405280600b81526020016a2432b9379029b4b63b32b960a91b81525081526020016040518060400160405280600d81526020016c47656e6573697320576869746560981b81525081526020016040518060400160405280600d81526020016c47656e6573697320426c61636b60981b81525081526020016040518060400160405280600381526020016214995960ea1b8152508152602001604051806040016040528060068152602001654f72616e676560d01b81525081526020016040518060400160405280600681526020016559656c6c6f7760d01b81525081526020016040518060400160405280600a8152602001694368617274726575736560b01b81525081526020016040518060400160405280600581526020016423b932b2b760d91b8152508152602001604051806040016040528060048152602001631519585b60e21b81525081526020016040518060400160405280600481526020016321bcb0b760e11b815250815260200160405180604001604052806007815260200166536b79426c756560c81b815250815260200160405180604001604052806004815260200163426c756560e01b815250815260200160405180604001604052806006815260200165507572706c6560d01b8152508152602001604051806040016040528060078152602001664d6167656e746160c81b8152508152602001604051806040016040528060078152602001664675636873696160c81b815250815250600590600f620002d892919062000642565b50604080516102208101825260076101e08201818152662337373737373760c81b610200840152825282518084018452818152662363636363636360c81b6020828101919091528084019190915283518085018552918252662331313131313160c81b828201528284019190915282518084018452600e81526d68736c28302c3630252c3338252960901b81830152606083015282518084018452600f8082526e68736c2833302c3630252c3338252960881b828401526080840191909152835180850185528181526e68736c2836302c3630252c3338252960881b8184015260a0840152835180850185528181526e68736c2838302c3630252c3338252960881b8184015260c08401528351808501855260108082526f68736c283132302c3630252c3338252960801b8285015260e0850191909152845180860186528181526f68736c283135302c3630252c3338252960801b81850152610100850152845180860186528181526f68736c283138302c3630252c3338252960801b81850152610120850152845180860186528181526f68736c283231302c3630252c3338252960801b81850152610140850152845180860186528181526f68736c283234302c3630252c3338252960801b81850152610160850152845180860186528181526f68736c283237302c3630252c3338252960801b81850152610180850152845180860186528181526f68736c283330302c3630252c3338252960801b818501526101a0850152845180860190955284526f68736c283333302c3630252c3338252960801b918401919091526101c08201929092526200053c916014919062000642565b50604080516107a081019091526106ec60808201818152829162002a3260a08401398152602001604051806105e001604052806105a781526020016200311e6105a7913981526020016040518061064001604052806106098152602001620036c56106099139815260200160405180610520016040528061050081526020016200253261050091399052620005d690602390600462000687565b50348015620005e457600080fd5b5062000811565b826005810192821562000630579160200282015b828111156200063057825180516200061f918491602090910190620006cc565b5091602001919060010190620005ff565b506200063e92915062000757565b5090565b82600f810192821562000630579160200282015b8281111562000630578251805162000676918491602090910190620006cc565b509160200191906001019062000656565b826004810192821562000630579160200282015b82811115620006305782518051620006bb918491602090910190620006cc565b50916020019190600101906200069b565b828054620006da90620007d4565b90600052602060002090601f016020900481019282620006fe576000855562000749565b82601f106200071957805160ff191683800117855562000749565b8280016001018555821562000749579182015b82811115620007495782518255916020019190600101906200072c565b506200063e92915062000778565b808211156200063e5760006200076e82826200078f565b5060010162000757565b5b808211156200063e576000815560010162000779565b5080546200079d90620007d4565b6000825580601f10620007b15750620007d1565b601f016020900490600052602060002090810190620007d1919062000778565b50565b600281046001821680620007e957607f821691505b602082108114156200080b57634e487b7160e01b600052602260045260246000fd5b50919050565b611d1180620008216000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80630a8578211461005c5780632901237c146100855780636082e3a2146100985780636ba0383a146100ab578063bec11c63146100be575b600080fd5b61006f61006a366004610e00565b6100d1565b60405161007c9190611342565b60405180910390f35b61006f610093366004610ea8565b610382565b61006f6100a6366004610ea8565b61043a565b61006f6100b9366004610e00565b610460565b61006f6100cc366004610de8565b610a37565b6060600060058660ff16600f81106100f957634e487b7160e01b600052603260045260246000fd5b01805461010590611407565b80601f016020809104026020016040519081016040528092919081815260200182805461013190611407565b801561017e5780601f106101535761010080835404028352916020019161017e565b820191906000526020600020905b81548152906001019060200180831161016157829003601f168201915b505050505090506000610195898989898989610460565b905060006101a28a610ad7565b86866040516020016101b6939291906110b2565b60408051601f19818403018152828201909152600e82526d526567697374726174696f6e202360901b602083015291506000906101fb906101f68d610ad7565b610bfa565b6102cf60405180604001604052806005815260200164436c61737360d81b81525060008d60ff166005811061024057634e487b7160e01b600052603260045260246000fd5b01805461024c90611407565b80601f016020809104026020016040519081016040528092919081815260200182805461027890611407565b80156102c55780601f1061029a576101008083540402835291602001916102c5565b820191906000526020600020905b8154815290600101906020018083116102a857829003601f168201915b5050505050610c26565b6102fb604051806040016040528060048152602001634261797360e01b8152506101f68c60ff16610ad7565b6103226040518060400160405280600581526020016421b7b637b960d91b81525088610c26565b8587604051602001610339969594939291906111de565b604051602081830303815290604052905061035381610c3b565b60405160200161036391906112b8565b6040516020818303038152906040529450505050509695505050505050565b606060008260ff16600581106103a857634e487b7160e01b600052603260045260246000fd5b0180546103b490611407565b80601f01602080910402602001604051908101604052809291908181526020018280546103e090611407565b801561042d5780601f106104025761010080835404028352916020019161042d565b820191906000526020600020905b81548152906001019060200180831161041057829003601f168201915b505050505090505b919050565b606060058260ff16600f81106103a857634e487b7160e01b600052603260045260246000fd5b6060600061046d88610ad7565b9050600061047d8660ff16610ad7565b9050610487610daf565b6040518061040001604052806103db815260200161154a6103db91398152601460ff8916600f81106104c957634e487b7160e01b600052603260045260246000fd5b0180546104d590611407565b80601f016020809104026020016040519081016040528092919081815260200182805461050190611407565b801561054e5780601f106105235761010080835404028352916020019161054e565b820191906000526020600020905b81548152906001019060200180831161053157829003601f168201915b5050505050816001600f811061057457634e487b7160e01b600052603260045260246000fd5b6020020181905250604051806102c0016040528061029a81526020016119ba61029a913960408083019190915280516020601f8801819004810282018101909252868152908790879081908401838280828437600092019190915250849250600391506105de9050565b6020020181905250604051806080016040528060558152602001611c876055913960808083019190915260a08201849052604080519182019052605680825261149e602083013960c0820152600060ff8a166005811061064e57634e487b7160e01b600052603260045260246000fd5b01805461065a90611407565b80601f016020809104026020016040519081016040528092919081815260200182805461068690611407565b80156106d35780601f106106a8576101008083540402835291602001916106d3565b820191906000526020600020905b8154815290600101906020018083116106b657829003601f168201915b5050505050816007600f81106106f957634e487b7160e01b600052603260045260246000fd5b60200201819052506040518060800160405280605681526020016114f460569139610100820152600560ff8916600f811061074457634e487b7160e01b600052603260045260246000fd5b01805461075090611407565b80601f016020809104026020016040519081016040528092919081815260200182805461077c90611407565b80156107c95780601f1061079e576101008083540402835291602001916107c9565b820191906000526020600020905b8154815290600101906020018083116107ac57829003601f168201915b5050505050816009600f81106107ef57634e487b7160e01b600052603260045260246000fd5b602002018190525060405180608001604052806055815260200161192560559139610140820152610160810182905260408051606081019091526033808252611c546020830139610180820152600460ff8a16101561091d5760238960ff166004811061086c57634e487b7160e01b600052603260045260246000fd5b01805461087890611407565b80601f01602080910402602001604051908101604052809291908181526020018280546108a490611407565b80156108f15780601f106108c6576101008083540402835291602001916108f1565b820191906000526020600020905b8154815290600101906020018083116108d457829003601f168201915b505050505081600d600f811061091757634e487b7160e01b600052603260045260246000fd5b60200201525b604080518082018252600a8152691e17b39f1e17b9bb339f60b11b6020808301919091526101c0840191909152825183820151848401516060860151608087015160a088015160c089015160e08a01516101008b0151995160009a6109849a909101610ff0565b60408051808303601f19018152908290526101208401516101408501516101608601516101808701516101a08801516101c08901519597506000966109cc9690602001610f71565b6040516020818303038152906040529050610a0782826040516020016109f3929190610f42565b604051602081830303815290604052610c3b565b604051602001610a1791906112fd565b604051602081830303815290604052955050505050509695505050505050565b60238160048110610a4757600080fd5b018054909150610a5690611407565b80601f0160208091040260200160405190810160405280929190818152602001828054610a8290611407565b8015610acf5780601f10610aa457610100808354040283529160200191610acf565b820191906000526020600020905b815481529060010190602001808311610ab257829003601f168201915b505050505081565b606081610afc57506040805180820190915260018152600360fc1b6020820152610435565b8160005b8115610b265780610b1081611442565b9150610b1f9050600a8361138d565b9150610b00565b60008167ffffffffffffffff811115610b4f57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015610b79576020820181803683370190505b5090505b8415610bf257610b8e6001836113c0565b9150610b9b600a8661145d565b610ba6906030611375565b60f81b818381518110610bc957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350610beb600a8661138d565b9450610b7d565b949350505050565b60608282604051602001610c0f92919061116f565b604051602081830303815290604052905092915050565b60608282604051602001610c0f9291906110fe565b805160609080610c5b575050604080516020810190915260008152610435565b60006003610c6a836002611375565b610c74919061138d565b610c7f9060046113a1565b90506000610c8e826020611375565b67ffffffffffffffff811115610cb457634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015610cde576020820181803683370190505b509050600060405180606001604052806040815260200161197a604091399050600181016020830160005b86811015610d6a576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b835260049092019101610d09565b506003860660018114610d845760028114610d9557610da1565b613d3d60f01b600119830152610da1565b603d60f81b6000198301525b505050918152949350505050565b604051806101e00160405280600f905b6060815260200190600190039081610dbf5790505090565b803560ff8116811461043557600080fd5b600060208284031215610df9578081fd5b5035919050565b60008060008060008060a08789031215610e18578182fd5b86359550610e2860208801610dd7565b9450610e3660408801610dd7565b9350610e4460608801610dd7565b9250608087013567ffffffffffffffff80821115610e60578384fd5b818901915089601f830112610e73578384fd5b813581811115610e81578485fd5b8a6020828501011115610e92578485fd5b6020830194508093505050509295509295509295565b600060208284031215610eb9578081fd5b610ec282610dd7565b9392505050565b60008151610edb8185602086016113d7565b9290920192915050565b61227d60f01b815260020190565b7f222c226465736372697074696f6e223a224275696c6420506c616e7320666f7281527f2061204d6f6f6e4361742053706163656372616674222c22696d616765223a22602082015260400190565b60008351610f548184602088016113d7565b835190830190610f688183602088016113d7565b01949350505050565b600087516020610f848285838d016113d7565b885191840191610f978184848d016113d7565b8851920191610fa98184848c016113d7565b8751920191610fbb8184848b016113d7565b8651920191610fcd8184848a016113d7565b8551920191610fdf81848489016113d7565b919091019998505050505050505050565b60008a51611002818460208f016113d7565b8a5190830190611016818360208f016113d7565b8a516110288183850160208f016113d7565b8a5192909101019061103e818360208d016113d7565b88516110508183850160208d016113d7565b8851929091010190611066818360208b016113d7565b86516110788183850160208b016113d7565b865192909101019061108e8183602089016113d7565b84516110a081838501602089016113d7565b9101019b9a5050505050505050505050565b60006a4c6f6f747072696e74202360a81b825284516110d881600b8501602089016113d7565b6101d160f51b600b918401918201528385600d830137909201600d019182525092915050565b6e3d913a3930b4ba2fba3cb832911d1160891b8152825160009061112981600f8501602088016113d7565b6a1116113b30b63ab2911d1160a91b600f91840191820152835161115481601a8401602088016113d7565b61227d60f01b601a9290910191820152601c01949350505050565b6e3d913a3930b4ba2fba3cb832911d1160891b8152825160009061119a81600f8501602088016113d7565b691116113b30b63ab2911d60b11b600f9184019182015283516111c48160198401602088016113d7565b607d60f81b60199290910191820152601a01949350505050565b607b60f81b81526d2261747472696275746573223a5b60901b6001820152865160009061121281600f850160208c016113d7565b8083019050600b60fa1b80600f8301528851611235816010850160208d016113d7565b601092019182018190528751611252816011850160208c016113d7565b6011920191820152855161126d816012840160208a016113d7565b692e96113730b6b2911d1160b11b601292909101918201526112ab6112a66112a061129b601c850189610ec9565b610ef3565b86610ec9565b610ee5565b9998505050505050505050565b60007f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000825282516112f081601d8501602087016113d7565b91909101601d0192915050565b60007f646174613a696d6167652f7376672b786d6c3b6261736536342c0000000000008252825161133581601a8501602087016113d7565b91909101601a0192915050565b60006020825282518060208401526113618160408501602087016113d7565b601f01601f19169190910160400192915050565b6000821982111561138857611388611471565b500190565b60008261139c5761139c611487565b500490565b60008160001904831182151516156113bb576113bb611471565b500290565b6000828210156113d2576113d2611471565b500390565b60005b838110156113f25781810151838201526020016113da565b83811115611401576000848401525b50505050565b60028104600182168061141b57607f821691505b6020821081141561143c57634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561145657611456611471565b5060010190565b60008261146c5761146c611487565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fdfe3c2f746578743e3c7465787420636c6173733d2274206b2220783d223131352220793d22313837223e436c6173733a3c2f746578743e3c7465787420636c6173733d22742220783d223132352220793d22313837223e3c2f746578743e3c7465787420636c6173733d2274206b2220783d223131352220793d22323237223e436f6c6f723a3c2f746578743e3c7465787420636c6173733d22742220783d223132352220793d22323237223e3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302036303020363030223e3c7374796c653e202e737b66696c6c3a77686974653b7374726f6b653a77686974653b7374726f6b652d77696474683a323b7374726f6b652d6d697465726c696d69743a31303b66696c6c2d6f7061636974793a302e313b7374726f6b652d6c696e656361703a726f756e647d2e73317b66696c6c2d6f7061636974793a302e337d2e73327b7374726f6b652d77696474683a317d2e747b2066696c6c3a77686974653b666f6e742d66616d696c793a73657269663b666f6e742d73697a653a323070783b7d2e6b7b666f6e742d7765696768743a626f6c643b746578742d616e63686f723a656e643b66696c6c3a236464643b7d2e6e7b666f6e742d73697a653a323270783b666f6e742d7765696768743a626f6c643b746578742d616e63686f723a6d6964646c657d2e6c7b66696c6c3a6e6f6e653b7374726f6b653a726762283233302c3233302c3233302c302e35293b7374726f6b652d77696474683a313b636c69702d706174683a75726c282363293b7d2e727b66696c6c3a7267626128302c302c302c302e35293b7374726f6b653a77686974653b7374726f6b652d77696474683a333b7d2e72317b7374726f6b652d77696474683a20317d202e617b66696c6c3a234646464646463b66696c6c2d6f7061636974793a302e313b7374726f6b653a234646464646463b7374726f6b652d77696474683a323b7374726f6b652d6d697465726c696d69743a31303b7d2e627b66696c6c3a6e6f6e653b7374726f6b653a234646464646463b7374726f6b652d77696474683a323b7374726f6b652d6d697465726c696d69743a31303b7d202e637b66696c6c3a234646464646463b66696c6c2d6f7061636974793a302e323b7374726f6b653a234646464646463b7374726f6b652d77696474683a323b7374726f6b652d6d697465726c696d69743a31303b7d202e647b66696c6c3a234646464646463b66696c6c2d6f7061636974793a302e333b7374726f6b653a234646464646463b7374726f6b652d77696474683a323b7374726f6b652d6d697465726c696d69743a31303b7d3c2f7374796c653e3c646566733e3c636c6970506174682069643d2263223e3c726563742077696474683d2236303022206865696768743d2236303022202f3e3c2f636c6970506174683e3c2f646566733e3c726563742077696474683d2236303022206865696768743d22363030222066696c6c3d223c2f746578743e3c7465787420636c6173733d2274206b2220783d223131352220793d22323637223e426179733a3c2f746578743e3c7465787420636c6173733d22742220783d223132352220793d22323637223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f222f3e3c706f6c796c696e6520636c6173733d226c2220706f696e74733d2234302c2d352034302c3630352038302c3630352038302c2d35203132302c2d35203132302c363035203136302c363035203136302c2d35203230302c2d35203230302c363035203234302c363035203234302c2d35203238302c2d35203238302c363035203332302c363035203332302c2d35203336302c2d35203336302c363035203430302c363035203430302c2d35203434302c2d35203434302c363035203438302c363035203438302c2d35203532302c2d35203532302c363035203536302c363035203536302c2d35203630302c2d35203630302c36303522202f3e3c706f6c796c696e6520636c6173733d226c2220706f696e74733d222d352c3430203630352c3430203630352c3830202d352c3830202d352c313230203630352c313230203630352c313630202d352c313630202d352c323030203630352c323030203630352c323430202d352c323430202d352c323830203630352c323830203630352c333230202d352c333230202d352c333630203630352c333630203630352c343030202d352c343030202d352c343430203630352c343430203630352c343830202d352c343830202d352c353230203630352c353230203630352c353630202d352c353630202d352c363030203630352c36303022202f3e3c7265637420636c6173733d22722220783d2231302220793d223130222077696474683d2235383022206865696768743d223530222072783d22313522202f3e3c7265637420636c6173733d226c20722072312220783d222d352220793d223830222077696474683d2232383522206865696768743d2235333522202f3e3c7465787420636c6173733d2274206e2220783d223330302220793d223432223e3c2f746578743e3c67207472616e73666f726d3d227472616e736c617465283434302c343430297363616c6528312e3229223e3c2f746578743e3c7465787420636c6173733d2274206b2220783d223131352220793d22313437223e5265673a3c2f746578743e3c7465787420636c6173733d22742220783d223132352220793d22313437223e23a2646970667358221220b1157b857733a2076ebc6dfc880d2e2c8a25afd9e96b72e77dcc242ccd753d7464736f6c634300080100333c7061746820636c6173733d22732220643d224d302e32362c39332e33336831342e333363302c302d302e37362d31312e34362d322e32372d33327331332e36342d37362e34372c31392e39352d39392e3937732d322e35322d36302e30332d33322d36302e303320732d33382e33312c33362e35342d33322c36302e30337332312e34362c37392e34332c31392e39352c39392e3937732d322e32372c33322d322e32372c333248302e3236222f3e3c7061746820636c6173733d22732220643d224d2d31322e392c37362e35376c2d34372e30322c362e30366c332e30332d31382e39356c34332e36342d32322e3432204d2d32362e33382d31382e34366c2d392e30392c31342e33317631392e33336c31342e37382d31302e38204d31332e34322c37362e3537206c34372e30322c362e30366c2d332e30332d31382e39354c31332e37372c34312e3235204d32312e32322c342e33374c33362c31352e3137562d342e31356c2d392e30392d31342e3331222f3e3c7061746820636c6173733d22732073312220643d224d2d33332e36362c34362e36336c2d312e38332c33392e3033682d31332e32346c2d312e38332d33392e303363302d342e36362c332e37382d382e34342c382e34342d382e343420432d33372e34342c33382e31382d33332e36362c34312e39362d33332e36362c34362e36337a204d33342e31392c34362e36336c312e38332c33392e30336831332e32346c312e38332d33392e303363302d342e36362d332e37382d382e34342d382e34342d382e3434204333372e39372c33382e31382c33342e31392c34312e39362c33342e31392c34362e36337a222f3e3c7061746820636c6173733d22732073312220643d224d2d31392e31382d37342e383363312e30342c312e382c302e39352c31372e31352c332e30332c323763312e35312c372e31342c342e30312c31352e39322c322e33382c31382e3134632d312e34332c312e39342d372e35392c312e32342d392e39352d312e333720632d332e34312d332e37382d342e31352d31302e35362d342e39332d31362e3637432d33302e31332d35392e33392d32322e33352d38302e33312d31392e31382d37342e38337a204d2d33372e39342c38352e3636682d372e39366c2d312e31362c352e34376831302e32384c2d33372e39342c38352e36367a204d2d31302e36352c39332e33336c2d312e33332c382e303548302e32366831322e32346c2d312e33332d382e3035204d302e32362d33342e363763302c302c312e38322c302c362e31322c3073372e34352d33322c372e30342d343353392e32382d38382e36362c302e32362d38382e363620732d31322e37352d302e30312d31332e31362c31302e3939632d302e34312c31312c322e37342c34332c372e30342c343353302e32362d33342e36372c302e32362d33342e36377a204d31392e37312d37342e3833632d312e30342c312e382d302e39352c31372e31352d332e30332c323720632d312e35312c372e31342d342e30312c31352e39322d322e33382c31382e313463312e34332c312e39342c372e35392c312e32342c392e39352d312e333763332e34312d332e37382c342e31352d31302e35362c342e39332d31362e3637204333302e36352d35392e33392c32322e38382d38302e33312c31392e37312d37342e38337a204d33372e332c39312e31336831302e32386c2d312e31362d352e3437682d372e39364c33372e332c39312e31337a222f3e3c7061746820636c6173733d22732220643d224d2d36312e37342c37372e3739682d31322e36315633322e33326831322e36315637372e37397a204d2d32382e30332c32362e36346c2d372e35382d31322e36337634342e313268372e35385632362e36347a204d2d302e36352c35322e35326831302e3939204c34312e34312c312e33364c32342e37342d31322e3636482d302e3635682d32352e33394c2d34322e37322c312e33366c33312e30372c35312e3136482d302e36357a204d36302e34332c37372e37396831322e36315633322e33324836302e34335637372e37397a204d32362e37332c35382e313468372e3538205631342e30326c2d372e35382c31322e36335635382e31347a222f3e3c7061746820636c6173733d22732220643d224d2d32332e38392c33322e353676342e3737682d34342e313556382e37356832392e3831204d2d35382e37362c31332e3736682d31382e35357631382e35356831382e35355631332e37367a204d32322e35392c33322e353676342e37376834342e313556382e3735204833362e3932204d35372e34362c33322e33326831382e35355631332e37364835372e34365633322e33327a204d352e37392c34362e39384c352e37392c34362e393863302d312e30372d302e38372d312e39342d312e39342d312e3934682d39632d312e30372c302d312e39342c302e38372d312e39342c312e393420763063302c312e30372c302e38372c312e39342c312e39342c312e3934683943342e39322c34382e39332c352e37392c34382e30362c352e37392c34362e39387a222f3e3c7061746820636c6173733d22732073312220643d224d2d37392e39322c39342e34335638362e31204d2d35362e30342c39342e34335638362e31204d37382e36312c39342e34335638362e31204d35342e37342c39342e34335638362e31204d2d31342e34382c352e33336832382e3034204d2d392e34352c312e312048382e3532222f3e3c7061746820636c6173733d22732073312220643d224d2d34342e31312c39342e3433682d34372e38375638322e373663302d322e37362c322e32342d352c352d356833372e383763322e37362c302c352c322e32342c352c355639342e34337a204d2d31392e38382c35372e3637762d362e31382063302d312e36342d312e33332d322e39372d322e39372d322e3937682d392e31357631322e313368392e3135432d32312e32322c36302e36352d31392e38382c35392e33322d31392e38382c35372e36377a204d34322e382c39342e34336834372e38375638322e373663302d322e37362d322e32342d352d352d35204834372e38632d322e37362c302d352c322e32342d352c355639342e34337a204d2d302e36352c33312e31316831342e30384c33332e34322c332e38364c32352e33392c322e326c2d382e39362c382e3833482d302e3635682d31372e30386c2d382e39362d382e38336c2d382e30342c312e3636206c31392e39392c32372e3235482d302e36357a204d32312e35352c36302e363568392e31355634382e3532682d392e3135632d312e36342c302d322e39372c312e33332d322e39372c322e393776362e31384331382e35382c35392e33322c31392e39312c36302e36352c32312e35352c36302e36357a222f3e3c7061746820636c6173733d22732073312220643d224d2d32362e30342d31322e36366c2d31312e31372c392e34762d32372e343668372e35316c31362e31372c31382e3036482d32362e30347a204d32342e37342d31322e36366c31312e31372c392e34762d32372e34364832382e344c31322e32332d31322e3636204832342e37347a222f3e3c7061746820636c6173733d22732073322220643d224d2d31392e38382c35322e3836682d332e3739204d2d31392e38382c35362e3436682d332e3739204d32322e33372c35322e3836682d332e3739204d31382e35382c35362e343668332e3739222f3e20203c7061746820636c6173733d22732073322220643d224d2d33392e36372c382e34316c2d312e35382c33332e3833682d31312e34376c2d312e35382d33332e383363302d342e30342c332e32382d372e33322c372e33322d372e3332432d34322e39352c312e312d33392e36372c342e33372d33392e36372c382e34317a204d2d34332e33382c34322e3234682d362e396c2d312e30312c342e373468382e39314c2d34332e33382c34322e32347a204d33382e33372c382e34316c312e35382c33332e38336831312e34374c35332c382e343163302d342e30342d332e32382d372e33322d372e33322d372e3332204334312e36342c312e312c33382e33372c342e33372c33382e33372c382e34317a204d34312e30362c34362e393868382e39316c2d312e30312d342e3734682d362e394c34312e30362c34362e39387a222f3e3c7061746820636c6173733d22732220643d224d35352e35322c36302e36326c2d3132352e38352c372e3135632d31332e33352c302e37362d32342e35392d392e38362d32342e35392d32332e3233763063302d31332e33372c31312e32342d32332e39392c32342e35392d32332e32336c3132352e38352c372e3135205636302e36327a222f3e3c7061746820636c6173733d22732220643d224d34382e33392c34322e327631302e32386c2d352e34372d312e3136762d372e39364c34382e33392c34322e327a204d36332e32362c32312e39324c36332e32362c32312e3932632d322e37352c302d342e38322c322e352d342e33312c352e32206c332e33332c31372e363168312e39376c332e33332d31372e36314336382e30392c32342e34322c36362e30312c32312e39322c36332e32362c32312e39327a204d36332e32362c36372e35354c36332e32362c36372e353563322e37352c302c342e38322d322e352c342e33312d352e326c2d332e33332d31372e363120682d312e39376c2d332e33332c31372e36314335382e34342c36352e30352c36302e35312c36372e35352c36332e32362c36372e35357a204d2d34342e39372c34332e36344c2d34342e39372c34332e363463302e37362c302e37362c312e39392c302e37362c322e37352c306c362e33362d362e33362063302e37362d302e37362c302e37362d312e39392c302d322e37356c302c30632d302e37362d302e37362d312e39392d302e37362d322e37352c306c2d362e33362c362e3336432d34352e37322c34312e36352d34352e37322c34322e38382d34342e39372c34332e36347a204d2d33342e38322c34332e3634204c2d33342e38322c34332e363463302e37362c302e37362c312e39392c302e37362c322e37352c306c362e33362d362e333663302e37362d302e37362c302e37362d312e39392c302d322e37356c302c30632d302e37362d302e37362d312e39392d302e37362d322e37352c306c2d362e33362c362e333620432d33352e35382c34312e36352d33352e35382c34322e38382d33342e38322c34332e36347a204d36332e32362c34332e3333682d372e373476322e383168372e37345634332e33337a222f3e3c7061746820636c6173733d22732220643d224d2d37312e34372c36322e37357631352e3733204d2d36352e36312c36322e37357632322e3933222f3e203c7061746820636c6173733d22732073312220643d224d35322e32342c36302e386c312e37322c31312e30346c31392e38392c342e3476362e32314c33382e392c38382e3339632d382e30392c312e33372d31352e35352d342e36382d31352e38372d31322e38386c2d302e35312d31332e3033204d35312e32342c32382e32204c36372e31362c322e35366c2d38302e32352d332e3136632d362e31362d302e32342d31322e31332c322e31362d31362e342c362e36316c2d31362e30332c31362e3639222f3e3c7061746820636c6173733d22732073312220643d224d332e38392c33392e30396c33392e30332c312e38337631332e32344c332e38392c35352e3938632d342e36362c302d382e34342d332e37382d382e34342d382e3434432d342e35362c34322e38372d302e37382c33392e30392c332e38392c33392e30397a204d2d34322e37342c33312e31316c2d33312e34392d312e3236632d352e37332c302d31302e37352c332e38312d31322e332c392e33336c2d302e36372c352e33366832392e30314c2d34322e37342c33312e31317a204d33302e30332c34372e35334c33302e30332c34372e35332063302d312e30372d302e38372d312e39342d312e39342d312e3934682d39632d312e30372c302d312e39342c302e38372d312e39342c312e3934763063302c312e30372c302e38372c312e39342c312e39342c312e393468394332392e31362c34392e34372c33302e30332c34382e362c33302e30332c34372e35337a222f3e3c7061746820636c6173733d22732220643d224d2d34312e30352c36342e3338482d37362e33632d392e38332c302d31372e37392d372e39382d31372e37372d31372e386c302e30322d372e39366c35332d33312e33345636342e33387a204d2d33332e34392c32312e39347633362e33396c31322e39362c392e36342063372e30312c352e32322c31352e35322c382e30332c32342e32362c382e30336835302e353456372e32396c2d31322d322e33394332372e39382c322e30352c31332e31392c332e342d302e33342c382e37374c2d33332e34392c32312e39347a222f3e203c7061746820636c6173733d22732220643d224d2d35332e37342c34392e36376c39332e382d31372e3238204d2d35332e37342c39362e33386839392e3836204d2d36302e33372c34342e36354c2d36302e33372c34342e363563302d312e30372d302e38372d312e39342d312e39342d312e3934682d3920632d312e30372c302d312e39342c302e38372d312e39342c312e3934763063302c312e30372c302e38372c312e39342c312e39342c312e39346839432d36312e32342c34362e35392d36302e33372c34352e37322d36302e33372c34342e36357a204d2d36302e33372c33372e37384c2d36302e33372c33372e37382063302d312e30372d302e38372d312e39342d312e39342d312e3934682d39632d312e30372c302d312e39342c302e38372d312e39342c312e3934763063302c312e30372c302e38372c312e39342c312e39342c312e39346839432d36312e32342c33392e37322d36302e33372c33382e38352d36302e33372c33372e3738207a204d2d33332e34392c32362e3333682d372e35367632372e393268372e35365632362e33337a222f3e3c7061746820636c6173733d22732073312220643d224d2d302e32392c33302e3833762d3963302d312e30372c302e38372d312e39342c312e39342d312e3934683063312e30372c302c312e39342c302e38372c312e39342c312e3934763963302c312e30372d302e38372c312e39342d312e39342c312e393468302043302e35382c33322e37372d302e32392c33312e392d302e32392c33302e38337a204d312e34372d302e3134632d342e36362c302d382e34342c332e37382d382e34342c382e34346c312e38332c33392e303348382e30384c392e39312c382e332043392e39312c332e36342c362e31332d302e31342c312e34372d302e31347a222f3e203c7061746820636c6173733d22732073312220643d224d34322e32362c33322e3338632d31372e36372c302d33322c31342e33332d33322c33327331342e33332c33322c33322c33327333322d31342e33332c33322d33325335392e39342c33322e33382c34322e32362c33322e33387a204d34322e32362c38392e393820632d31342e31342c302d32352e362d31312e34362d32352e362d32352e367331312e34362d32352e362c32352e362d32352e367332352e362c31312e34362c32352e362c32352e365335362e342c38392e39382c34322e32362c38392e39387a204d2d35312e37342c34392e353720632d31322e39332c302d32332e342c31302e34382d32332e342c32332e343163302c31322e39332c31302e34382c32332e342c32332e342c32332e347332332e342d31302e34382c32332e342d32332e34432d32382e33332c36302e30352d33382e38312c34392e35372d35312e37342c34392e35377a204d2d35312e37342c39312e37632d31302e33342c302d31382e37322d382e33382d31382e37322d31382e373263302d31302e33342c382e33382d31382e37322c31382e37322d31382e37327331382e37322c382e33382c31382e37322c31382e373220432d33332e30312c38332e33322d34312e342c39312e372d35312e37342c39312e377a204d2d34362e33352c32392e3032682d31342e37386c31342e342d31302e36314c2d34362e33352c32392e30327a204d362e382c35322e3831482d332e34396c312e31362d352e343768372e39364c362e382c35322e38317a204d35342e32362c32302e336c392d337631382e39376c2d392d332e3238204d35342e32362c35332e30346c392d337631382e39376c2d392d332e3238222f3e

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100575760003560e01c80630a8578211461005c5780632901237c146100855780636082e3a2146100985780636ba0383a146100ab578063bec11c63146100be575b600080fd5b61006f61006a366004610e00565b6100d1565b60405161007c9190611342565b60405180910390f35b61006f610093366004610ea8565b610382565b61006f6100a6366004610ea8565b61043a565b61006f6100b9366004610e00565b610460565b61006f6100cc366004610de8565b610a37565b6060600060058660ff16600f81106100f957634e487b7160e01b600052603260045260246000fd5b01805461010590611407565b80601f016020809104026020016040519081016040528092919081815260200182805461013190611407565b801561017e5780601f106101535761010080835404028352916020019161017e565b820191906000526020600020905b81548152906001019060200180831161016157829003601f168201915b505050505090506000610195898989898989610460565b905060006101a28a610ad7565b86866040516020016101b6939291906110b2565b60408051601f19818403018152828201909152600e82526d526567697374726174696f6e202360901b602083015291506000906101fb906101f68d610ad7565b610bfa565b6102cf60405180604001604052806005815260200164436c61737360d81b81525060008d60ff166005811061024057634e487b7160e01b600052603260045260246000fd5b01805461024c90611407565b80601f016020809104026020016040519081016040528092919081815260200182805461027890611407565b80156102c55780601f1061029a576101008083540402835291602001916102c5565b820191906000526020600020905b8154815290600101906020018083116102a857829003601f168201915b5050505050610c26565b6102fb604051806040016040528060048152602001634261797360e01b8152506101f68c60ff16610ad7565b6103226040518060400160405280600581526020016421b7b637b960d91b81525088610c26565b8587604051602001610339969594939291906111de565b604051602081830303815290604052905061035381610c3b565b60405160200161036391906112b8565b6040516020818303038152906040529450505050509695505050505050565b606060008260ff16600581106103a857634e487b7160e01b600052603260045260246000fd5b0180546103b490611407565b80601f01602080910402602001604051908101604052809291908181526020018280546103e090611407565b801561042d5780601f106104025761010080835404028352916020019161042d565b820191906000526020600020905b81548152906001019060200180831161041057829003601f168201915b505050505090505b919050565b606060058260ff16600f81106103a857634e487b7160e01b600052603260045260246000fd5b6060600061046d88610ad7565b9050600061047d8660ff16610ad7565b9050610487610daf565b6040518061040001604052806103db815260200161154a6103db91398152601460ff8916600f81106104c957634e487b7160e01b600052603260045260246000fd5b0180546104d590611407565b80601f016020809104026020016040519081016040528092919081815260200182805461050190611407565b801561054e5780601f106105235761010080835404028352916020019161054e565b820191906000526020600020905b81548152906001019060200180831161053157829003601f168201915b5050505050816001600f811061057457634e487b7160e01b600052603260045260246000fd5b6020020181905250604051806102c0016040528061029a81526020016119ba61029a913960408083019190915280516020601f8801819004810282018101909252868152908790879081908401838280828437600092019190915250849250600391506105de9050565b6020020181905250604051806080016040528060558152602001611c876055913960808083019190915260a08201849052604080519182019052605680825261149e602083013960c0820152600060ff8a166005811061064e57634e487b7160e01b600052603260045260246000fd5b01805461065a90611407565b80601f016020809104026020016040519081016040528092919081815260200182805461068690611407565b80156106d35780601f106106a8576101008083540402835291602001916106d3565b820191906000526020600020905b8154815290600101906020018083116106b657829003601f168201915b5050505050816007600f81106106f957634e487b7160e01b600052603260045260246000fd5b60200201819052506040518060800160405280605681526020016114f460569139610100820152600560ff8916600f811061074457634e487b7160e01b600052603260045260246000fd5b01805461075090611407565b80601f016020809104026020016040519081016040528092919081815260200182805461077c90611407565b80156107c95780601f1061079e576101008083540402835291602001916107c9565b820191906000526020600020905b8154815290600101906020018083116107ac57829003601f168201915b5050505050816009600f81106107ef57634e487b7160e01b600052603260045260246000fd5b602002018190525060405180608001604052806055815260200161192560559139610140820152610160810182905260408051606081019091526033808252611c546020830139610180820152600460ff8a16101561091d5760238960ff166004811061086c57634e487b7160e01b600052603260045260246000fd5b01805461087890611407565b80601f01602080910402602001604051908101604052809291908181526020018280546108a490611407565b80156108f15780601f106108c6576101008083540402835291602001916108f1565b820191906000526020600020905b8154815290600101906020018083116108d457829003601f168201915b505050505081600d600f811061091757634e487b7160e01b600052603260045260246000fd5b60200201525b604080518082018252600a8152691e17b39f1e17b9bb339f60b11b6020808301919091526101c0840191909152825183820151848401516060860151608087015160a088015160c089015160e08a01516101008b0151995160009a6109849a909101610ff0565b60408051808303601f19018152908290526101208401516101408501516101608601516101808701516101a08801516101c08901519597506000966109cc9690602001610f71565b6040516020818303038152906040529050610a0782826040516020016109f3929190610f42565b604051602081830303815290604052610c3b565b604051602001610a1791906112fd565b604051602081830303815290604052955050505050509695505050505050565b60238160048110610a4757600080fd5b018054909150610a5690611407565b80601f0160208091040260200160405190810160405280929190818152602001828054610a8290611407565b8015610acf5780601f10610aa457610100808354040283529160200191610acf565b820191906000526020600020905b815481529060010190602001808311610ab257829003601f168201915b505050505081565b606081610afc57506040805180820190915260018152600360fc1b6020820152610435565b8160005b8115610b265780610b1081611442565b9150610b1f9050600a8361138d565b9150610b00565b60008167ffffffffffffffff811115610b4f57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015610b79576020820181803683370190505b5090505b8415610bf257610b8e6001836113c0565b9150610b9b600a8661145d565b610ba6906030611375565b60f81b818381518110610bc957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350610beb600a8661138d565b9450610b7d565b949350505050565b60608282604051602001610c0f92919061116f565b604051602081830303815290604052905092915050565b60608282604051602001610c0f9291906110fe565b805160609080610c5b575050604080516020810190915260008152610435565b60006003610c6a836002611375565b610c74919061138d565b610c7f9060046113a1565b90506000610c8e826020611375565b67ffffffffffffffff811115610cb457634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015610cde576020820181803683370190505b509050600060405180606001604052806040815260200161197a604091399050600181016020830160005b86811015610d6a576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b835260049092019101610d09565b506003860660018114610d845760028114610d9557610da1565b613d3d60f01b600119830152610da1565b603d60f81b6000198301525b505050918152949350505050565b604051806101e00160405280600f905b6060815260200190600190039081610dbf5790505090565b803560ff8116811461043557600080fd5b600060208284031215610df9578081fd5b5035919050565b60008060008060008060a08789031215610e18578182fd5b86359550610e2860208801610dd7565b9450610e3660408801610dd7565b9350610e4460608801610dd7565b9250608087013567ffffffffffffffff80821115610e60578384fd5b818901915089601f830112610e73578384fd5b813581811115610e81578485fd5b8a6020828501011115610e92578485fd5b6020830194508093505050509295509295509295565b600060208284031215610eb9578081fd5b610ec282610dd7565b9392505050565b60008151610edb8185602086016113d7565b9290920192915050565b61227d60f01b815260020190565b7f222c226465736372697074696f6e223a224275696c6420506c616e7320666f7281527f2061204d6f6f6e4361742053706163656372616674222c22696d616765223a22602082015260400190565b60008351610f548184602088016113d7565b835190830190610f688183602088016113d7565b01949350505050565b600087516020610f848285838d016113d7565b885191840191610f978184848d016113d7565b8851920191610fa98184848c016113d7565b8751920191610fbb8184848b016113d7565b8651920191610fcd8184848a016113d7565b8551920191610fdf81848489016113d7565b919091019998505050505050505050565b60008a51611002818460208f016113d7565b8a5190830190611016818360208f016113d7565b8a516110288183850160208f016113d7565b8a5192909101019061103e818360208d016113d7565b88516110508183850160208d016113d7565b8851929091010190611066818360208b016113d7565b86516110788183850160208b016113d7565b865192909101019061108e8183602089016113d7565b84516110a081838501602089016113d7565b9101019b9a5050505050505050505050565b60006a4c6f6f747072696e74202360a81b825284516110d881600b8501602089016113d7565b6101d160f51b600b918401918201528385600d830137909201600d019182525092915050565b6e3d913a3930b4ba2fba3cb832911d1160891b8152825160009061112981600f8501602088016113d7565b6a1116113b30b63ab2911d1160a91b600f91840191820152835161115481601a8401602088016113d7565b61227d60f01b601a9290910191820152601c01949350505050565b6e3d913a3930b4ba2fba3cb832911d1160891b8152825160009061119a81600f8501602088016113d7565b691116113b30b63ab2911d60b11b600f9184019182015283516111c48160198401602088016113d7565b607d60f81b60199290910191820152601a01949350505050565b607b60f81b81526d2261747472696275746573223a5b60901b6001820152865160009061121281600f850160208c016113d7565b8083019050600b60fa1b80600f8301528851611235816010850160208d016113d7565b601092019182018190528751611252816011850160208c016113d7565b6011920191820152855161126d816012840160208a016113d7565b692e96113730b6b2911d1160b11b601292909101918201526112ab6112a66112a061129b601c850189610ec9565b610ef3565b86610ec9565b610ee5565b9998505050505050505050565b60007f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000825282516112f081601d8501602087016113d7565b91909101601d0192915050565b60007f646174613a696d6167652f7376672b786d6c3b6261736536342c0000000000008252825161133581601a8501602087016113d7565b91909101601a0192915050565b60006020825282518060208401526113618160408501602087016113d7565b601f01601f19169190910160400192915050565b6000821982111561138857611388611471565b500190565b60008261139c5761139c611487565b500490565b60008160001904831182151516156113bb576113bb611471565b500290565b6000828210156113d2576113d2611471565b500390565b60005b838110156113f25781810151838201526020016113da565b83811115611401576000848401525b50505050565b60028104600182168061141b57607f821691505b6020821081141561143c57634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561145657611456611471565b5060010190565b60008261146c5761146c611487565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fdfe3c2f746578743e3c7465787420636c6173733d2274206b2220783d223131352220793d22313837223e436c6173733a3c2f746578743e3c7465787420636c6173733d22742220783d223132352220793d22313837223e3c2f746578743e3c7465787420636c6173733d2274206b2220783d223131352220793d22323237223e436f6c6f723a3c2f746578743e3c7465787420636c6173733d22742220783d223132352220793d22323237223e3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302036303020363030223e3c7374796c653e202e737b66696c6c3a77686974653b7374726f6b653a77686974653b7374726f6b652d77696474683a323b7374726f6b652d6d697465726c696d69743a31303b66696c6c2d6f7061636974793a302e313b7374726f6b652d6c696e656361703a726f756e647d2e73317b66696c6c2d6f7061636974793a302e337d2e73327b7374726f6b652d77696474683a317d2e747b2066696c6c3a77686974653b666f6e742d66616d696c793a73657269663b666f6e742d73697a653a323070783b7d2e6b7b666f6e742d7765696768743a626f6c643b746578742d616e63686f723a656e643b66696c6c3a236464643b7d2e6e7b666f6e742d73697a653a323270783b666f6e742d7765696768743a626f6c643b746578742d616e63686f723a6d6964646c657d2e6c7b66696c6c3a6e6f6e653b7374726f6b653a726762283233302c3233302c3233302c302e35293b7374726f6b652d77696474683a313b636c69702d706174683a75726c282363293b7d2e727b66696c6c3a7267626128302c302c302c302e35293b7374726f6b653a77686974653b7374726f6b652d77696474683a333b7d2e72317b7374726f6b652d77696474683a20317d202e617b66696c6c3a234646464646463b66696c6c2d6f7061636974793a302e313b7374726f6b653a234646464646463b7374726f6b652d77696474683a323b7374726f6b652d6d697465726c696d69743a31303b7d2e627b66696c6c3a6e6f6e653b7374726f6b653a234646464646463b7374726f6b652d77696474683a323b7374726f6b652d6d697465726c696d69743a31303b7d202e637b66696c6c3a234646464646463b66696c6c2d6f7061636974793a302e323b7374726f6b653a234646464646463b7374726f6b652d77696474683a323b7374726f6b652d6d697465726c696d69743a31303b7d202e647b66696c6c3a234646464646463b66696c6c2d6f7061636974793a302e333b7374726f6b653a234646464646463b7374726f6b652d77696474683a323b7374726f6b652d6d697465726c696d69743a31303b7d3c2f7374796c653e3c646566733e3c636c6970506174682069643d2263223e3c726563742077696474683d2236303022206865696768743d2236303022202f3e3c2f636c6970506174683e3c2f646566733e3c726563742077696474683d2236303022206865696768743d22363030222066696c6c3d223c2f746578743e3c7465787420636c6173733d2274206b2220783d223131352220793d22323637223e426179733a3c2f746578743e3c7465787420636c6173733d22742220783d223132352220793d22323637223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f222f3e3c706f6c796c696e6520636c6173733d226c2220706f696e74733d2234302c2d352034302c3630352038302c3630352038302c2d35203132302c2d35203132302c363035203136302c363035203136302c2d35203230302c2d35203230302c363035203234302c363035203234302c2d35203238302c2d35203238302c363035203332302c363035203332302c2d35203336302c2d35203336302c363035203430302c363035203430302c2d35203434302c2d35203434302c363035203438302c363035203438302c2d35203532302c2d35203532302c363035203536302c363035203536302c2d35203630302c2d35203630302c36303522202f3e3c706f6c796c696e6520636c6173733d226c2220706f696e74733d222d352c3430203630352c3430203630352c3830202d352c3830202d352c313230203630352c313230203630352c313630202d352c313630202d352c323030203630352c323030203630352c323430202d352c323430202d352c323830203630352c323830203630352c333230202d352c333230202d352c333630203630352c333630203630352c343030202d352c343030202d352c343430203630352c343430203630352c343830202d352c343830202d352c353230203630352c353230203630352c353630202d352c353630202d352c363030203630352c36303022202f3e3c7265637420636c6173733d22722220783d2231302220793d223130222077696474683d2235383022206865696768743d223530222072783d22313522202f3e3c7265637420636c6173733d226c20722072312220783d222d352220793d223830222077696474683d2232383522206865696768743d2235333522202f3e3c7465787420636c6173733d2274206e2220783d223330302220793d223432223e3c2f746578743e3c67207472616e73666f726d3d227472616e736c617465283434302c343430297363616c6528312e3229223e3c2f746578743e3c7465787420636c6173733d2274206b2220783d223131352220793d22313437223e5265673a3c2f746578743e3c7465787420636c6173733d22742220783d223132352220793d22313437223e23a2646970667358221220b1157b857733a2076ebc6dfc880d2e2c8a25afd9e96b72e77dcc242ccd753d7464736f6c63430008010033

Deployed Bytecode Sourcemap

226:14249:1:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12619:1291;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;513:119;;;;;;:::i;:::-;;:::i;1074:::-;;;;;;:::i;:::-;;:::i;8308:3489::-;;;;;;:::i;:::-;;:::i;1954:6261::-;;;;;;:::i;:::-;;:::i;12619:1291::-;12773:13;12799:23;12825:11;12837:7;12825:20;;;;;;;-1:-1:-1;;;12825:20:1;;;;;;;;;;12799:46;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12856:17;12876:55;12885:11;12898:7;12907;12916:4;12922:8;;12876;:55::i;:::-;12856:75;;12942:22;12999:21;13008:11;12999:8;:21::i;:::-;13028:8;;12967:70;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;12967:70:1;;;;;;13202:56;;;;;;;;;-1:-1:-1;;;12967:70:1;13202:56;;;12967:70;-1:-1:-1;13048:17:1;;13202:56;;13236:21;13245:11;13236:8;:21::i;:::-;13202:15;:56::i;:::-;13311:52;;;;;;;;;;;;;;-1:-1:-1;;;13311:52:1;;;13342:11;13354:7;13342:20;;;;;;;-1:-1:-1;;;13342:20:1;;;;;;;;;;13311:52;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:21;:52::i;:::-;13416:39;;;;;;;;;;;;;;-1:-1:-1;;;13416:39:1;;;13440:14;13449:4;13440:14;;:8;:14::i;13416:39::-;13508:41;;;;;;;;;;;;;;-1:-1:-1;;;13508:41:1;;;13539:9;13508:21;:41::i;:::-;13614:9;13747:3;13068:736;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;13048:756;;13879:19;13893:4;13879:13;:19::i;:::-;13829:70;;;;;;;;:::i;:::-;;;;;;;;;;;;;13815:85;;;;;;12619:1291;;;;;;;;:::o;513:119::-;571:13;604:11;616:7;604:20;;;;;;;-1:-1:-1;;;604:20:1;;;;;;;;;;597:27;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;513:119;;;;:::o;1074:::-;1132:13;1165:11;1177:7;1165:20;;;;;;;-1:-1:-1;;;1165:20:1;;;;;;;;8308:3489;8464:13;8497:20;8520:21;8529:11;8520:8;:21::i;:::-;8497:44;;8552:21;8576:14;8585:4;8576:14;;:8;:14::i;:::-;8552:38;;8603:23;;:::i;:::-;8637:1017;;;;;;;;;;;;;;;;;;;9676:11;:20;;;;;;;;-1:-1:-1;;;9676:20:1;;;;;;;;;;9665:31;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:5;9671:1;9665:8;;;;;-1:-1:-1;;;9665:8:1;;;;;;;;;;;;:31;;;;9707:716;;;;;;;;;;;;;;;;;:8;;;;:716;;;;10434:19;;9707:8;10434:19;;;;;;;;;;;;;;;;;;;10445:8;;;;;;10434:19;;10445:8;;;;10434:19;;;;;;;;;-1:-1:-1;10434:5:1;;-1:-1:-1;10440:1:1;;-1:-1:-1;10434:8:1;;-1:-1:-1;10434:8:1;;;;;:19;;;;10464:110;;;;;;;;;;;;;;;;;:8;;;;:110;;;;10585:8;;;:17;;;10613:111;;;;;;;;;;;;;10464:8;10613:111;;;:8;;;:111;10746:11;:20;;;;;;;;-1:-1:-1;;;10746:20:1;;;;;;;;;;10735:31;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:5;10741:1;10735:8;;;;;-1:-1:-1;;;10735:8:1;;;;;;;;;;;;:31;;;;10777:111;;;;;;;;;;;;;;;;;:8;;;:111;10910:11;:20;;;;;;;;-1:-1:-1;;;10910:20:1;;;;;;;;;;10899:31;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:5;10905:1;10899:8;;;;;-1:-1:-1;;;10899:8:1;;;;;;;;;;;;:31;;;;10941:111;;;;;;;;;;;;;;;;;:9;;;:111;11063:9;;;:19;;;11093:67;;;;;;;;;;;;;;10941:9;11093:67;;;:9;;;:67;11185:1;11175:11;;;;11171:76;;;11215:11;11227:7;11215:20;;;;;;;-1:-1:-1;;;11215:20:1;;;;;;;;;;11203:32;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:5;11209:2;11203:9;;;;;-1:-1:-1;;;11203:9:1;;;;;;;;;;;;:32;11171:76;11257:24;;;;;;;;;;;-1:-1:-1;;;11257:24:1;;;;;;;;:9;;;:24;;;;11331:8;;11341;;;;11351;;;;11407;;;;11417;;;;11427;;;;11483;;;;11493;;;;11503;;;;11314:198;;-1:-1:-1;;11314:198:1;;11503:8;;11314:198;;:::i;:::-;;;;;;;-1:-1:-1;;11314:198:1;;;;;;;11560:8;;;;11570:9;;;;11581;;;;11638;;;;11649;;;;11660;;;;11314:198;;-1:-1:-1;11523:17:1;;11543:127;;11660:9;11560:8;11543:127;;:::i;:::-;;;;;;;;;;;;;11523:147;;11744:43;11775:4;11781;11758:28;;;;;;;;;:::i;:::-;;;;;;;;;;;;;11744:13;:43::i;:::-;11697:91;;;;;;;;:::i;:::-;;;;;;;;;;;;;11683:106;;;;;;;8308:3489;;;;;;;;:::o;1954:6261::-;;;;;;;;;;;;;;;;;-1:-1:-1;1954:6261:1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;13941:529::-;13994:13;14024:10;14020:53;;-1:-1:-1;14051:10:1;;;;;;;;;;;;-1:-1:-1;;;14051:10:1;;;;;;14020:53;14098:5;14083:12;14139:78;14146:9;;14139:78;;14172:8;;;;:::i;:::-;;-1:-1:-1;14195:10:1;;-1:-1:-1;14203:2:1;14195:10;;:::i;:::-;;;14139:78;;;14227:19;14259:6;14249:17;;;;;;-1:-1:-1;;;14249:17:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;14249:17:1;;14227:39;;14277:154;14284:10;;14277:154;;14311:11;14321:1;14311:11;;:::i;:::-;;-1:-1:-1;14380:10:1;14388:2;14380:5;:10;:::i;:::-;14367:24;;:2;:24;:::i;:::-;14354:39;;14337:6;14344;14337:14;;;;;;-1:-1:-1;;;14337:14:1;;;;;;;;;;;;:56;-1:-1:-1;;;;;14337:56:1;;;;;;;;-1:-1:-1;14408:11:1;14417:2;14408:11;;:::i;:::-;;;14277:154;;;14455:6;13941:529;-1:-1:-1;;;;13941:529:1:o;11942:206::-;12030:13;12109:3;12129:5;12070:69;;;;;;;;;:::i;:::-;;;;;;;;;;;;;12056:84;;11942:206;;;;:::o;12295:216::-;12389:13;12468:3;12490:5;12429:73;;;;;;;;;:::i;14826:1624::-;14924:11;;14884:13;;14950:8;14946:23;;-1:-1:-1;;14960:9:1;;;;;;;;;-1:-1:-1;14960:9:1;;;;14946:23;15021:18;15059:1;15048:7;:3;15054:1;15048:7;:::i;:::-;15047:13;;;;:::i;:::-;15042:19;;:1;:19;:::i;:::-;15021:40;-1:-1:-1;15119:19:1;15151:15;15021:40;15164:2;15151:15;:::i;:::-;15141:26;;;;;;-1:-1:-1;;;15141:26:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;15141:26:1;;15119:48;;15180:18;15201:5;;;;;;;;;;;;;;;;;15180:26;;15270:1;15263:5;15259:13;15319:2;15311:6;15307:15;15379:1;15342:738;15406:3;15403:1;15400:10;15342:738;;;15457:1;15496:12;;;;;15490:19;15587:4;15575:2;15571:14;;;;;15553:40;;15547:47;15688:2;15684:14;;;15680:25;;15666:40;;15660:47;15809:1;15805:13;;;15801:24;;15787:39;;15781:46;15921:16;;;;15907:31;;15901:38;15619:1;15615:11;;;15709:4;15656:58;;;15647:68;15736:11;;15777:57;;;15768:67;;;;15856:11;;15897:49;;15888:59;15972:3;15968:13;15997:22;;16063:1;16048:17;;;;15450:9;15342:738;;;15346:53;16112:1;16107:3;16103:11;16147:1;16142:106;;;;16267:1;16262:86;;;;16096:252;;16142:106;-1:-1:-1;;;;;16193:17:1;;16186:43;16142:106;;16262:86;-1:-1:-1;;;;;16299:17:1;;16292:41;16096:252;-1:-1:-1;;;16364:26:1;;;;14826:1624;-1:-1:-1;;;;14826:1624:1:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:158:2:-;82:20;;142:4;131:16;;121:27;;111:2;;162:1;159;152:12;177:190;;289:2;277:9;268:7;264:23;260:32;257:2;;;310:6;302;295:22;257:2;-1:-1:-1;338:23:2;;247:120;-1:-1:-1;247:120:2:o;372:928::-;;;;;;;566:3;554:9;545:7;541:23;537:33;534:2;;;588:6;580;573:22;534:2;629:9;616:23;606:33;;658:38;692:2;681:9;677:18;658:38;:::i;:::-;648:48;;715:38;749:2;738:9;734:18;715:38;:::i;:::-;705:48;;772:38;806:2;795:9;791:18;772:38;:::i;:::-;762:48;;861:3;850:9;846:19;833:33;885:18;926:2;918:6;915:14;912:2;;;947:6;939;932:22;912:2;990:6;979:9;975:22;965:32;;1035:7;1028:4;1024:2;1020:13;1016:27;1006:2;;1062:6;1054;1047:22;1006:2;1107;1094:16;1133:2;1125:6;1122:14;1119:2;;;1154:6;1146;1139:22;1119:2;1204:7;1199:2;1190:6;1186:2;1182:15;1178:24;1175:37;1172:2;;;1230:6;1222;1215:22;1172:2;1266;1262;1258:11;1248:21;;1288:6;1278:16;;;;;524:776;;;;;;;;:::o;1305:194::-;;1415:2;1403:9;1394:7;1390:23;1386:32;1383:2;;;1436:6;1428;1421:22;1383:2;1464:29;1483:9;1464:29;:::i;:::-;1454:39;1373:126;-1:-1:-1;;;1373:126:2:o;1504:186::-;;1585:5;1579:12;1600:52;1645:6;1640:3;1633:4;1626:5;1622:16;1600:52;:::i;:::-;1668:16;;;;;1555:135;-1:-1:-1;;1555:135:2:o;1695:127::-;-1:-1:-1;;;1762:27:2;;1814:1;1805:11;;1752:70::o;1827:277::-;1906:66;1894:79;;2003:66;1998:2;1989:12;;1982:88;2095:2;2086:12;;1884:220::o;2109:466::-;;2322:6;2316:13;2338:53;2384:6;2379:3;2372:4;2364:6;2360:17;2338:53;:::i;:::-;2454:13;;2413:16;;;;2476:57;2454:13;2413:16;2510:4;2498:17;;2476:57;:::i;:::-;2549:20;;2292:283;-1:-1:-1;;;;2292:283:2:o;2580:1257::-;;2989:6;2983:13;3015:4;3028:51;3072:6;3067:3;3062:2;3054:6;3050:15;3028:51;:::i;:::-;3142:13;;3101:16;;;;3164:55;3142:13;3101:16;3186:15;;;3164:55;:::i;:::-;3286:13;;3241:20;;;3308:55;3286:13;3241:20;3330:15;;;3308:55;:::i;:::-;3430:13;;3385:20;;;3452:55;3430:13;3385:20;3474:15;;;3452:55;:::i;:::-;3574:13;;3529:20;;;3596:55;3574:13;3529:20;3618:15;;;3596:55;:::i;:::-;3718:13;;3673:20;;;3740:55;3718:13;3673:20;3762:15;;;3740:55;:::i;:::-;3811:20;;;;;2959:878;-1:-1:-1;;;;;;;;;2959:878:2:o;3842:1780::-;;4395:6;4389:13;4411:53;4457:6;4452:3;4445:4;4437:6;4433:17;4411:53;:::i;:::-;4527:13;;4486:16;;;;4549:57;4527:13;4486:16;4583:4;4571:17;;4549:57;:::i;:::-;4637:6;4631:13;4653:72;4716:8;4705;4698:5;4694:20;4687:4;4679:6;4675:17;4653:72;:::i;:::-;4807:13;;4751:20;;;;4747:35;;4829:57;4807:13;4747:35;4863:4;4851:17;;4829:57;:::i;:::-;4917:6;4911:13;4933:72;4996:8;4985;4978:5;4974:20;4967:4;4959:6;4955:17;4933:72;:::i;:::-;5087:13;;5031:20;;;;5027:35;;5109:57;5087:13;5027:35;5143:4;5131:17;;5109:57;:::i;:::-;5197:6;5191:13;5213:72;5276:8;5265;5258:5;5254:20;5247:4;5239:6;5235:17;5213:72;:::i;:::-;5367:13;;5311:20;;;;5307:35;;5389:57;5367:13;5307:35;5423:4;5411:17;;5389:57;:::i;:::-;5477:6;5471:13;5493:72;5556:8;5545;5538:5;5534:20;5527:4;5519:6;5515:17;5493:72;:::i;:::-;5585:20;;5581:35;;4365:1257;-1:-1:-1;;;;;;;;;;;4365:1257:2:o;5627:752::-;;-1:-1:-1;;;6043:3:2;6036:26;6091:6;6085:13;6107:62;6162:6;6157:2;6152:3;6148:12;6141:4;6133:6;6129:17;6107:62;:::i;:::-;-1:-1:-1;;;6228:2:2;6188:16;;;6220:11;;;6213:25;6281:6;6273;6268:2;6260:11;;6247:41;6311:15;;;6328:2;6307:24;6340:15;;;-1:-1:-1;6307:24:2;6026:353;-1:-1:-1;;6026:353:2:o;6384:984::-;-1:-1:-1;;;6884:55:2;;6962:13;;6384:984;;6984:62;6962:13;7034:2;7025:12;;7018:4;7006:17;;6984:62;:::i;:::-;-1:-1:-1;;;7105:2:2;7065:16;;;7097:11;;;7090:55;7170:13;;7192:63;7170:13;7241:2;7233:11;;7226:4;7214:17;;7192:63;:::i;:::-;-1:-1:-1;;;7315:2:2;7274:17;;;;7307:11;;;7300:35;7359:2;7351:11;;6874:494;-1:-1:-1;;;;6874:494:2:o;7373:971::-;-1:-1:-1;;;7873:55:2;;7951:13;;7373:971;;7973:62;7951:13;8023:2;8014:12;;8007:4;7995:17;;7973:62;:::i;:::-;-1:-1:-1;;;8094:2:2;8054:16;;;8086:11;;;8079:53;8157:13;;8179:63;8157:13;8228:2;8220:11;;8213:4;8201:17;;8179:63;:::i;:::-;-1:-1:-1;;;8302:2:2;8261:17;;;;8294:11;;;8287:24;8335:2;8327:11;;7863:481;-1:-1:-1;;;;7863:481:2:o;8349:2196::-;-1:-1:-1;;;9544:16:2;;-1:-1:-1;;;9585:1:2;9576:11;;9569:61;9653:13;;8349:2196;;9675:62;9653:13;9725:2;9716:12;;9709:4;9697:17;;9675:62;:::i;:::-;9765:6;9760:3;9756:16;9746:26;;-1:-1:-1;;;9823:2:2;9818;9814;9810:11;9803:23;9857:6;9851:13;9873:63;9927:8;9922:2;9918;9914:11;9907:4;9899:6;9895:17;9873:63;:::i;:::-;9996:2;9955:17;;9988:11;;;9981:23;;;10029:13;;10051:63;10029:13;10100:2;10092:11;;10085:4;10073:17;;10051:63;:::i;:::-;10174:2;10133:17;;10166:11;;;10159:23;10207:13;;10229:63;10207:13;10278:2;10270:11;;10263:4;10251:17;;10229:63;:::i;:::-;-1:-1:-1;;;10352:2:2;10311:17;;;;10344:11;;;10337:53;10406:133;10438:100;10465:72;10497:39;10532:2;10524:11;;10516:6;10497:39;:::i;:::-;10465:72;:::i;:::-;10457:6;10438:100;:::i;:::-;10406:133;:::i;:::-;10399:140;9534:1011;-1:-1:-1;;;;;;;;;9534:1011:2:o;10550:448::-;;10812:31;10807:3;10800:44;10873:6;10867:13;10889:62;10944:6;10939:2;10934:3;10930:12;10923:4;10915:6;10911:17;10889:62;:::i;:::-;10971:16;;;;10989:2;10967:25;;10790:208;-1:-1:-1;;10790:208:2:o;11003:445::-;;11265:28;11260:3;11253:41;11323:6;11317:13;11339:62;11394:6;11389:2;11384:3;11380:12;11373:4;11365:6;11361:17;11339:62;:::i;:::-;11421:16;;;;11439:2;11417:25;;11243:205;-1:-1:-1;;11243:205:2:o;11453:383::-;;11602:2;11591:9;11584:21;11634:6;11628:13;11677:6;11672:2;11661:9;11657:18;11650:34;11693:66;11752:6;11747:2;11736:9;11732:18;11727:2;11719:6;11715:15;11693:66;:::i;:::-;11820:2;11799:15;-1:-1:-1;;11795:29:2;11780:45;;;;11827:2;11776:54;;11574:262;-1:-1:-1;;11574:262:2:o;11841:128::-;;11912:1;11908:6;11905:1;11902:13;11899:2;;;11918:18;;:::i;:::-;-1:-1:-1;11954:9:2;;11889:80::o;11974:120::-;;12040:1;12030:2;;12045:18;;:::i;:::-;-1:-1:-1;12079:9:2;;12020:74::o;12099:168::-;;12205:1;12201;12197:6;12193:14;12190:1;12187:21;12182:1;12175:9;12168:17;12164:45;12161:2;;;12212:18;;:::i;:::-;-1:-1:-1;12252:9:2;;12151:116::o;12272:125::-;;12340:1;12337;12334:8;12331:2;;;12345:18;;:::i;:::-;-1:-1:-1;12382:9:2;;12321:76::o;12402:258::-;12474:1;12484:113;12498:6;12495:1;12492:13;12484:113;;;12574:11;;;12568:18;12555:11;;;12548:39;12520:2;12513:10;12484:113;;;12615:6;12612:1;12609:13;12606:2;;;12650:1;12641:6;12636:3;12632:16;12625:27;12606:2;;12455:205;;;:::o;12665:380::-;12750:1;12740:12;;12797:1;12787:12;;;12808:2;;12862:4;12854:6;12850:17;12840:27;;12808:2;12915;12907:6;12904:14;12884:18;12881:38;12878:2;;;12961:10;12956:3;12952:20;12949:1;12942:31;12996:4;12993:1;12986:15;13024:4;13021:1;13014:15;12878:2;;12720:325;;;:::o;13050:135::-;;-1:-1:-1;;13110:17:2;;13107:2;;;13130:18;;:::i;:::-;-1:-1:-1;13177:1:2;13166:13;;13097:88::o;13190:112::-;;13248:1;13238:2;;13253:18;;:::i;:::-;-1:-1:-1;13287:9:2;;13228:74::o;13307:127::-;13368:10;13363:3;13359:20;13356:1;13349:31;13399:4;13396:1;13389:15;13423:4;13420:1;13413:15;13439:127;13500:10;13495:3;13491:20;13488:1;13481:31;13531:4;13528:1;13521:15;13555:4;13552:1;13545:15

Swarm Source

ipfs://b1157b857733a2076ebc6dfc880d2e2c8a25afd9e96b72e77dcc242ccd753d74

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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