ETH Price: $3,107.24 (+1.25%)
Gas: 5 Gwei

Contract

0xAd77f8106d1E4891be0428133f35F78977671F2F
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
0x61012060149946882022-06-20 4:43:13751 days ago1655700193IN
 Create: goodblocksGen0
0 ETH0.1197280613.6207822

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

Contract Source Code Verified (Exact Match)

Contract Name:
goodblocksGen0

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion
File 1 of 3 : goodblocksGen0.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/Base64.sol";

error YoureNotTheOwnerHomie();
error SorryYouCantAbandonOwnershipToTheZeroAddress();

contract goodblocksGen0
{
    constructor()
    {
        _Owner = msg.sender;
    }
    struct GoodBlock
    {
        uint8 pixelSizeIndex;
        uint8 symmetryIndex;
        uint8 colorGroupIndex;
        uint8 paletteIndex;
        bool isDarkBlock; 
        uint16 tokenIndex;
        bytes3 labelColor;
        string blockDNA;
    }
    uint8[5] private PixelSizes = [5,8,10,20,25];
    uint8[5] private PixelSizeHalf = [3,4,5,10,13];
    uint8[5] private PixelSizePadding = [1,2,2,3,5];
    uint8[5] private PixelSizePercents = [20,0,10,5,4];
    uint8[] private PixelSizeWeights = [25,15,20,15,25];
    uint8[] private BlockSymmetryWeights = [40,25,15,15,4,1];
    uint8[] private ColorGroupWeights = [30,10,20,10,25,30,15];
    uint8[] private PixelColorWeights = [65,20,10,5];
    uint8[] private PixelColorWeightsBiggins1 = [20,35,30,15];
    uint8[] private PixelColorWeightsBiggins2 = [40,30,20,10];
    string private GenerationDescription = "goodblocks generation 0 (gen0) is made up of random pixel images. head to goodblocks.io to learn more about the art process!";
    function updateGenerationDescription(string memory _newDescription) external
    {
        if(msg.sender != _Owner) revert YoureNotTheOwnerHomie();
        GenerationDescription = _newDescription;
    }
    string[5] private PixelSizeNames = ["Biggins", "Great Eight", "10 out of 10", "Score", "XXV"];
    string[8] private PixelEightPercents = ["0%", "12.5%", "25%", "37.5%", "50%", "62.5%", "75%", "87.5%"];
    string[6] private BlockSymmetryNames = ["X=0", "Y=0", "Y=X", "Y=-X", "Flipper", "Chaos"];
    string[6] private BlockSymmetryStrings = 
    [
        '(1000,0) scale(-1,1)', // left right
        '(0,1000) scale(1,-1)', // top bottom
        '(1000, 0) scale(-1,1) rotate(-90,500,500)', // diagonal top left to bottom right /
        '(1000, 0) scale(-1,1) rotate(90,500,500)', // diagonal bottom left to top right \
        '(1000,1000) scale(-1,-1)', // flip across x then flip accross y
        '(0,0) scale(1,1)' // do nothing
    ];
    string private constant LabelFlags =
        "01000101"  // palette 0 Joy
        "11111111"  // palette 1 Night
        "11000010"  // palette 2 Cosmos
        "00000110"  // palette 3 Earth
        "10100011"  // palette 4 Arctic
        "01111100"  // palette 5 Serenity
        "10111000"; // palette 6 Twilight

    string[7] private ColorGroupNames = ["Joy", "Night", "Cosmos", "Earth", "Arctic", "Serenity", "Twilight"];
    string[56] private ColorPalettes = 
    [
        "#FDFF8F;#A8ECE7;#F4BEEE;#D47AE8", // 0 palette (Joy)
        "#FD6F96;#FFEBA1;#95DAC1;#6F69AC",
        "#FFDF6B;#FF79CD;#AA2EE6;#23049D",
        "#95E1D3;#EAFFD0;#FCE38A;#FF75A0",
        "#FFCC29;#F58634;#007965;#00AF91",
        "#998CEB;#77E4D4;#B4FE98;#FBF46D",
        "#EEEEEE;#77D970;#172774;#FF0075",
        "#005F99;#FF449F;#FFF5B7;#00EAD3",
        "#0B0B0D;#474A56;#929AAB;#D3D5FD", // 1 palette (Night)
        "#07031A;#4F8A8B;#B1B493;#FFCB74",
        "#2E3A63;#665C84;#71A0A5;#FAB95B",
        "#000000;#226089;#4592AF;#E3C4A8",
        "#1B1F3A;#53354A;#A64942;#FF7844",
        "#1a1a1a;#153B44;#2D6E7E;#C6DE41",
        "#0F0A3C;#07456F;#009F9D;#CDFFEB",
        "#130026;#801336;#C72C41;#EE4540",
        "#111D5E;#C70039;#F37121;#C0E218", // 2 palette (Cosmos)
        "#02383C;#230338;#ED5107;#C70D3A",
        "#03C4A1;#C62A88;#590995;#150485",
        "#00A8CC;#005082;#000839;#FFA41B",
        "#E94560;#0F3460;#16213E;#1A1A2E",
        "#D2FAFB;#FE346E;#512B58;#2C003E",
        "#706C61;#E1F4F3;#FFFFFF;#333333",
        "#FAF7F2;#2BB3C0;#161C2E;#EF6C35",
        "#FFFBE9;#E3CAA5;#CEAB93;#AD8B73", // 3 palette (Earth)
        "#A09F57;#C56824;#CFB784;#EADEB8",
        "#E3D0B9;#E1BC91;#C19277;#62959C",
        "#E9C891;#8A8635;#AE431E;#D06224",
        "#83B582;#D6E4AA;#FFFFC5;#F0DD92",
        "#303E27;#B4BB72;#E7EAA8;#F6FAF7",
        "#A8896C;#F1E8A7;#AED09E;#61B292",
        "#F4DFBA;#EEC373;#CA965C;#876445",
        "#42C2FF;#85F4FF;#B8FFF9;#EFFFFD", // 4 palette (Arctic)
        "#E8F0F2;#A2DBFA;#39A2DB;#053742",
        "#3E64FF;#5EDFFF;#B2FCFF;#ECFCFF",
        "#D1FFFA;#4AA9AF;#3E31AE;#1C226B",
        "#F7F3F3;#C1EAF2;#5CC2F2;#191BA9",
        "#F3F3F3;#303841;#3A4750;#2185D5",
        "#769FCD;#B9D7EA;#D6E6F2;#F7FBFC",
        "#3D6CB9;#00D1FF;#00FFF0;#FAFAF6",
        "#99FEFF;#94DAFF;#94B3FD;#B983FF", // 5 palette (Serenity)
        "#E5707E;#E6B566;#E8E9A1;#A3DDCB",
        "#6892D5;#79D1C3;#C9FDD7;#F8FCFB",
        "#6C5B7B;#C06C84;#F67280;#F8B195",
        "#30475E;#BA6B57;#F1935C;#E7B2A5",
        "#FFEBD3;#264E70;#679186;#FFB4AC",
        "#6DDCCF;#94EBCD;#FFEFA1;#FFCB91",
        "#D8EFF0;#B0E0A8;#F0F69F;#F3C1C6",
        "#35477D;#6C5B7B;#C06C84;#F67280", // 6 palette (Twilight)
        "#F6C065;#55B3B1;#AF0069;#09015F",
        "#470D21;#9C0F48;#D67D3E;#F9E4D4",
        "#001F52;#A10054;#FF8D68;#FFECBA",
        "#FF6C00;#A0204C;#23103A;#282D4F",
        "#FFF9B2;#ECAC5D;#B24080;#3F0713",
        "#FFE98A;#C84771;#61105E;#280B45",
        "#EDE862;#FA9856;#F27370;#22559C"
    ];
    string private constant SvgHeader = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"'
        ' preserveAspectRatio="xMinYMin" shape-rendering="crispEdges" viewBox="0 0 1000 1000">';
    string[] private svgBody = 
    [
        // 0 - goodblock token number
        '<g id="goodblock',
        // 1 - goodblock background
        '"><g id="bigBlock"><rect id="background" width="100%" height="100%" fill="',
        // 2 - color group 1 fill
        '" /></g><g id="littleBlocks"><g id="yetAnotherGroupForAnimation"><g id="ogBlocks"><g id="colorOneGroup" fill="',
        // 3 - color group blocks
        '">',
        // 4 - color group 2 fill
        '</g><g id="colorTwoGroup" fill="',
        // 5 - color group 2 blocks
        '">',
        // 6 - color group 3 fill
        '</g><g id="colorThreeGroup" fill="',
        // 7 - color group 3 blocks
        '">',
        // 8 - block symmetry
        '</g></g><g id="poserBlocks"><use xlink:href="#ogBlocks" transform="translate',
        // 9 - label colors
        '"/></g></g></g></g>'
        '<text x="10%" y="96%" text-anchor="middle" fill="#',
        // 10 - goodblock name
        '" font-size="18" font-family="Courier New">',
        // 11 - animation1 background values
        '</text>'
        '<!--lilNudge-->'
        '<animateTransform'
           ' id="lilNudgeA" xlink:href="#littleBlocks"'
           ' attributeName="transform" type="rotate"'
           ' values="0 500 500;15 500 500;0 500 500;"'
           ' begin="colorOneGroup.click" dur=".5"/>'
        '<animate'
           ' xlink:href="#background" attributeName="fill"'
           ' values="',
        // 12 - animation1 background values
        '" begin="colorOneGroup.click" dur=".5"/>'
        '<!--letsGoForASpin-->'
        '<animate xlink:href="#background" attributeName="fill" values="',
        // 13 - animation2 background values
        '" begin="colorTwoGroup.click" dur="2"/>'
        '<animateTransform xlink:href="#yetAnotherGroupForAnimation"'
            ' attributeName="transform" begin="colorTwoGroup.click"'
            ' type="rotate" values="0 500 500;360 500 500" dur="2"/>'
        '<animateTransform xlink:href="#littleBlocks"'
            ' attributeName="transform" begin="colorTwoGroup.click"'
            ' values="0 0;-1000 0" dur=".5"/>'
        '<animateTransform xlink:href="#littleBlocks"'
            ' attributeName="transform" begin="colorTwoGroup.click+.5"'
            ' values="1000 0;-1000 0" dur="1"/>'
        '<animateTransform xlink:href="#littleBlocks"'
            ' attributeName="transform" begin="colorTwoGroup.click+1.5"'
            ' values="1000 0;0 0" dur=".5"/>'
        '<!--whatTheHeckIsHappening?-->'
        '<animate xlink:href="#background"'
            ' attributeName="fill" begin="colorThreeGroup.click"'
            ' values="',
        // 14 - end of svg!
            '" keyTimes="0;.01;.99;1" dur="10"/>'
        '<animateTransform xlink:href="#yetAnotherGroupForAnimation"'
            ' attributeName="transform" begin="colorThreeGroup.click + .02"'
            ' type="translate" values="0 0;0 50;0 250;0 150;0 0;"'
            ' keyTimes="0;.002;.5;.98;1" dur="9.98s"/>'
        '<animateTransform xlink:href="#colorOneGroup"'
            ' attributeName="transform" additive="sum" type="scale"'
            ' begin="colorThreeGroup.click" values="1;.4;.3;.4;1"'
            ' keyTimes="0;.02;.5;.98;1" dur="10s"/>'
        '<animateTransform xlink:href="#colorOneGroup"'
            ' attributeName="transform" additive="sum" type="rotate"'
            ' begin="colorThreeGroup.click + .02" values="0 1000 1000; 360 1000 1000"'
            ' dur="9.98s"/>'
        '<animateTransform xlink:href="#colorTwoGroup"'
            ' attributeName="transform" additive="sum" type="scale"'
            ' begin="colorThreeGroup.click" values="1;.6;.5;.6;1"'
            ' keyTimes="0;.02;.5;.98;1" dur="10s"/>'
        '<animateTransform xlink:href="#colorTwoGroup"'
            ' attributeName="transform" additive="sum" type="rotate"' 
            ' begin="colorThreeGroup.click + .02" values="0 500 600;-360 500 600"'
            ' dur="9.98s"/>'
        '<animateTransform xlink:href="#colorThreeGroup"'
            ' attributeName="transform" additive="sum" type="scale"'
            ' begin="colorThreeGroup.click" values="1;.8;.6;.4;1"'
            ' keyTimes="0;.01;.5;.98;1" dur="10s"/>'
        '<animateTransform xlink:href="#colorThreeGroup"'
            ' attributeName="transform" additive="sum" type="rotate"'
            ' begin="colorThreeGroup.click + .02" values="0 500 500;360 500 500"'
            ' dur="9.98s"/>'
    '</svg>'
    ];
    function updateSvgBody(uint256 _index, string memory _newString) external returns (string[] memory)
    {
        if(msg.sender != _Owner) revert YoureNotTheOwnerHomie();
        svgBody[_index] = _newString;
        return svgBody;
    }
    function substring(string memory str, uint256 startIndex, uint256 endIndex) private pure returns (string memory)
    {
        bytes memory strBytes = bytes(str);
        bytes memory result = new bytes(endIndex - startIndex);
        for (uint256 i = startIndex; i < endIndex; i++)
        {
            result[i - startIndex] = strBytes[i];
        }
        return string(result);
    }
    function random(string memory _input) private pure returns (uint256)
    {
        return uint256(keccak256(abi.encodePacked(_input)));
    }
    function getWeightedItem(uint8[] memory weightArray, uint256 i) private pure returns (uint8)
    {
        uint256 index = 0;
        uint256 j = weightArray[0];
        while (j <= i)
        {
            index++;
            j += weightArray[index];
        }
        return uint8(index);
    }
    function tokenToGoodblock(uint256 _tokenId) public view returns(GoodBlock memory)
    {
        GoodBlock memory goodblock;
        // set index
        goodblock.tokenIndex = uint16(_tokenId);
        // get pixel set
        goodblock.pixelSizeIndex = getWeightedItem(PixelSizeWeights, random(Strings.toString(_tokenId + 20)) % 100);
        // get symmetry
        goodblock.symmetryIndex = getWeightedItem(BlockSymmetryWeights, random(Strings.toString(_tokenId + 22)) % 100) ;
        // get color group
        goodblock.colorGroupIndex = getWeightedItem(ColorGroupWeights, random(Strings.toString(_tokenId + 1)) % 140);
        // get palette index
        goodblock.paletteIndex = uint8(random(string(abi.encodePacked("Wth?", Strings.toString(_tokenId + 4)))) % 8);

        string memory blockDNA =  string(abi.encodePacked(
            Strings.toString(_tokenId),
            "_",
            Strings.toString(goodblock.pixelSizeIndex),
            "_",
            Strings.toString(goodblock.symmetryIndex),
            "_",
            Strings.toString(goodblock.colorGroupIndex),
            "_",
            Strings.toString(goodblock.paletteIndex)
        ));

        // if in list, then label flag
        if (keccak256(abi.encodePacked(substring(LabelFlags, (goodblock.colorGroupIndex * 8 + goodblock.paletteIndex), (goodblock.colorGroupIndex * 8 + goodblock.paletteIndex)+1))) == keccak256("1"))
        {
            goodblock.labelColor = bytes3("fff");
        } else
        {
            goodblock.labelColor = bytes3("000");
        }

        // DARK LOGIC
        if(_tokenId < 2133 || _tokenId > 6120)
        {
            goodblock.isDarkBlock = false;
            goodblock.blockDNA = string(abi.encodePacked(blockDNA,"_0"));
            return goodblock;
        }

        //d check if in y bounds
        if(_tokenId > 2132 && _tokenId < 3789)
        {
            // get y and x respectively
            uint tokenDivY = uint(_tokenId/91);
            uint tokenModX = _tokenId%91;
            
            // CHECK EASY ONES
            if(tokenDivY < 28)
            {
                if(tokenModX < 40 || tokenModX > 44)
                {
                    goodblock.isDarkBlock = false;
                    goodblock.blockDNA = string(abi.encodePacked(blockDNA,"_0"));
                    return goodblock;
                } else
                {
                    goodblock.isDarkBlock = true;
                    goodblock.blockDNA = string(abi.encodePacked(blockDNA,"_1"));
                    goodblock.labelColor = bytes3("fff");
                    return goodblock;
                }
            }

            // CHECK REGION
            if(tokenModX > 29 && tokenModX < 62)
            {
                tokenDivY = tokenDivY - 28;
                if(keccak256(abi.encodePacked(substring(d, tokenDivY*32+tokenModX-30, tokenDivY*32+tokenModX-30 + 1))) == keccak256("1"))
                {
                    goodblock.isDarkBlock = true;
                    goodblock.blockDNA = string(abi.encodePacked(blockDNA,"_1"));
                    goodblock.labelColor = bytes3("fff");
                    return goodblock;
                }else
                {
                    goodblock.isDarkBlock = false;
                    goodblock.blockDNA = string(abi.encodePacked(blockDNA,"_0"));
                    return goodblock;
                }
            }
        }
        // g check if in y bounds
        else if(_tokenId > 4077 && _tokenId < 6121)
        {
            // get y and x respectively
            uint tokenDivY = uint(_tokenId/91);
            uint tokenModX = _tokenId%91;
            
            // CHECK EASY ONES
            // d
            if(tokenDivY < 49)
            {
                if(tokenModX < 74 || tokenModX > 78)
                {
                    goodblock.isDarkBlock = false;
                    goodblock.blockDNA = string(abi.encodePacked(blockDNA,"_0"));
                    return goodblock;
                } else
                {
                    goodblock.isDarkBlock = true;
                    goodblock.blockDNA = string(abi.encodePacked(blockDNA,"_1"));
                    goodblock.labelColor = bytes3("fff");
                    return goodblock;
                }
            }
            // g
            else if(tokenDivY > 62)
            {
                if(tokenModX > 27)
                {
                    goodblock.isDarkBlock = false;
                    goodblock.blockDNA = string(abi.encodePacked(blockDNA,"_0"));
                    return goodblock;
                }
            }

            // CHECK REGION
            if(tokenModX > 12 && tokenModX < 79)
            {
                tokenDivY = tokenDivY - 49;
                if(keccak256(abi.encodePacked(substring(g, tokenDivY*66+tokenModX-13, tokenDivY*66+tokenModX-13 + 1))) == keccak256("1"))
                {
                    goodblock.isDarkBlock = true;
                    goodblock.blockDNA = string(abi.encodePacked(blockDNA,"_1"));
                    goodblock.labelColor = bytes3("fff");
                    return goodblock;
                }else
                {
                    goodblock.isDarkBlock = false;
                    goodblock.blockDNA = string(abi.encodePacked(blockDNA,"_0"));
                    return goodblock;
                }
            }
        }
        
        goodblock.isDarkBlock = false;
        goodblock.blockDNA = string(abi.encodePacked(blockDNA,"_0"));
        return goodblock;
    }
    function goodblockToSVG(GoodBlock memory _goodblock) private view returns(string memory)
    {
        // set variables for goodblock generation
        string memory rectPercent;
        string[] memory pixelPercents = new string[](PixelSizes[_goodblock.pixelSizeIndex]);
 
        // check if pixel set is 8
        if(PixelSizes[_goodblock.pixelSizeIndex] == 8)
        {
            // set rectangle width/height
            rectPercent = "12.5%";
            // set percents for positions
            for(uint256 i=0; i<PixelSizes[_goodblock.pixelSizeIndex]; i++)
            {
                pixelPercents[i] = PixelEightPercents[i];
            }

        } else
        {
            // set rectangle width/height
            rectPercent = string(abi.encodePacked(Strings.toString(PixelSizePercents[_goodblock.pixelSizeIndex]), "%"));
            // set percents for positions
            for(uint256 i = 0; i<PixelSizes[_goodblock.pixelSizeIndex]; i++) 
            {
                pixelPercents[i] = string(abi.encodePacked(Strings.toString(i*PixelSizePercents[_goodblock.pixelSizeIndex]), "%"));
            }
        }

        // create color groups to house rectangles
        string[3] memory colorGroupRectangles;
        uint256 tempColorGroupIndex;
        string memory blockMap;

        // 0 left right
        // 1 top bottom
        // diag top left
        // diag bottom left
        // diag both
        // chaos

        // create _goodblock
        // loop through y axis top to bottom
        for (uint y=0; y<PixelSizes[_goodblock.pixelSizeIndex]; y++)
        {
            // check for padding first
            if(y < PixelSizePadding[_goodblock.pixelSizeIndex] || 
                PixelSizes[_goodblock.pixelSizeIndex]-y < PixelSizePadding[_goodblock.pixelSizeIndex] + 1)
            {
                continue; 
            }

            // top bottom then skip bottom half
            if(_goodblock.symmetryIndex == 1)
            {
                if((y+1) > PixelSizeHalf[_goodblock.pixelSizeIndex])
                {
                    continue;
                }
            }

            // stop halfway if token%2 == 0
            if(_goodblock.symmetryIndex == 2 && _goodblock.tokenIndex % 2 == 0)
            {
                if((y+1) > PixelSizeHalf[_goodblock.pixelSizeIndex])
                {
                    continue;
                }
            }

            // stop halfway if token%2 == 0
            if(_goodblock.symmetryIndex == 3 && _goodblock.tokenIndex % 2 == 0)
            {
                if((y+1) < PixelSizeHalf[_goodblock.pixelSizeIndex])
                {
                    continue;
                }
            }

            // loop through x axis left to right
            for (uint x=0; x<PixelSizes[_goodblock.pixelSizeIndex]; x++)
            {
                // check for padding first
                if(x < PixelSizePadding[_goodblock.pixelSizeIndex] ||
                    PixelSizes[_goodblock.pixelSizeIndex]-x < PixelSizePadding[_goodblock.pixelSizeIndex] + 1)
                {
                    continue;
                }

                // left right or flipper
                if(_goodblock.symmetryIndex == 0 || _goodblock.symmetryIndex == 4)
                {
                    if((x+1) > PixelSizeHalf[_goodblock.pixelSizeIndex])
                    {
                        continue;
                    }
                }            
                // diagonal top left to bottom right
                else if(_goodblock.symmetryIndex == 2)
                {
                    if(_goodblock.tokenIndex % 2 == 0)
                    {
                        if((x+1) > PixelSizeHalf[_goodblock.pixelSizeIndex])
                        {
                            continue;
                        }

                    } else
                    {
                        if(x > (PixelSizes[_goodblock.pixelSizeIndex] - y - 1))
                        {
                            continue;
                        }
                    }    
                }
                // diagonal bottom left to top right
                else if(_goodblock.symmetryIndex == 3)
                {
                    if(_goodblock.tokenIndex % 2 == 0)
                    {
                        if((x+1) > PixelSizeHalf[_goodblock.pixelSizeIndex]
                        )
                        {
                            continue;
                        }
                    } else
                    {
                        if(x < y + 1)
                        {
                            continue;
                        }
                    }
                }
                
                tempColorGroupIndex = getWeightedItem(PixelColorWeights, random(string(abi.encodePacked(_goodblock.blockDNA, Strings.toString(x*24 + y*22 + _goodblock.tokenIndex)))) % 100);

                // determine color group for next rectangle
                if(_goodblock.pixelSizeIndex == 0)
                {
                    if(_goodblock.tokenIndex % 4 == 0)
                    {
                        tempColorGroupIndex = getWeightedItem(PixelColorWeightsBiggins1, random(string(abi.encodePacked(_goodblock.blockDNA, Strings.toString(x*13 + y*4 + 13 + _goodblock.tokenIndex)))) % 100);
                    } else if(_goodblock.tokenIndex % 2 == 0)
                    {
                        tempColorGroupIndex = getWeightedItem(PixelColorWeightsBiggins2, random(string(abi.encodePacked(_goodblock.blockDNA, Strings.toString(x*13 + y*4 + 13 + _goodblock.tokenIndex)))) % 100);
                    }
                }

                // check if pixel is background color
                if(tempColorGroupIndex == 0)
                {
                    blockMap = string(abi.encodePacked(blockMap, "0"));
                    continue;
                }

                blockMap = string(abi.encodePacked(blockMap, "1"));

                // add rectangle to appropriate color group
                colorGroupRectangles[tempColorGroupIndex-1] = string(abi.encodePacked(
                    colorGroupRectangles[tempColorGroupIndex-1],
                    '<rect x="',
                    pixelPercents[x],
                    '" y="',
                    pixelPercents[y]
                ));
                colorGroupRectangles[tempColorGroupIndex-1] = string(abi.encodePacked(  
                    colorGroupRectangles[tempColorGroupIndex-1],  
                    '" width="',
                    rectPercent,
                    '" height="',
                    rectPercent,
                    '"/>'
                ));

                // next
            }
        }
        
        _goodblock.blockDNA = string(abi.encodePacked(_goodblock.blockDNA, "_", blockMap));

        string memory animatedBG2;

        // determine background color
        string memory bgColor = substring(ColorPalettes[(_goodblock.colorGroupIndex * 8 + _goodblock.paletteIndex)], 0, 7);
        
        if(_goodblock.isDarkBlock)
        {
            // update animated bg 2
            animatedBG2 = string(abi.encodePacked(
                '#000;',
                bgColor,';',
                bgColor,';',
                '#000'
            ));
            // make bg black
            bgColor = "#000";
        } else
        {
            // update animated bg 2
            animatedBG2 = string(abi.encodePacked(
                bgColor,';',
                '#000;',
                '#000;',
                bgColor
            ));
        }

        // 0 - goodblock token number
        // 1 - goodblock background
        // 2 - color group 1 fill
        // 3 - color group blocks
        // 4 - color group 2 fill
        // 5 - color group 2 blocks
        // 6 - color group 3 fill
        // 7 - color group 3 blocks
        // 8 - block symmetry
        // 9 - animation1 background values
        // 10 - animation1 background values
        // 11 - animation2 background values
        // 12 - end of svg!

        string memory blockSVG = string(abi.encodePacked(
            SvgHeader,
            svgBody[0],
            Strings.toString(uint256(_goodblock.tokenIndex)),
            svgBody[1],
            bgColor,
            svgBody[2]
        ));

        blockSVG = string(abi.encodePacked(
            blockSVG,
            substring(ColorPalettes[(_goodblock.colorGroupIndex * 8 + _goodblock.paletteIndex)], 8, 15),
            svgBody[3],
            colorGroupRectangles[0],
            svgBody[4]
        ));
        
        blockSVG = string(abi.encodePacked(
            blockSVG,
            substring(ColorPalettes[(_goodblock.colorGroupIndex * 8 + _goodblock.paletteIndex)], 16, 23),
            svgBody[5],
            colorGroupRectangles[1]
        ));
        
        blockSVG = string(abi.encodePacked(
            blockSVG,
            svgBody[6],
            substring(ColorPalettes[(_goodblock.colorGroupIndex * 8 + _goodblock.paletteIndex)], 24, 31),
            svgBody[7]
        ));

        blockSVG = string(abi.encodePacked(
            blockSVG,
            colorGroupRectangles[2],
            svgBody[8],
            BlockSymmetryStrings[_goodblock.symmetryIndex]
        ));
        
        blockSVG = string(abi.encodePacked(
            blockSVG,
            svgBody[9],
            _goodblock.labelColor,
            svgBody[10],
            ColorGroupNames[_goodblock.colorGroupIndex],
            ' #',
            Strings.toString(_goodblock.tokenIndex)
        ));
        
        blockSVG = string(abi.encodePacked(
            blockSVG,
            svgBody[11],
            ColorPalettes[(_goodblock.colorGroupIndex * 8 + _goodblock.paletteIndex)],
            svgBody[12]
        ));

        blockSVG = string(abi.encodePacked(
            blockSVG,
            ColorPalettes[(_goodblock.colorGroupIndex * 8 + _goodblock.paletteIndex)],
            svgBody[13],
            animatedBG2,
            svgBody[14]
        ));

        return blockSVG;        
    }
    function blockToMetadata(GoodBlock memory _goodblock) private view returns(string memory)
    {
        string memory metadata = string(abi.encodePacked(
            '{"trait_type": "Pixel Size", "value":"',
            PixelSizeNames[_goodblock.pixelSizeIndex],
            '"},{"trait_type": "Symmetry", "value":"',
            BlockSymmetryNames[_goodblock.symmetryIndex],
            '"},{"trait_type": "Color Group", "value":"',
            ColorGroupNames[_goodblock.colorGroupIndex],
            '"},{"trait_type": "Palette Index", "value":"',
            Strings.toString(_goodblock.paletteIndex),
            '"},'
        ));

        if(_goodblock.isDarkBlock)
        {
            metadata = string(abi.encodePacked(
                metadata,
                '{"trait_type": "Special Trait", "value":"Do Good"},'
            ));
        } else
        {
            metadata = string(abi.encodePacked(
                metadata,
                '{"trait_type": "Special Trait", "value":"None"},'
            ));
        }

        return metadata;
    }
    function tokenGenURI(uint256 _tokenId, string memory _tokenMetadata, string memory _tokenAttributes) public view returns(string memory)
    {
        // get goodblock
        GoodBlock memory goodblock = tokenToGoodblock(_tokenId);        
        // get svg
        string memory goodblockSVG = string(Base64.encode(bytes(goodblockToSVG(goodblock))));
        // get attributes for metadata
        string memory goodblockMetadata = blockToMetadata(goodblock);
        // set up token uri
        string memory tokenUri = string(abi.encodePacked(
            '{"name":"',
            ColorGroupNames[goodblock.colorGroupIndex],
            ' #',
            Strings.toString(_tokenId),
            '","description":"',
            GenerationDescription,
            '","DNA":"',
            goodblock.blockDNA,
            '",',
            _tokenMetadata,
            ',"attributes":[',
            goodblockMetadata,
            _tokenAttributes,
            '],"image":"data:image/svg+xml;base64,',
            goodblockSVG,
            '"}'
        ));       
        
        return string(abi.encodePacked("data:application/json;base64,", string(Base64.encode(bytes(tokenUri)))));
    }
    string private constant d = "0000111110111110000001111111000000111111111111100001111111111100011111111111111000111111111111101111111111111110011111111111111111111100011111100111111000111111111110000011111001111100000111111111100000111110011111000001111111111000001111100111110000011111111110000011111001111100000111111111110001111110011111100011111111111111111111100111111111111111011111111111111000111111111111100011111111111110000111111111110000011111101111100000011111110000";
    string private constant g = "000011110011111000000111111100000000001111111000000000011111011111001111111111111000011111111111000000111111111110000001111111111111011111111111111000111111111111100001111111111111000011111111111111111111111111111001111111111111110011111111111111100111111111111111111111000111111001111110001111110011111100011111100111111000111111111110000011111001111100000111110011111000001111100111110000011111111110000011111001111100000111110011111000001111100111110000011111111110000011111001111100000111110011111000001111100111110000011111111110000011111001111100000111110011111000001111100111110000011111111111000111111001111110001111110011111100011111100111111000111111011111111111111001111111111111110011111111111111100111111111111111001111111111111000111111111111100001111111111111000011111111111111000111111011111000011111111111000000111111111110000001111111111111000000000011111000000111111100000000001111111000000000111111011111011100000111111000000000000000000000000000000000000000000000000000011111111111111000000000000000000000000000000000000000000000000000011111111111110000000000000000000000000000000000000000000000000000011111111111100000000000000000000000000000000000000000000000000000001111111110000000000000000000000000000000000000000000000000000000";
    address public _Owner;
    function transferOwnership(address _newOwner) external 
    {
        if(msg.sender != _Owner) revert YoureNotTheOwnerHomie();
        if(_newOwner == address(0)) revert SorryYouCantAbandonOwnershipToTheZeroAddress();
        _Owner = _newOwner;
    }
}

File 2 of 3 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        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);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 3 of 3 : Base64.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Base64.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return result;
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"SorryYouCantAbandonOwnershipToTheZeroAddress","type":"error"},{"inputs":[],"name":"YoureNotTheOwnerHomie","type":"error"},{"inputs":[],"name":"_Owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"string","name":"_tokenMetadata","type":"string"},{"internalType":"string","name":"_tokenAttributes","type":"string"}],"name":"tokenGenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenToGoodblock","outputs":[{"components":[{"internalType":"uint8","name":"pixelSizeIndex","type":"uint8"},{"internalType":"uint8","name":"symmetryIndex","type":"uint8"},{"internalType":"uint8","name":"colorGroupIndex","type":"uint8"},{"internalType":"uint8","name":"paletteIndex","type":"uint8"},{"internalType":"bool","name":"isDarkBlock","type":"bool"},{"internalType":"uint16","name":"tokenIndex","type":"uint16"},{"internalType":"bytes3","name":"labelColor","type":"bytes3"},{"internalType":"string","name":"blockDNA","type":"string"}],"internalType":"struct goodblocksGen0.GoodBlock","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newDescription","type":"string"}],"name":"updateGenerationDescription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"string","name":"_newString","type":"string"}],"name":"updateSvgBody","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"nonpayable","type":"function"}]

61012060405260056080818152600860a052600a60c052601460e05260196101005262000030916000919062001580565b506040805160a08101825260038152600460208201526005918101829052600a6060820152600d60808201526200006b916001919062001580565b506040805160a0810182526001815260026020820181905291810182905260036060820152600560808201819052620000a692919062001580565b506040805160a0810182526014815260006020820152600a9181019190915260056060820181905260046080830152620000e39160039162001580565b506040805160a0810182526019808252600f6020830181905260149383019390935260608201929092526080810191909152620001259060049060056200161a565b506040805160c0810182526028815260196020820152600f918101829052606081019190915260046080820152600160a0820152620001699060059060066200161a565b506040805160e081018252601e808252600a6020830181905260149383019390935260608201929092526019608082015260a0810191909152600f60c0820152620001b99060069060076200161a565b50604080516080810182526041815260146020820152600a9181019190915260056060820152620001ef9060079060046200161a565b50604080516080810182526014815260236020820152601e91810191909152600f6060820152620002259060089060046200161a565b506040805160808101825260288152601e6020820152601491810191909152600a60608201526200025b9060099060046200161a565b506040518060a00160405280607c815260200162006274607c913980516200028c91600a9160209091019062001683565b506040518060a001604052806040518060400160405280600781526020016642696767696e7360c81b81525081526020016040518060400160405280600b81526020016a11dc99585d08115a59da1d60aa1b81525081526020016040518060400160405280600c81526020016b03130206f7574206f662031360a41b81525081526020016040518060400160405280600581526020016453636f726560d81b8152508152602001604051806040016040528060038152602001622c2c2b60e91b815250815250600b9060056200036492919062001700565b5060408051610140810182526002610100820190815261302560f01b61012083015281528151808301835260058082526431322e352560d81b602083810191909152808401929092528351808501855260038082526232352560e81b8285015284860191909152845180860186528281526433372e352560d81b818501526060850152845180860186528181526235302560e81b818501526080850152845180860186528281526436322e352560d81b8185015260a0850152845180860186529081526237352560e81b8184015260c0840152835180850190945283526438372e352560d81b9083015260e08101919091526200046690601090600862001753565b506040805161010081018252600360c08201818152620583d360ec1b60e0840152825282518084018452818152620593d360ec1b6020828101919091528084019190915283518085018552918252620b27ab60eb1b82820152828401919091528251808401845260048152630b27a5ab60e31b818301526060830152825180840184526007815266233634b83832b960c91b818301526080830152825180840190935260058352644368616f7360d81b9083015260a08101919091526200053290601890600662001798565b506040518060c001604052806040518060400160405280601481526020017f28313030302c3029207363616c65282d312c312900000000000000000000000081525081526020016040518060400160405280601481526020017f28302c3130303029207363616c6528312c2d31290000000000000000000000008152508152602001604051806060016040528060298152602001620060d360299139815260200160405180606001604052806028815260200162005ff16028913981526020016040518060400160405280601881526020017f28313030302c3130303029207363616c65282d312c2d3129000000000000000081525081526020016040518060400160405280601081526020016f28302c3029207363616c6528312c312960801b815250815250601e9060066200066b92919062001798565b506040518060e00160405280604051806040016040528060038152602001624a6f7960e81b815250815260200160405180604001604052806005815260200164139a59da1d60da1b815250815260200160405180604001604052806006815260200165436f736d6f7360d01b81525081526020016040518060400160405280600581526020016408ac2e4e8d60db1b81525081526020016040518060400160405280600681526020016541726374696360d01b815250815260200160405180604001604052806008815260200167536572656e69747960c01b815250815260200160405180604001604052806008815260200167151dda5b1a59da1d60c21b815250815250602490600762000782929190620017dd565b506040805161074081018252601f61070082018181527f234644464638463b234138454345373b234634424545453b23443437414538006107208401528252825180840184528181527f234644364639363b234646454241313b233935444143313b233646363941430060208281019190915280840191909152835180850185528281527f234646444636423b234646373943443b234141324545363b23323330343944008183015283850152835180850185528281527f233935453144333b234541464644303b234643453338413b2346463735413000818301526060840152835180850185528281527f234646434332393b234635383633343b233030373936353b2330304146393100818301526080840152835180850185528281527f233939384345423b233737453444343b234234464539383b23464246343644008183015260a0840152835180850185528281527f234545454545453b233737443937303b233137323737343b23464630303735008183015260c0840152835180850185528281527f233030354639393b234646343439463b234646463542373b23303045414433008183015260e0840152835180850185528281527f233042304230443b233437344135363b233932394141423b234433443546440081830152610100840152835180850185528281527f233037303331413b233446384138423b234231423439333b234646434237340081830152610120840152835180850185528281527f233245334136333b233636354338343b233731413041353b234641423935420081830152610140840152835180850185528281527f233030303030303b233232363038393b233435393241463b234533433441380081830152610160840152835180850185528281527f233142314633413b233533333534413b234136343934323b234646373834340081830152610180840152835180850185528281527f233161316131613b233135334234343b233244364537453b2343364445343100818301526101a0840152835180850185528281527f233046304133433b233037343536463b233030394639443b2343444646454200818301526101c0840152835180850185528281527f233133303032363b233830313333363b234337324334313b2345453435343000818301526101e0840152835180850185528281527f233131314435453b234337303033393b234633373132313b234330453231380081830152610200840152835180850185528281527f233032333833433b233233303333383b234544353130373b234337304433410081830152610220840152835180850185528281527f233033433441313b234336324138383b233539303939353b233135303438350081830152610240840152835180850185528281527f233030413843433b233030353038323b233030303833393b234646413431420081830152610260840152835180850185528281527f234539343536303b233046333436303b233136323133453b233141314132450081830152610280840152835180850185528281527f234432464146423b234645333436453b233531324235383b2332433030334500818301526102a0840152835180850185528281527f233730364336313b234531463446333b234646464646463b2333333333333300818301526102c0840152835180850185528281527f234641463746323b233242423343303b233136314332453b2345463643333500818301526102e0840152835180850185528281527f234646464245393b234533434141353b234345414239333b234144384237330081830152610300840152835180850185528281527f234130394635373b234335363832343b234346423738343b234541444542380081830152610320840152835180850185528281527f234533443042393b234531424339313b234331393237373b233632393539430081830152610340840152835180850185528281527f234539433839313b233841383633353b234145343331453b234430363232340081830152610360840152835180850185528281527f233833423538323b234436453441413b234646464643353b234630444439320081830152610380840152835180850185528281527f233330334532373b234234424237323b234537454141383b2346364641463700818301526103a0840152835180850185528281527f234138383936433b234631453841373b234145443039453b2336314232393200818301526103c0840152835180850185528281527f234634444642413b234545433337333b234341393635433b2338373634343500818301526103e0840152835180850185528281527f233432433246463b233835463446463b234238464646393b234546464646440081830152610400840152835180850185528281527f234538463046323b234132444246413b233339413244423b233035333734320081830152610420840152835180850185528281527f233345363446463b233545444646463b234232464346463b234543464346460081830152610440840152835180850185528281527f234431464646413b233441413941463b233345333141453b233143323236420081830152610460840152835180850185528281527f234637463346333b234331454146323b233543433246323b233139314241390081830152610480840152835180850185528281527f234633463346333b233330333834313b233341343735303b2332313835443500818301526104a0840152835180850185528281527f233736394643443b234239443745413b234436453646323b2346374642464300818301526104c0840152835180850185528281527f233344364342393b233030443146463b233030464646303b2346414641463600818301526104e0840152835180850185528281527f233939464546463b233934444146463b233934423346443b234239383346460081830152610500840152835180850185528281527f234535373037453b234536423536363b234538453941313b234133444443420081830152610520840152835180850185528281527f233638393244353b233739443143333b234339464444373b234638464346420081830152610540840152835180850185528281527f233643354237423b234330364338343b234636373238303b234638423139350081830152610560840152835180850185528281527f233330343735453b234241364235373b234631393335433b234537423241350081830152610580840152835180850185528281527f234646454244333b233236344537303b233637393138363b2346464234414300818301526105a0840152835180850185528281527f233644444343463b233934454243443b234646454641313b2346464342393100818301526105c0840152835180850185528281527f234438454646303b234230453041383b234630463639463b2346334331433600818301526105e0840152835180850185528281527f233335343737443b233643354237423b234330364338343b234636373238300081830152610600840152835180850185528281527f234636433036353b233535423342313b234146303036393b233039303135460081830152610620840152835180850185528281527f233437304432313b233943304634383b234436374433453b234639453444340081830152610640840152835180850185528281527f233030314635323b234131303035343b234646384436383b234646454342410081830152610660840152835180850185528281527f234646364330303b234130323034433b233233313033413b233238324434460081830152610680840152835180850185528281527f234646463942323b234543414335443b234232343038303b2333463037313300818301526106a0840152835180850185528281527f234646453938413b234338343737313b233631313035453b2332383042343500818301526106c084015283518085019094529083527f234544453836323b234641393835363b234632373337303b2332323535394300908301526106e08101919091526200133790602b90603862001822565b50604051806101e001604052806040518060400160405280601081526020016f3c672069643d22676f6f64626c6f636b60801b81525081526020016040518060800160405280604a815260200162005f2b604a913981526020016040518060a00160405280606e815260200162006065606e9139815260200160405180604001604052806002815260200161111f60f11b81525081526020016040518060400160405280602081526020017f3c2f673e3c672069643d22636f6c6f7254776f47726f7570222066696c6c3d22815250815260200160405180604001604052806002815260200161111f60f11b815250815260200160405180606001604052806022815260200162005f0960229139815260200160405180604001604052806002815260200161111f60f11b81525081526020016040518060800160405280604c815260200162006019604c91398152602001604051806080016040528060458152602001620062046045913981526020016040518060600160405280602b815260200162006249602b913981526020016040518061014001604052806101088152602001620060fc610108913981526020016040518060a00160405280607c815260200162005f75607c913981526020016040518061030001604052806102d88152602001620056d26102d89139815260200160405180610580016040528061055f8152602001620059aa61055f913990526200155990606390600f62001867565b503480156200156757600080fd5b50606480546001600160a01b0319163317905562001970565b600183019183908215620016085791602002820160005b83821115620015d757835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030262001597565b8015620016065782816101000a81549060ff0219169055600101602081600001049283019260010302620015d7565b505b5062001616929150620018b9565b5090565b82805482825590600052602060002090601f016020900481019282156200160857916020028201600083821115620015d757835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030262001597565b828054620016919062001933565b90600052602060002090601f016020900481019282620016b5576000855562001608565b82601f10620016d057805160ff191683800117855562001608565b8280016001018555821562001608579182015b8281111562001608578251825591602001919060010190620016e3565b826005810192821562001745579160200282015b828111156200174557825180516200173491849160209091019062001683565b509160200191906001019062001714565b5062001616929150620018d0565b826008810192821562001745579160200282015b828111156200174557825180516200178791849160209091019062001683565b509160200191906001019062001767565b826006810192821562001745579160200282015b82811115620017455782518051620017cc91849160209091019062001683565b5091602001919060010190620017ac565b826007810192821562001745579160200282015b828111156200174557825180516200181191849160209091019062001683565b5091602001919060010190620017f1565b826038810192821562001745579160200282015b828111156200174557825180516200185691849160209091019062001683565b509160200191906001019062001836565b82805482825590600052602060002090810192821562001745579160200282015b82811115620017455782518051620018a891849160209091019062001683565b509160200191906001019062001888565b5b80821115620016165760008155600101620018ba565b8082111562001616576000620018e78282620018f1565b50600101620018d0565b508054620018ff9062001933565b6000825580601f1062001910575050565b601f016020900490600052602060002090810190620019309190620018b9565b50565b600181811c908216806200194857607f821691505b602082108114156200196a57634e487b7160e01b600052602260045260246000fd5b50919050565b613d5280620019806000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063dcc2345511610050578063dcc23455146100e0578063dd4a89131461010b578063f2fde38b1461012057600080fd5b806307160cf5146100775780631ea40c71146100a0578063c379dc43146100c0575b600080fd5b61008a610085366004612527565b610133565b60405161009791906132ed565b60405180910390f35b6100b36100ae366004612540565b610887565b6040516100979190613278565b6100d36100ce366004612587565b6109c1565b60405161009791906132da565b6064546100f3906001600160a01b031681565b6040516001600160a01b039091168152602001610097565b61011e6101193660046124f2565b610a7f565b005b61011e61012e3660046124c2565b610ac1565b604080516101008082018352600080835260208084018290528385018290526060808501839052608080860184905260a080870185905260c080880186905260e080890185905289519788018a52868852878601879052878a0187905287850187905292870186905286019490945284015261ffff861691830191909152600480548551818402810184019096528086529394929361024d939283018282801561021a57602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116101eb5790505b5050505050606461023e6102398760146102349190613394565b610b66565b610c84565b61024891906134eb565b610cb5565b60ff16815260058054604080516020808402820181019092528281526102d893909290918301828280156102be57602002820191906000526020600020906000905b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161028f5790505b5050505050606461023e6102398760166102349190613394565b60ff16602080830191909152600680546040805182850281018501909152818152610368939092919083018282801561034e57602002820191906000526020600020906000905b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161031f5790505b5050505050608c61023e6102398760016102349190613394565b60ff16604082015260086103a7610383610234866004613394565b604051602001610393919061318b565b604051602081830303815290604052610c84565b6103b191906134eb565b60ff16606082015260006103c484610b66565b82516103d29060ff16610b66565b6103e2846020015160ff16610b66565b6103f2856040015160ff16610b66565b610402866060015160ff16610b66565b604051602001610416959493929190612bc8565b60408051601f198184030181526060830190915260388083529092507fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6916104b591613558602083013960608501516040860151610475906008613404565b61047f91906133ac565b60ff168560600151866040015160086104989190613404565b6104a291906133ac565b6104ad9060016133ac565b60ff16610d2a565b6040516020016104c591906126d6565b6040516020818303038152906040528051906020012014156104f2576233333360e91b60c0830152610519565b7f303030000000000000000000000000000000000000000000000000000000000060c08301525b61085584108061052a57506117e884115b1561056357600060808301526040516105479082906020016129d0565b60408051601f1981840301815291905260e08301525092915050565b610854841180156105755750610ecd84105b15610747576000610587605b866133d1565b90506000610596605b876134eb565b9050601c82101561062e5760288110806105b05750602c81115b156105ec57600060808501526040516105cd9084906020016129d0565b60408051601f1981840301815291905260e08501525091949350505050565b60016080850152604051610604908490602001612ab9565b60408051601f1981840301815291905260e085015250506233333360e91b60c08301525092915050565b601d8111801561063e5750603e81105b156107405761064e601c8361342d565b91507fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66106e4604051806101e001604052806101c081526020016136776101c09139601e8461069e8760206133e5565b6106a89190613394565b6106b2919061342d565b601e856106c08860206133e5565b6106ca9190613394565b6106d4919061342d565b6106df906001613394565b610d2a565b6040516020016106f491906126d6565b6040516020818303038152906040528051906020012014156107285760016080850152604051610604908490602001612ab9565b600060808501526040516105cd9084906020016129d0565b505061086f565b610fed8411801561075957506117e984105b1561086f57600061076b605b866133d1565b9050600061077a605b876134eb565b905060318210156107b057604a8110806105b05750604e8111156105ec57600060808501526040516105cd9084906020016129d0565b603e8211156107da57601b8111156107da57600060808501526040516105cd9084906020016129d0565b600c811180156107ea5750604f81105b1561086c576107fa60318361342d565b91507fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66106e46040518061052001604052806104e681526020016138376104e69139600d8461084a8760426133e5565b6108549190613394565b61085e919061342d565b600d856106c08860426133e5565b50505b600060808301526040516105479082906020016129d0565b6064546060906001600160a01b031633146108b557604051638e2aa84b60e01b815260040160405180910390fd5b81606384815481106108c9576108c961352b565b9060005260206000200190805190602001906108e6929190612375565b506063805480602002602001604051908101604052809291908181526020016000905b828210156109b557838290600052602060002001805461092890613474565b80601f016020809104026020016040519081016040528092919081815260200182805461095490613474565b80156109a15780601f10610976576101008083540402835291602001916109a1565b820191906000526020600020905b81548152906001019060200180831161098457829003601f168201915b505050505081526020019060010190610909565b50505050905092915050565b606060006109ce85610133565b905060006109e36109de83610e27565b61213e565b905060006109f083612292565b905060006024846040015160ff1660078110610a0e57610a0e61352b565b01610a1889610b66565b60e0860151604051610a39939291600a918c9088908d908b90602001612e1d565b6040516020818303038152906040529050610a538161213e565b604051602001610a6391906131d0565b6040516020818303038152906040529450505050509392505050565b6064546001600160a01b03163314610aaa57604051638e2aa84b60e01b815260040160405180910390fd5b8051610abd90600a906020840190612375565b5050565b6064546001600160a01b03163314610aec57604051638e2aa84b60e01b815260040160405180910390fd5b6001600160a01b038116610b2c576040517fe132e00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b606081610b8a5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115610bb45780610b9e816134af565b9150610bad9050600a836133d1565b9150610b8e565b60008167ffffffffffffffff811115610bcf57610bcf613541565b6040519080825280601f01601f191660200182016040528015610bf9576020820181803683370190505b5090505b8415610c7c57610c0e60018361342d565b9150610c1b600a866134eb565b610c26906030613394565b60f81b818381518110610c3b57610c3b61352b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610c75600a866133d1565b9450610bfd565b949350505050565b600081604051602001610c9791906126d6565b60408051601f19818403018152919052805160209091012092915050565b60008060009050600084600081518110610cd157610cd161352b565b602002602001015160ff1690505b838111610d225781610cf0816134af565b925050848281518110610d0557610d0561352b565b602002602001015160ff1681610d1b9190613394565b9050610cdf565b509392505050565b6060836000610d39858561342d565b67ffffffffffffffff811115610d5157610d51613541565b6040519080825280601f01601f191660200182016040528015610d7b576020820181803683370190505b509050845b84811015610e1d57828181518110610d9a57610d9a61352b565b01602001517fff000000000000000000000000000000000000000000000000000000000000001682610dcc888461342d565b81518110610ddc57610ddc61352b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080610e15816134af565b915050610d80565b5095945050505050565b606080600080846000015160ff1660058110610e4557610e4561352b565b602081049091015460ff601f9092166101000a90041667ffffffffffffffff811115610e7357610e73613541565b604051908082528060200260200182016040528015610ea657816020015b6060815260200190600190039081610e915790505b5090506000846000015160ff1660058110610ec357610ec361352b565b602091828204019190069054906101000a900460ff1660ff1660081415611027576040518060400160405280600581526020017f31322e3525000000000000000000000000000000000000000000000000000000815250915060005b845160009060ff1660058110610f3757610f3761352b565b602081049091015460ff601f9092166101000a9004168110156110215760108160088110610f6757610f6761352b565b018054610f7390613474565b80601f0160208091040260200160405190810160405280929190818152602001828054610f9f90613474565b8015610fec5780601f10610fc157610100808354040283529160200191610fec565b820191906000526020600020905b815481529060010190602001808311610fcf57829003601f168201915b50505050508282815181106110035761100361352b565b60200260200101819052508080611019906134af565b915050610f1f565b50611145565b61105f6003856000015160ff16600581106110445761104461352b565b602081049091015460ff601f9092166101000a900416610b66565b60405160200161106f9190612a78565b604051602081830303815290604052915060005b845160009060ff166005811061109b5761109b61352b565b602081049091015460ff601f9092166101000a900416811015611143576110f46003866000015160ff16600581106110d5576110d561352b565b60208104919091015461023491601f166101000a900460ff16836133e5565b6040516020016111049190612a78565b6040516020818303038152906040528282815181106111255761112561352b565b6020026020010181905250808061113b906134af565b915050611083565b505b61114d6123f9565b6000606060005b875160009060ff166005811061116c5761116c61352b565b602081049091015460ff601f9092166101000a90041681101561197257875160029060ff16600581106111a1576111a161352b565b602081049091015460ff601f9092166101000a9004168110806112365750875160029060ff16600581106111d7576111d761352b565b6020810491909101546111f791601f166101000a900460ff1660016133ac565b60ff168160008a6000015160ff16600581106112155761121561352b565b6020810491909101546112349291601f166101000a900460ff1661342d565b105b1561124057611960565b876020015160ff166001141561129457875160019060ff16600581106112685761126861352b565b602081049091015460ff601f9092166101000a900416611289826001613394565b111561129457611960565b876020015160ff1660021480156112bd575060028860a001516112b791906134ca565b61ffff16155b1561130657875160019060ff16600581106112da576112da61352b565b602081049091015460ff601f9092166101000a9004166112fb826001613394565b111561130657611960565b876020015160ff16600314801561132f575060028860a0015161132991906134ca565b61ffff16155b1561137857875160019060ff166005811061134c5761134c61352b565b602081049091015460ff601f9092166101000a90041661136d826001613394565b101561137857611960565b60005b885160009060ff16600581106113935761139361352b565b602081049091015460ff601f9092166101000a90041681101561195e57885160029060ff16600581106113c8576113c861352b565b602081049091015460ff601f9092166101000a90041681108061145d5750885160029060ff16600581106113fe576113fe61352b565b60208104919091015461141e91601f166101000a900460ff1660016133ac565b60ff168160008b6000015160ff166005811061143c5761143c61352b565b60208104919091015461145b9291601f166101000a900460ff1661342d565b105b156114675761194c565b602089015160ff1615806114825750886020015160ff166004145b156114d057885160019060ff166005811061149f5761149f61352b565b602081049091015460ff601f9092166101000a9004166114c0826001613394565b11156114cb5761194c565b6115bb565b886020015160ff16600214156115635760028960a001516114f191906134ca565b61ffff1661151157885160019060ff166005811061149f5761149f61352b565b60018260008b6000015160ff166005811061152e5761152e61352b565b60208104919091015461154d9291601f166101000a900460ff1661342d565b611557919061342d565b8111156114cb5761194c565b886020015160ff16600314156115bb5760028960a0015161158491906134ca565b61ffff166115a457885160019060ff166005811061149f5761149f61352b565b6115af826001613394565b8110156115bb5761194c565b611680600780548060200260200160405190810160405280929190818152602001828054801561162857602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116115f95790505b5050505050606461023e8c60e0015161166f8e60a0015161ffff1688601661165091906133e5565b61165b8960186133e5565b6116659190613394565b6102349190613394565b6040516020016103939291906126f2565b895160ff9182169550166117fe5760048960a0015161169f91906134ca565b61ffff166117665761175c600880548060200260200160405190810160405280929190818152602001828054801561171457602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116116e55790505b5050505050606461023e8c60e0015161166f8e60a0015161ffff1688600461173c91906133e5565b61174789600d6133e5565b6117519190613394565b61166590600d613394565b60ff1693506117fe565b60028960a0015161177791906134ca565b61ffff166117fe576117f86009805480602002602001604051908101604052809291908181526020018280548015611714576000918252602091829020805460ff1684529082028301929091600191018084116116e55790505050505050606461023e8c60e0015161166f8e60a0015161ffff1688600461173c91906133e5565b60ff1693505b8361182a578260405160200161181491906129ab565b604051602081830303815290604052925061194c565b8260405160200161183b9190612b4b565b60408051601f1981840301815291905292508461185960018661342d565b600381106118695761186961352b565b60200201518682815181106118805761188061352b565b602002602001015187848151811061189a5761189a61352b565b60200260200101516040516020016118b493929190612c5e565b60408051601f19818403018152919052856118d060018761342d565b600381106118e0576118e061352b565b6020020152846118f160018661342d565b600381106119015761190161352b565b6020020151878860405160200161191a93929190612cf5565b60408051601f198184030181529190528561193660018761342d565b600381106119465761194661352b565b60200201525b80611956816134af565b91505061137b565b505b8061196a816134af565b915050611154565b508660e001518160405160200161198a929190612b8c565b6040516020818303038152906040528760e0018190525060606000611a70602b8a606001518b6040015160086119c09190613404565b6119ca91906133ac565b60ff16603881106119dd576119dd61352b565b0180546119e990613474565b80601f0160208091040260200160405190810160405280929190818152602001828054611a1590613474565b8015611a625780601f10611a3757610100808354040283529160200191611a62565b820191906000526020600020905b815481529060010190602001808311611a4557829003601f168201915b505050505060006007610d2a565b9050886080015115611abc578081604051602001611a8f929190613215565b60408051601f1981840301815282820190915260048252630233030360e41b602083015292509050611ae1565b8081604051602001611acf929190612afa565b60405160208183030381529060405291505b60006040518060e0016040528060a7815260200161359060a791396063600081548110611b1057611b1061352b565b90600052602060002001611b2b8c60a0015161ffff16610b66565b6063600181548110611b3f57611b3f61352b565b90600052602060002001856063600281548110611b5e57611b5e61352b565b90600052602060002001604051602001611b7d969594939291906128d4565b604051602081830303815290604052905080611c5a602b8c606001518d604001516008611baa9190613404565b611bb491906133ac565b60ff1660388110611bc757611bc761352b565b018054611bd390613474565b80601f0160208091040260200160405190810160405280929190818152602001828054611bff90613474565b8015611c4c5780601f10611c2157610100808354040283529160200191611c4c565b820191906000526020600020905b815481529060010190602001808311611c2f57829003601f168201915b50505050506008600f610d2a565b6063600381548110611c6e57611c6e61352b565b6000918252602082200190899060200201516063600481548110611c9457611c9461352b565b90600052602060002001604051602001611cb2959493929190612771565b604051602081830303815290604052905080611d8f602b8c606001518d604001516008611cdf9190613404565b611ce991906133ac565b60ff1660388110611cfc57611cfc61352b565b018054611d0890613474565b80601f0160208091040260200160405190810160405280929190818152602001828054611d3490613474565b8015611d815780601f10611d5657610100808354040283529160200191611d81565b820191906000526020600020905b815481529060010190602001808311611d6457829003601f168201915b505050505060106017610d2a565b6063600581548110611da357611da361352b565b60009182526020909120018860016020020151604051602001611dc99493929190612721565b6040516020818303038152906040529050806063600681548110611def57611def61352b565b90600052602060002001611ec4602b8d606001518e604001516008611e149190613404565b611e1e91906133ac565b60ff1660388110611e3157611e3161352b565b018054611e3d90613474565b80601f0160208091040260200160405190810160405280929190818152602001828054611e6990613474565b8015611eb65780601f10611e8b57610100808354040283529160200191611eb6565b820191906000526020600020905b815481529060010190602001808311611e9957829003601f168201915b50505050506018601f610d2a565b6063600781548110611ed857611ed861352b565b90600052602060002001604051602001611ef59493929190612898565b60408051601f1981840301815291905290508086600260200201516063600881548110611f2457611f2461352b565b90600052602060002001601e8d6020015160ff1660068110611f4857611f4861352b565b01604051602001611f5c94939291906127cf565b6040516020818303038152906040529050806063600981548110611f8257611f8261352b565b906000526020600020018b60c001516063600a81548110611fa557611fa561352b565b9060005260206000200160248e6040015160ff1660078110611fc957611fc961352b565b01611fdb8f60a0015161ffff16610b66565b604051602001611ff096959493929190612816565b6040516020818303038152906040529050806063600b815481106120165761201661352b565b90600052602060002001602b8c606001518d6040015160086120389190613404565b61204291906133ac565b60ff16603881106120555761205561352b565b016063600c8154811061206a5761206a61352b565b906000526020600020016040516020016120879493929190612976565b604051602081830303815290604052905080602b8b606001518c6040015160086120b19190613404565b6120bb91906133ac565b60ff16603881106120ce576120ce61352b565b016063600d815481106120e3576120e361352b565b90600052602060002001856063600e815481106121025761210261352b565b9060005260206000200160405160200161212095949392919061293d565b60408051601f198184030181529190529a9950505050505050505050565b606081516000141561215e57505060408051602081019091526000815290565b6000604051806060016040528060408152602001613637604091399050600060038451600261218d9190613394565b61219791906133d1565b6121a29060046133e5565b67ffffffffffffffff8111156121ba576121ba613541565b6040519080825280601f01601f1916602001820160405280156121e4576020820181803683370190505b509050600182016020820185865187015b80821015612250576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506121f5565b505060038651066001811461226c576002811461227f57612287565b603d6001830353603d6002830353612287565b603d60018303535b509195945050505050565b60606000600b836000015160ff16600581106122b0576122b061352b565b016018846020015160ff16600681106122cb576122cb61352b565b016024856040015160ff16600781106122e6576122e661352b565b016122f7866060015160ff16610b66565b60405160200161230a9493929190612fef565b604051602081830303815290604052905082608001511561234c57806040516020016123369190612db6565b604051602081830303815290604052905061236f565b8060405160200161235d9190612a11565b60405160208183030381529060405290505b92915050565b82805461238190613474565b90600052602060002090601f0160209004810192826123a357600085556123e9565b82601f106123bc57805160ff19168380011785556123e9565b828001600101855582156123e9579182015b828111156123e95782518255916020019190600101906123ce565b506123f5929150612420565b5090565b60405180606001604052806003905b60608152602001906001900390816124085790505090565b5b808211156123f55760008155600101612421565b600082601f83011261244657600080fd5b813567ffffffffffffffff8082111561246157612461613541565b604051601f8301601f19908116603f0116810190828211818310171561248957612489613541565b816040528381528660208588010111156124a257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000602082840312156124d457600080fd5b81356001600160a01b03811681146124eb57600080fd5b9392505050565b60006020828403121561250457600080fd5b813567ffffffffffffffff81111561251b57600080fd5b610c7c84828501612435565b60006020828403121561253957600080fd5b5035919050565b6000806040838503121561255357600080fd5b82359150602083013567ffffffffffffffff81111561257157600080fd5b61257d85828601612435565b9150509250929050565b60008060006060848603121561259c57600080fd5b83359250602084013567ffffffffffffffff808211156125bb57600080fd5b6125c787838801612435565b935060408601359150808211156125dd57600080fd5b506125ea86828701612435565b9150509250925092565b6000815180845261260c816020860160208601613444565b601f01601f19169290920160200192915050565b60008151612632818560208601613444565b9290920192915050565b8054600090600181811c908083168061265657607f831692505b602080841082141561267857634e487b7160e01b600052602260045260246000fd5b81801561268c576001811461269d576126ca565b60ff198616895284890196506126ca565b60008881526020902060005b868110156126c25781548b8201529085019083016126a9565b505084890196505b50505050505092915050565b600082516126e8818460208701613444565b9190910192915050565b60008351612704818460208801613444565b835190830190612718818360208801613444565b01949350505050565b60008551612733818460208a01613444565b855190830190612747818360208a01613444565b6127538183018761263c565b9150508351612766818360208801613444565b019695505050505050565b60008651612783818460208b01613444565b865190830190612797818360208b01613444565b6127a38183018861263c565b91505084516127b6818360208901613444565b6127c28183018661263c565b9998505050505050505050565b600085516127e1818460208a01613444565b8551908301906127f5818360208a01613444565b61280a6128048284018861263c565b8661263c565b98975050505050505050565b60008751612828818460208c01613444565b6128348184018961263c565b90507fffffff00000000000000000000000000000000000000000000000000000000008716815261286b612804600383018861263c565b905061202360f01b81528351612888816002840160208801613444565b0160020198975050505050505050565b600085516128aa818460208a01613444565b6128b68184018761263c565b905084516128c8818360208901613444565b61280a8183018661263c565b600087516128e6818460208c01613444565b6128f28184018961263c565b90508651612904818360208b01613444565b6129108183018861263c565b9150508451612923818360208901613444565b61292f8183018661263c565b9a9950505050505050505050565b6000865161294f818460208b01613444565b61296461295e8285018961263c565b8761263c565b905084516127b6818360208901613444565b60008551612988818460208a01613444565b6129a061299a61295e8386018961263c565b8561263c565b979650505050505050565b600082516129bd818460208701613444565b600360fc1b920191825250600101919050565b600082516129e2818460208701613444565b7f5f30000000000000000000000000000000000000000000000000000000000000920191825250600201919050565b60008251612a23818460208701613444565b7f7b2274726169745f74797065223a20225370656369616c205472616974222c209201918252507f2276616c7565223a224e6f6e65227d2c000000000000000000000000000000006020820152603001919050565b60008251612a8a818460208701613444565b7f2500000000000000000000000000000000000000000000000000000000000000920191825250600101919050565b60008251612acb818460208701613444565b7f5f31000000000000000000000000000000000000000000000000000000000000920191825250600201919050565b60008351612b0c818460208801613444565b603b60f81b90830190815264233030303b60d81b6001820181905260068201528351612b3f81600b840160208801613444565b01600b01949350505050565b60008251612b5d818460208701613444565b7f3100000000000000000000000000000000000000000000000000000000000000920191825250600101919050565b60008351612b9e818460208801613444565b605f60f81b9083019081528351612bbc816001840160208801613444565b01600101949350505050565b60008651612bda818460208b01613444565b8083019050605f60f81b8082528751612bfa816001850160208c01613444565b600192019182018190528651612c17816002850160208b01613444565b600292019182018190528551612c34816003850160208a01613444565b60039201918201528351612c4f816004840160208801613444565b01600401979650505050505050565b60008451612c70818460208901613444565b7f3c7265637420783d2200000000000000000000000000000000000000000000009083019081528451612caa816009840160208901613444565b7f2220793d22000000000000000000000000000000000000000000000000000000600992909101918201528351612ce881600e840160208801613444565b01600e0195945050505050565b60008451612d07818460208901613444565b7f222077696474683d2200000000000000000000000000000000000000000000009083019081528451612d41816009840160208901613444565b7f22206865696768743d2200000000000000000000000000000000000000000000600992909101918201528351612d7f816013840160208801613444565b7f222f3e00000000000000000000000000000000000000000000000000000000006013929091019182015260160195945050505050565b60008251612dc8818460208701613444565b7f7b2274726169745f74797065223a20225370656369616c205472616974222c209201918252507f2276616c7565223a22446f20476f6f64227d2c000000000000000000000000006020820152603301919050565b7f7b226e616d65223a22000000000000000000000000000000000000000000000081526000612e4f600983018b61263c565b61202360f01b81528951612e6a816002840160208e01613444565b7f222c226465736372697074696f6e223a2200000000000000000000000000000060029290910191820152612ea2601382018a61263c565b90507f222c22444e41223a22000000000000000000000000000000000000000000000081528751612eda816009840160208c01613444565b7f222c000000000000000000000000000000000000000000000000000000000000600992909101918201528651612f1881600b840160208b01613444565b7f2c2261747472696275746573223a5b0000000000000000000000000000000000600b9290910191820152612fe0612fb7612fb1612f62612f5c601a86018b612620565b89612620565b7f5d2c22696d616765223a22646174613a696d6167652f7376672b786d6c3b626181527f736536342c000000000000000000000000000000000000000000000000000000602082015260250190565b86612620565b7f227d000000000000000000000000000000000000000000000000000000000000815260020190565b9b9a5050505050505050505050565b7f7b2274726169745f74797065223a2022506978656c2053697a65222c2022766181527f6c7565223a22000000000000000000000000000000000000000000000000000060208201526000613047602683018761263c565b7f227d2c7b2274726169745f74797065223a202253796d6d65747279222c20227681527f616c7565223a2200000000000000000000000000000000000000000000000000602082015261309d602782018761263c565b90507f227d2c7b2274726169745f74797065223a2022436f6c6f722047726f7570222c81527f202276616c7565223a220000000000000000000000000000000000000000000060208201526130f5602a82018661263c565b90507f227d2c7b2274726169745f74797065223a202250616c6574746520496e64657881527f222c202276616c7565223a2200000000000000000000000000000000000000006020820152835161315381602c840160208801613444565b7f227d2c0000000000000000000000000000000000000000000000000000000000602c9290910191820152602f019695505050505050565b7f5774683f000000000000000000000000000000000000000000000000000000008152600082516131c3816004850160208701613444565b9190910160040192915050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161320881601d850160208701613444565b91909101601d0192915050565b64233030303b60d81b815260008351613235816005850160208801613444565b8083019050603b60f81b8060058301528451613258816006850160208901613444565b6006920191820152630233030360e41b6007820152600b01949350505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156132cd57603f198886030184526132bb8583516125f4565b9450928501929085019060010161329f565b5092979650505050505050565b6020815260006124eb60208301846125f4565b6020815260ff825116602082015260ff60208301511660408201526000604083015161331e606084018260ff169052565b50606083015160ff8116608084015250608083015180151560a08401525060a083015161ffff811660c08401525060c08301517fffffff0000000000000000000000000000000000000000000000000000000000811660e08401525060e083015161010083810152610c7c6101208401826125f4565b600082198211156133a7576133a76134ff565b500190565b600060ff821660ff84168060ff038211156133c9576133c96134ff565b019392505050565b6000826133e0576133e0613515565b500490565b60008160001904831182151516156133ff576133ff6134ff565b500290565b600060ff821660ff84168160ff0481118215151615613425576134256134ff565b029392505050565b60008282101561343f5761343f6134ff565b500390565b60005b8381101561345f578181015183820152602001613447565b8381111561346e576000848401525b50505050565b600181811c9082168061348857607f821691505b602082108114156134a957634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156134c3576134c36134ff565b5060010190565b600061ffff808416806134df576134df613515565b92169190910692915050565b6000826134fa576134fa613515565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfe30313030303130313131313131313131313130303030313030303030303131303130313030303131303131313131303031303131313030303c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b22207072657365727665417370656374526174696f3d22784d696e594d696e222073686170652d72656e646572696e673d2263726973704564676573222076696577426f783d2230203020313030302031303030223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f30303030313131313130313131313130303030303031313131313131303030303030313131313131313131313131313030303031313131313131313131313030303131313131313131313131313131303030313131313131313131313131313031313131313131313131313131313130303131313131313131313131313131313131313131313030303131313131313030313131313131303030313131313131313131313130303030303131313131303031313131313030303030313131313131313131313030303030313131313130303131313131303030303031313131313131313131303030303031313131313030313131313130303030303131313131313131313130303030303131313131303031313131313030303030313131313131313131313130303031313131313130303131313131313030303131313131313131313131313131313131313131313030313131313131313131313131313131303131313131313131313131313131303030313131313131313131313131313030303131313131313131313131313130303030313131313131313131313130303030303131313131313031313131313030303030303131313131313130303030303030303131313130303131313131303030303030313131313131313030303030303030303031313131313131303030303030303030303131313131303131313131303031313131313131313131313131303030303131313131313131313131303030303030313131313131313131313130303030303031313131313131313131313131303131313131313131313131313131303030313131313131313131313131313030303031313131313131313131313131303030303131313131313131313131313131313131313131313131313131313131303031313131313131313131313131313130303131313131313131313131313131313030313131313131313131313131313131313131313131303030313131313131303031313131313130303031313131313130303131313131313030303131313131313030313131313131303030313131313131313131313130303030303131313131303031313131313030303030313131313130303131313131303030303031313131313030313131313130303030303131313131313131313130303030303131313131303031313131313030303030313131313130303131313131303030303031313131313030313131313130303030303131313131313131313130303030303131313131303031313131313030303030313131313130303131313131303030303031313131313030313131313130303030303131313131313131313130303030303131313131303031313131313030303030313131313130303131313131303030303031313131313030313131313130303030303131313131313131313131303030313131313131303031313131313130303031313131313130303131313131313030303131313131313030313131313131303030313131313131303131313131313131313131313131303031313131313131313131313131313130303131313131313131313131313131313030313131313131313131313131313131303031313131313131313131313131303030313131313131313131313131313030303031313131313131313131313131303030303131313131313131313131313131303030313131313131303131313131303030303131313131313131313131303030303030313131313131313131313130303030303031313131313131313131313131303030303030303030303131313131303030303030313131313131313030303030303030303031313131313131303030303030303030313131313131303131313131303131313030303030313131313131303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303131313131313131313131313131303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303131313131313131313131313130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303131313131313131313131313030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303031313131313131313130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030a2646970667358221220ed7f5ad08c62fab5418f823981c19168bbff586bc3f7acb1ab252e9874a944cc64736f6c634300080700332220626567696e3d22636f6c6f7254776f47726f75702e636c69636b22206475723d2232222f3e3c616e696d6174655472616e73666f726d20786c696e6b3a687265663d2223796574416e6f7468657247726f7570466f72416e696d6174696f6e22206174747269627574654e616d653d227472616e73666f726d2220626567696e3d22636f6c6f7254776f47726f75702e636c69636b2220747970653d22726f74617465222076616c7565733d223020353030203530303b333630203530302035303022206475723d2232222f3e3c616e696d6174655472616e73666f726d20786c696e6b3a687265663d22236c6974746c65426c6f636b7322206174747269627574654e616d653d227472616e73666f726d2220626567696e3d22636f6c6f7254776f47726f75702e636c69636b222076616c7565733d223020303b2d31303030203022206475723d222e35222f3e3c616e696d6174655472616e73666f726d20786c696e6b3a687265663d22236c6974746c65426c6f636b7322206174747269627574654e616d653d227472616e73666f726d2220626567696e3d22636f6c6f7254776f47726f75702e636c69636b2b2e35222076616c7565733d223130303020303b2d31303030203022206475723d2231222f3e3c616e696d6174655472616e73666f726d20786c696e6b3a687265663d22236c6974746c65426c6f636b7322206174747269627574654e616d653d227472616e73666f726d2220626567696e3d22636f6c6f7254776f47726f75702e636c69636b2b312e35222076616c7565733d223130303020303b30203022206475723d222e35222f3e3c212d2d776861745468654865636b497348617070656e696e673f2d2d3e3c616e696d61746520786c696e6b3a687265663d22236261636b67726f756e6422206174747269627574654e616d653d2266696c6c2220626567696e3d22636f6c6f72546872656547726f75702e636c69636b222076616c7565733d2222206b657954696d65733d22303b2e30313b2e39393b3122206475723d223130222f3e3c616e696d6174655472616e73666f726d20786c696e6b3a687265663d2223796574416e6f7468657247726f7570466f72416e696d6174696f6e22206174747269627574654e616d653d227472616e73666f726d2220626567696e3d22636f6c6f72546872656547726f75702e636c69636b202b202e30322220747970653d227472616e736c617465222076616c7565733d223020303b302035303b30203235303b30203135303b3020303b22206b657954696d65733d22303b2e3030323b2e353b2e39383b3122206475723d22392e393873222f3e3c616e696d6174655472616e73666f726d20786c696e6b3a687265663d2223636f6c6f724f6e6547726f757022206174747269627574654e616d653d227472616e73666f726d222061646469746976653d2273756d2220747970653d227363616c652220626567696e3d22636f6c6f72546872656547726f75702e636c69636b222076616c7565733d22313b2e343b2e333b2e343b3122206b657954696d65733d22303b2e30323b2e353b2e39383b3122206475723d22313073222f3e3c616e696d6174655472616e73666f726d20786c696e6b3a687265663d2223636f6c6f724f6e6547726f757022206174747269627574654e616d653d227472616e73666f726d222061646469746976653d2273756d2220747970653d22726f746174652220626567696e3d22636f6c6f72546872656547726f75702e636c69636b202b202e3032222076616c7565733d2230203130303020313030303b203336302031303030203130303022206475723d22392e393873222f3e3c616e696d6174655472616e73666f726d20786c696e6b3a687265663d2223636f6c6f7254776f47726f757022206174747269627574654e616d653d227472616e73666f726d222061646469746976653d2273756d2220747970653d227363616c652220626567696e3d22636f6c6f72546872656547726f75702e636c69636b222076616c7565733d22313b2e363b2e353b2e363b3122206b657954696d65733d22303b2e30323b2e353b2e39383b3122206475723d22313073222f3e3c616e696d6174655472616e73666f726d20786c696e6b3a687265663d2223636f6c6f7254776f47726f757022206174747269627574654e616d653d227472616e73666f726d222061646469746976653d2273756d2220747970653d22726f746174652220626567696e3d22636f6c6f72546872656547726f75702e636c69636b202b202e3032222076616c7565733d223020353030203630303b2d333630203530302036303022206475723d22392e393873222f3e3c616e696d6174655472616e73666f726d20786c696e6b3a687265663d2223636f6c6f72546872656547726f757022206174747269627574654e616d653d227472616e73666f726d222061646469746976653d2273756d2220747970653d227363616c652220626567696e3d22636f6c6f72546872656547726f75702e636c69636b222076616c7565733d22313b2e383b2e363b2e343b3122206b657954696d65733d22303b2e30313b2e353b2e39383b3122206475723d22313073222f3e3c616e696d6174655472616e73666f726d20786c696e6b3a687265663d2223636f6c6f72546872656547726f757022206174747269627574654e616d653d227472616e73666f726d222061646469746976653d2273756d2220747970653d22726f746174652220626567696e3d22636f6c6f72546872656547726f75702e636c69636b202b202e3032222076616c7565733d223020353030203530303b333630203530302035303022206475723d22392e393873222f3e3c2f7376673e3c2f673e3c672069643d22636f6c6f72546872656547726f7570222066696c6c3d22223e3c672069643d22626967426c6f636b223e3c726563742069643d226261636b67726f756e64222077696474683d223130302522206865696768743d2231303025222066696c6c3d222220626567696e3d22636f6c6f724f6e6547726f75702e636c69636b22206475723d222e35222f3e3c212d2d6c657473476f466f72415370696e2d2d3e3c616e696d61746520786c696e6b3a687265663d22236261636b67726f756e6422206174747269627574654e616d653d2266696c6c222076616c7565733d2228313030302c203029207363616c65282d312c312920726f746174652839302c3530302c353030293c2f673e3c2f673e3c672069643d22706f736572426c6f636b73223e3c75736520786c696e6b3a687265663d22236f67426c6f636b7322207472616e73666f726d3d227472616e736c61746522202f3e3c2f673e3c672069643d226c6974746c65426c6f636b73223e3c672069643d22796574416e6f7468657247726f7570466f72416e696d6174696f6e223e3c672069643d226f67426c6f636b73223e3c672069643d22636f6c6f724f6e6547726f7570222066696c6c3d2228313030302c203029207363616c65282d312c312920726f74617465282d39302c3530302c353030293c2f746578743e3c212d2d6c696c4e756467652d2d3e3c616e696d6174655472616e73666f726d2069643d226c696c4e75646765412220786c696e6b3a687265663d22236c6974746c65426c6f636b7322206174747269627574654e616d653d227472616e73666f726d2220747970653d22726f74617465222076616c7565733d223020353030203530303b313520353030203530303b3020353030203530303b2220626567696e3d22636f6c6f724f6e6547726f75702e636c69636b22206475723d222e35222f3e3c616e696d61746520786c696e6b3a687265663d22236261636b67726f756e6422206174747269627574654e616d653d2266696c6c222076616c7565733d22222f3e3c2f673e3c2f673e3c2f673e3c2f673e3c7465787420783d223130252220793d223936252220746578742d616e63686f723d226d6964646c65222066696c6c3d22232220666f6e742d73697a653d2231382220666f6e742d66616d696c793d22436f7572696572204e6577223e676f6f64626c6f636b732067656e65726174696f6e2030202867656e3029206973206d616465207570206f662072616e646f6d20706978656c20696d616765732e206865616420746f20676f6f64626c6f636b732e696f20746f206c6561726e206d6f72652061626f757420746865206172742070726f6365737321

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063dcc2345511610050578063dcc23455146100e0578063dd4a89131461010b578063f2fde38b1461012057600080fd5b806307160cf5146100775780631ea40c71146100a0578063c379dc43146100c0575b600080fd5b61008a610085366004612527565b610133565b60405161009791906132ed565b60405180910390f35b6100b36100ae366004612540565b610887565b6040516100979190613278565b6100d36100ce366004612587565b6109c1565b60405161009791906132da565b6064546100f3906001600160a01b031681565b6040516001600160a01b039091168152602001610097565b61011e6101193660046124f2565b610a7f565b005b61011e61012e3660046124c2565b610ac1565b604080516101008082018352600080835260208084018290528385018290526060808501839052608080860184905260a080870185905260c080880186905260e080890185905289519788018a52868852878601879052878a0187905287850187905292870186905286019490945284015261ffff861691830191909152600480548551818402810184019096528086529394929361024d939283018282801561021a57602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116101eb5790505b5050505050606461023e6102398760146102349190613394565b610b66565b610c84565b61024891906134eb565b610cb5565b60ff16815260058054604080516020808402820181019092528281526102d893909290918301828280156102be57602002820191906000526020600020906000905b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161028f5790505b5050505050606461023e6102398760166102349190613394565b60ff16602080830191909152600680546040805182850281018501909152818152610368939092919083018282801561034e57602002820191906000526020600020906000905b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161031f5790505b5050505050608c61023e6102398760016102349190613394565b60ff16604082015260086103a7610383610234866004613394565b604051602001610393919061318b565b604051602081830303815290604052610c84565b6103b191906134eb565b60ff16606082015260006103c484610b66565b82516103d29060ff16610b66565b6103e2846020015160ff16610b66565b6103f2856040015160ff16610b66565b610402866060015160ff16610b66565b604051602001610416959493929190612bc8565b60408051601f198184030181526060830190915260388083529092507fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6916104b591613558602083013960608501516040860151610475906008613404565b61047f91906133ac565b60ff168560600151866040015160086104989190613404565b6104a291906133ac565b6104ad9060016133ac565b60ff16610d2a565b6040516020016104c591906126d6565b6040516020818303038152906040528051906020012014156104f2576233333360e91b60c0830152610519565b7f303030000000000000000000000000000000000000000000000000000000000060c08301525b61085584108061052a57506117e884115b1561056357600060808301526040516105479082906020016129d0565b60408051601f1981840301815291905260e08301525092915050565b610854841180156105755750610ecd84105b15610747576000610587605b866133d1565b90506000610596605b876134eb565b9050601c82101561062e5760288110806105b05750602c81115b156105ec57600060808501526040516105cd9084906020016129d0565b60408051601f1981840301815291905260e08501525091949350505050565b60016080850152604051610604908490602001612ab9565b60408051601f1981840301815291905260e085015250506233333360e91b60c08301525092915050565b601d8111801561063e5750603e81105b156107405761064e601c8361342d565b91507fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66106e4604051806101e001604052806101c081526020016136776101c09139601e8461069e8760206133e5565b6106a89190613394565b6106b2919061342d565b601e856106c08860206133e5565b6106ca9190613394565b6106d4919061342d565b6106df906001613394565b610d2a565b6040516020016106f491906126d6565b6040516020818303038152906040528051906020012014156107285760016080850152604051610604908490602001612ab9565b600060808501526040516105cd9084906020016129d0565b505061086f565b610fed8411801561075957506117e984105b1561086f57600061076b605b866133d1565b9050600061077a605b876134eb565b905060318210156107b057604a8110806105b05750604e8111156105ec57600060808501526040516105cd9084906020016129d0565b603e8211156107da57601b8111156107da57600060808501526040516105cd9084906020016129d0565b600c811180156107ea5750604f81105b1561086c576107fa60318361342d565b91507fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66106e46040518061052001604052806104e681526020016138376104e69139600d8461084a8760426133e5565b6108549190613394565b61085e919061342d565b600d856106c08860426133e5565b50505b600060808301526040516105479082906020016129d0565b6064546060906001600160a01b031633146108b557604051638e2aa84b60e01b815260040160405180910390fd5b81606384815481106108c9576108c961352b565b9060005260206000200190805190602001906108e6929190612375565b506063805480602002602001604051908101604052809291908181526020016000905b828210156109b557838290600052602060002001805461092890613474565b80601f016020809104026020016040519081016040528092919081815260200182805461095490613474565b80156109a15780601f10610976576101008083540402835291602001916109a1565b820191906000526020600020905b81548152906001019060200180831161098457829003601f168201915b505050505081526020019060010190610909565b50505050905092915050565b606060006109ce85610133565b905060006109e36109de83610e27565b61213e565b905060006109f083612292565b905060006024846040015160ff1660078110610a0e57610a0e61352b565b01610a1889610b66565b60e0860151604051610a39939291600a918c9088908d908b90602001612e1d565b6040516020818303038152906040529050610a538161213e565b604051602001610a6391906131d0565b6040516020818303038152906040529450505050509392505050565b6064546001600160a01b03163314610aaa57604051638e2aa84b60e01b815260040160405180910390fd5b8051610abd90600a906020840190612375565b5050565b6064546001600160a01b03163314610aec57604051638e2aa84b60e01b815260040160405180910390fd5b6001600160a01b038116610b2c576040517fe132e00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b606081610b8a5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115610bb45780610b9e816134af565b9150610bad9050600a836133d1565b9150610b8e565b60008167ffffffffffffffff811115610bcf57610bcf613541565b6040519080825280601f01601f191660200182016040528015610bf9576020820181803683370190505b5090505b8415610c7c57610c0e60018361342d565b9150610c1b600a866134eb565b610c26906030613394565b60f81b818381518110610c3b57610c3b61352b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610c75600a866133d1565b9450610bfd565b949350505050565b600081604051602001610c9791906126d6565b60408051601f19818403018152919052805160209091012092915050565b60008060009050600084600081518110610cd157610cd161352b565b602002602001015160ff1690505b838111610d225781610cf0816134af565b925050848281518110610d0557610d0561352b565b602002602001015160ff1681610d1b9190613394565b9050610cdf565b509392505050565b6060836000610d39858561342d565b67ffffffffffffffff811115610d5157610d51613541565b6040519080825280601f01601f191660200182016040528015610d7b576020820181803683370190505b509050845b84811015610e1d57828181518110610d9a57610d9a61352b565b01602001517fff000000000000000000000000000000000000000000000000000000000000001682610dcc888461342d565b81518110610ddc57610ddc61352b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080610e15816134af565b915050610d80565b5095945050505050565b606080600080846000015160ff1660058110610e4557610e4561352b565b602081049091015460ff601f9092166101000a90041667ffffffffffffffff811115610e7357610e73613541565b604051908082528060200260200182016040528015610ea657816020015b6060815260200190600190039081610e915790505b5090506000846000015160ff1660058110610ec357610ec361352b565b602091828204019190069054906101000a900460ff1660ff1660081415611027576040518060400160405280600581526020017f31322e3525000000000000000000000000000000000000000000000000000000815250915060005b845160009060ff1660058110610f3757610f3761352b565b602081049091015460ff601f9092166101000a9004168110156110215760108160088110610f6757610f6761352b565b018054610f7390613474565b80601f0160208091040260200160405190810160405280929190818152602001828054610f9f90613474565b8015610fec5780601f10610fc157610100808354040283529160200191610fec565b820191906000526020600020905b815481529060010190602001808311610fcf57829003601f168201915b50505050508282815181106110035761100361352b565b60200260200101819052508080611019906134af565b915050610f1f565b50611145565b61105f6003856000015160ff16600581106110445761104461352b565b602081049091015460ff601f9092166101000a900416610b66565b60405160200161106f9190612a78565b604051602081830303815290604052915060005b845160009060ff166005811061109b5761109b61352b565b602081049091015460ff601f9092166101000a900416811015611143576110f46003866000015160ff16600581106110d5576110d561352b565b60208104919091015461023491601f166101000a900460ff16836133e5565b6040516020016111049190612a78565b6040516020818303038152906040528282815181106111255761112561352b565b6020026020010181905250808061113b906134af565b915050611083565b505b61114d6123f9565b6000606060005b875160009060ff166005811061116c5761116c61352b565b602081049091015460ff601f9092166101000a90041681101561197257875160029060ff16600581106111a1576111a161352b565b602081049091015460ff601f9092166101000a9004168110806112365750875160029060ff16600581106111d7576111d761352b565b6020810491909101546111f791601f166101000a900460ff1660016133ac565b60ff168160008a6000015160ff16600581106112155761121561352b565b6020810491909101546112349291601f166101000a900460ff1661342d565b105b1561124057611960565b876020015160ff166001141561129457875160019060ff16600581106112685761126861352b565b602081049091015460ff601f9092166101000a900416611289826001613394565b111561129457611960565b876020015160ff1660021480156112bd575060028860a001516112b791906134ca565b61ffff16155b1561130657875160019060ff16600581106112da576112da61352b565b602081049091015460ff601f9092166101000a9004166112fb826001613394565b111561130657611960565b876020015160ff16600314801561132f575060028860a0015161132991906134ca565b61ffff16155b1561137857875160019060ff166005811061134c5761134c61352b565b602081049091015460ff601f9092166101000a90041661136d826001613394565b101561137857611960565b60005b885160009060ff16600581106113935761139361352b565b602081049091015460ff601f9092166101000a90041681101561195e57885160029060ff16600581106113c8576113c861352b565b602081049091015460ff601f9092166101000a90041681108061145d5750885160029060ff16600581106113fe576113fe61352b565b60208104919091015461141e91601f166101000a900460ff1660016133ac565b60ff168160008b6000015160ff166005811061143c5761143c61352b565b60208104919091015461145b9291601f166101000a900460ff1661342d565b105b156114675761194c565b602089015160ff1615806114825750886020015160ff166004145b156114d057885160019060ff166005811061149f5761149f61352b565b602081049091015460ff601f9092166101000a9004166114c0826001613394565b11156114cb5761194c565b6115bb565b886020015160ff16600214156115635760028960a001516114f191906134ca565b61ffff1661151157885160019060ff166005811061149f5761149f61352b565b60018260008b6000015160ff166005811061152e5761152e61352b565b60208104919091015461154d9291601f166101000a900460ff1661342d565b611557919061342d565b8111156114cb5761194c565b886020015160ff16600314156115bb5760028960a0015161158491906134ca565b61ffff166115a457885160019060ff166005811061149f5761149f61352b565b6115af826001613394565b8110156115bb5761194c565b611680600780548060200260200160405190810160405280929190818152602001828054801561162857602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116115f95790505b5050505050606461023e8c60e0015161166f8e60a0015161ffff1688601661165091906133e5565b61165b8960186133e5565b6116659190613394565b6102349190613394565b6040516020016103939291906126f2565b895160ff9182169550166117fe5760048960a0015161169f91906134ca565b61ffff166117665761175c600880548060200260200160405190810160405280929190818152602001828054801561171457602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116116e55790505b5050505050606461023e8c60e0015161166f8e60a0015161ffff1688600461173c91906133e5565b61174789600d6133e5565b6117519190613394565b61166590600d613394565b60ff1693506117fe565b60028960a0015161177791906134ca565b61ffff166117fe576117f86009805480602002602001604051908101604052809291908181526020018280548015611714576000918252602091829020805460ff1684529082028301929091600191018084116116e55790505050505050606461023e8c60e0015161166f8e60a0015161ffff1688600461173c91906133e5565b60ff1693505b8361182a578260405160200161181491906129ab565b604051602081830303815290604052925061194c565b8260405160200161183b9190612b4b565b60408051601f1981840301815291905292508461185960018661342d565b600381106118695761186961352b565b60200201518682815181106118805761188061352b565b602002602001015187848151811061189a5761189a61352b565b60200260200101516040516020016118b493929190612c5e565b60408051601f19818403018152919052856118d060018761342d565b600381106118e0576118e061352b565b6020020152846118f160018661342d565b600381106119015761190161352b565b6020020151878860405160200161191a93929190612cf5565b60408051601f198184030181529190528561193660018761342d565b600381106119465761194661352b565b60200201525b80611956816134af565b91505061137b565b505b8061196a816134af565b915050611154565b508660e001518160405160200161198a929190612b8c565b6040516020818303038152906040528760e0018190525060606000611a70602b8a606001518b6040015160086119c09190613404565b6119ca91906133ac565b60ff16603881106119dd576119dd61352b565b0180546119e990613474565b80601f0160208091040260200160405190810160405280929190818152602001828054611a1590613474565b8015611a625780601f10611a3757610100808354040283529160200191611a62565b820191906000526020600020905b815481529060010190602001808311611a4557829003601f168201915b505050505060006007610d2a565b9050886080015115611abc578081604051602001611a8f929190613215565b60408051601f1981840301815282820190915260048252630233030360e41b602083015292509050611ae1565b8081604051602001611acf929190612afa565b60405160208183030381529060405291505b60006040518060e0016040528060a7815260200161359060a791396063600081548110611b1057611b1061352b565b90600052602060002001611b2b8c60a0015161ffff16610b66565b6063600181548110611b3f57611b3f61352b565b90600052602060002001856063600281548110611b5e57611b5e61352b565b90600052602060002001604051602001611b7d969594939291906128d4565b604051602081830303815290604052905080611c5a602b8c606001518d604001516008611baa9190613404565b611bb491906133ac565b60ff1660388110611bc757611bc761352b565b018054611bd390613474565b80601f0160208091040260200160405190810160405280929190818152602001828054611bff90613474565b8015611c4c5780601f10611c2157610100808354040283529160200191611c4c565b820191906000526020600020905b815481529060010190602001808311611c2f57829003601f168201915b50505050506008600f610d2a565b6063600381548110611c6e57611c6e61352b565b6000918252602082200190899060200201516063600481548110611c9457611c9461352b565b90600052602060002001604051602001611cb2959493929190612771565b604051602081830303815290604052905080611d8f602b8c606001518d604001516008611cdf9190613404565b611ce991906133ac565b60ff1660388110611cfc57611cfc61352b565b018054611d0890613474565b80601f0160208091040260200160405190810160405280929190818152602001828054611d3490613474565b8015611d815780601f10611d5657610100808354040283529160200191611d81565b820191906000526020600020905b815481529060010190602001808311611d6457829003601f168201915b505050505060106017610d2a565b6063600581548110611da357611da361352b565b60009182526020909120018860016020020151604051602001611dc99493929190612721565b6040516020818303038152906040529050806063600681548110611def57611def61352b565b90600052602060002001611ec4602b8d606001518e604001516008611e149190613404565b611e1e91906133ac565b60ff1660388110611e3157611e3161352b565b018054611e3d90613474565b80601f0160208091040260200160405190810160405280929190818152602001828054611e6990613474565b8015611eb65780601f10611e8b57610100808354040283529160200191611eb6565b820191906000526020600020905b815481529060010190602001808311611e9957829003601f168201915b50505050506018601f610d2a565b6063600781548110611ed857611ed861352b565b90600052602060002001604051602001611ef59493929190612898565b60408051601f1981840301815291905290508086600260200201516063600881548110611f2457611f2461352b565b90600052602060002001601e8d6020015160ff1660068110611f4857611f4861352b565b01604051602001611f5c94939291906127cf565b6040516020818303038152906040529050806063600981548110611f8257611f8261352b565b906000526020600020018b60c001516063600a81548110611fa557611fa561352b565b9060005260206000200160248e6040015160ff1660078110611fc957611fc961352b565b01611fdb8f60a0015161ffff16610b66565b604051602001611ff096959493929190612816565b6040516020818303038152906040529050806063600b815481106120165761201661352b565b90600052602060002001602b8c606001518d6040015160086120389190613404565b61204291906133ac565b60ff16603881106120555761205561352b565b016063600c8154811061206a5761206a61352b565b906000526020600020016040516020016120879493929190612976565b604051602081830303815290604052905080602b8b606001518c6040015160086120b19190613404565b6120bb91906133ac565b60ff16603881106120ce576120ce61352b565b016063600d815481106120e3576120e361352b565b90600052602060002001856063600e815481106121025761210261352b565b9060005260206000200160405160200161212095949392919061293d565b60408051601f198184030181529190529a9950505050505050505050565b606081516000141561215e57505060408051602081019091526000815290565b6000604051806060016040528060408152602001613637604091399050600060038451600261218d9190613394565b61219791906133d1565b6121a29060046133e5565b67ffffffffffffffff8111156121ba576121ba613541565b6040519080825280601f01601f1916602001820160405280156121e4576020820181803683370190505b509050600182016020820185865187015b80821015612250576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506121f5565b505060038651066001811461226c576002811461227f57612287565b603d6001830353603d6002830353612287565b603d60018303535b509195945050505050565b60606000600b836000015160ff16600581106122b0576122b061352b565b016018846020015160ff16600681106122cb576122cb61352b565b016024856040015160ff16600781106122e6576122e661352b565b016122f7866060015160ff16610b66565b60405160200161230a9493929190612fef565b604051602081830303815290604052905082608001511561234c57806040516020016123369190612db6565b604051602081830303815290604052905061236f565b8060405160200161235d9190612a11565b60405160208183030381529060405290505b92915050565b82805461238190613474565b90600052602060002090601f0160209004810192826123a357600085556123e9565b82601f106123bc57805160ff19168380011785556123e9565b828001600101855582156123e9579182015b828111156123e95782518255916020019190600101906123ce565b506123f5929150612420565b5090565b60405180606001604052806003905b60608152602001906001900390816124085790505090565b5b808211156123f55760008155600101612421565b600082601f83011261244657600080fd5b813567ffffffffffffffff8082111561246157612461613541565b604051601f8301601f19908116603f0116810190828211818310171561248957612489613541565b816040528381528660208588010111156124a257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000602082840312156124d457600080fd5b81356001600160a01b03811681146124eb57600080fd5b9392505050565b60006020828403121561250457600080fd5b813567ffffffffffffffff81111561251b57600080fd5b610c7c84828501612435565b60006020828403121561253957600080fd5b5035919050565b6000806040838503121561255357600080fd5b82359150602083013567ffffffffffffffff81111561257157600080fd5b61257d85828601612435565b9150509250929050565b60008060006060848603121561259c57600080fd5b83359250602084013567ffffffffffffffff808211156125bb57600080fd5b6125c787838801612435565b935060408601359150808211156125dd57600080fd5b506125ea86828701612435565b9150509250925092565b6000815180845261260c816020860160208601613444565b601f01601f19169290920160200192915050565b60008151612632818560208601613444565b9290920192915050565b8054600090600181811c908083168061265657607f831692505b602080841082141561267857634e487b7160e01b600052602260045260246000fd5b81801561268c576001811461269d576126ca565b60ff198616895284890196506126ca565b60008881526020902060005b868110156126c25781548b8201529085019083016126a9565b505084890196505b50505050505092915050565b600082516126e8818460208701613444565b9190910192915050565b60008351612704818460208801613444565b835190830190612718818360208801613444565b01949350505050565b60008551612733818460208a01613444565b855190830190612747818360208a01613444565b6127538183018761263c565b9150508351612766818360208801613444565b019695505050505050565b60008651612783818460208b01613444565b865190830190612797818360208b01613444565b6127a38183018861263c565b91505084516127b6818360208901613444565b6127c28183018661263c565b9998505050505050505050565b600085516127e1818460208a01613444565b8551908301906127f5818360208a01613444565b61280a6128048284018861263c565b8661263c565b98975050505050505050565b60008751612828818460208c01613444565b6128348184018961263c565b90507fffffff00000000000000000000000000000000000000000000000000000000008716815261286b612804600383018861263c565b905061202360f01b81528351612888816002840160208801613444565b0160020198975050505050505050565b600085516128aa818460208a01613444565b6128b68184018761263c565b905084516128c8818360208901613444565b61280a8183018661263c565b600087516128e6818460208c01613444565b6128f28184018961263c565b90508651612904818360208b01613444565b6129108183018861263c565b9150508451612923818360208901613444565b61292f8183018661263c565b9a9950505050505050505050565b6000865161294f818460208b01613444565b61296461295e8285018961263c565b8761263c565b905084516127b6818360208901613444565b60008551612988818460208a01613444565b6129a061299a61295e8386018961263c565b8561263c565b979650505050505050565b600082516129bd818460208701613444565b600360fc1b920191825250600101919050565b600082516129e2818460208701613444565b7f5f30000000000000000000000000000000000000000000000000000000000000920191825250600201919050565b60008251612a23818460208701613444565b7f7b2274726169745f74797065223a20225370656369616c205472616974222c209201918252507f2276616c7565223a224e6f6e65227d2c000000000000000000000000000000006020820152603001919050565b60008251612a8a818460208701613444565b7f2500000000000000000000000000000000000000000000000000000000000000920191825250600101919050565b60008251612acb818460208701613444565b7f5f31000000000000000000000000000000000000000000000000000000000000920191825250600201919050565b60008351612b0c818460208801613444565b603b60f81b90830190815264233030303b60d81b6001820181905260068201528351612b3f81600b840160208801613444565b01600b01949350505050565b60008251612b5d818460208701613444565b7f3100000000000000000000000000000000000000000000000000000000000000920191825250600101919050565b60008351612b9e818460208801613444565b605f60f81b9083019081528351612bbc816001840160208801613444565b01600101949350505050565b60008651612bda818460208b01613444565b8083019050605f60f81b8082528751612bfa816001850160208c01613444565b600192019182018190528651612c17816002850160208b01613444565b600292019182018190528551612c34816003850160208a01613444565b60039201918201528351612c4f816004840160208801613444565b01600401979650505050505050565b60008451612c70818460208901613444565b7f3c7265637420783d2200000000000000000000000000000000000000000000009083019081528451612caa816009840160208901613444565b7f2220793d22000000000000000000000000000000000000000000000000000000600992909101918201528351612ce881600e840160208801613444565b01600e0195945050505050565b60008451612d07818460208901613444565b7f222077696474683d2200000000000000000000000000000000000000000000009083019081528451612d41816009840160208901613444565b7f22206865696768743d2200000000000000000000000000000000000000000000600992909101918201528351612d7f816013840160208801613444565b7f222f3e00000000000000000000000000000000000000000000000000000000006013929091019182015260160195945050505050565b60008251612dc8818460208701613444565b7f7b2274726169745f74797065223a20225370656369616c205472616974222c209201918252507f2276616c7565223a22446f20476f6f64227d2c000000000000000000000000006020820152603301919050565b7f7b226e616d65223a22000000000000000000000000000000000000000000000081526000612e4f600983018b61263c565b61202360f01b81528951612e6a816002840160208e01613444565b7f222c226465736372697074696f6e223a2200000000000000000000000000000060029290910191820152612ea2601382018a61263c565b90507f222c22444e41223a22000000000000000000000000000000000000000000000081528751612eda816009840160208c01613444565b7f222c000000000000000000000000000000000000000000000000000000000000600992909101918201528651612f1881600b840160208b01613444565b7f2c2261747472696275746573223a5b0000000000000000000000000000000000600b9290910191820152612fe0612fb7612fb1612f62612f5c601a86018b612620565b89612620565b7f5d2c22696d616765223a22646174613a696d6167652f7376672b786d6c3b626181527f736536342c000000000000000000000000000000000000000000000000000000602082015260250190565b86612620565b7f227d000000000000000000000000000000000000000000000000000000000000815260020190565b9b9a5050505050505050505050565b7f7b2274726169745f74797065223a2022506978656c2053697a65222c2022766181527f6c7565223a22000000000000000000000000000000000000000000000000000060208201526000613047602683018761263c565b7f227d2c7b2274726169745f74797065223a202253796d6d65747279222c20227681527f616c7565223a2200000000000000000000000000000000000000000000000000602082015261309d602782018761263c565b90507f227d2c7b2274726169745f74797065223a2022436f6c6f722047726f7570222c81527f202276616c7565223a220000000000000000000000000000000000000000000060208201526130f5602a82018661263c565b90507f227d2c7b2274726169745f74797065223a202250616c6574746520496e64657881527f222c202276616c7565223a2200000000000000000000000000000000000000006020820152835161315381602c840160208801613444565b7f227d2c0000000000000000000000000000000000000000000000000000000000602c9290910191820152602f019695505050505050565b7f5774683f000000000000000000000000000000000000000000000000000000008152600082516131c3816004850160208701613444565b9190910160040192915050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161320881601d850160208701613444565b91909101601d0192915050565b64233030303b60d81b815260008351613235816005850160208801613444565b8083019050603b60f81b8060058301528451613258816006850160208901613444565b6006920191820152630233030360e41b6007820152600b01949350505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156132cd57603f198886030184526132bb8583516125f4565b9450928501929085019060010161329f565b5092979650505050505050565b6020815260006124eb60208301846125f4565b6020815260ff825116602082015260ff60208301511660408201526000604083015161331e606084018260ff169052565b50606083015160ff8116608084015250608083015180151560a08401525060a083015161ffff811660c08401525060c08301517fffffff0000000000000000000000000000000000000000000000000000000000811660e08401525060e083015161010083810152610c7c6101208401826125f4565b600082198211156133a7576133a76134ff565b500190565b600060ff821660ff84168060ff038211156133c9576133c96134ff565b019392505050565b6000826133e0576133e0613515565b500490565b60008160001904831182151516156133ff576133ff6134ff565b500290565b600060ff821660ff84168160ff0481118215151615613425576134256134ff565b029392505050565b60008282101561343f5761343f6134ff565b500390565b60005b8381101561345f578181015183820152602001613447565b8381111561346e576000848401525b50505050565b600181811c9082168061348857607f821691505b602082108114156134a957634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156134c3576134c36134ff565b5060010190565b600061ffff808416806134df576134df613515565b92169190910692915050565b6000826134fa576134fa613515565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfe30313030303130313131313131313131313130303030313030303030303131303130313030303131303131313131303031303131313030303c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b22207072657365727665417370656374526174696f3d22784d696e594d696e222073686170652d72656e646572696e673d2263726973704564676573222076696577426f783d2230203020313030302031303030223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f30303030313131313130313131313130303030303031313131313131303030303030313131313131313131313131313030303031313131313131313131313030303131313131313131313131313131303030313131313131313131313131313031313131313131313131313131313130303131313131313131313131313131313131313131313030303131313131313030313131313131303030313131313131313131313130303030303131313131303031313131313030303030313131313131313131313030303030313131313130303131313131303030303031313131313131313131303030303031313131313030313131313130303030303131313131313131313130303030303131313131303031313131313030303030313131313131313131313130303031313131313130303131313131313030303131313131313131313131313131313131313131313030313131313131313131313131313131303131313131313131313131313131303030313131313131313131313131313030303131313131313131313131313130303030313131313131313131313130303030303131313131313031313131313030303030303131313131313130303030303030303131313130303131313131303030303030313131313131313030303030303030303031313131313131303030303030303030303131313131303131313131303031313131313131313131313131303030303131313131313131313131303030303030313131313131313131313130303030303031313131313131313131313131303131313131313131313131313131303030313131313131313131313131313030303031313131313131313131313131303030303131313131313131313131313131313131313131313131313131313131303031313131313131313131313131313130303131313131313131313131313131313030313131313131313131313131313131313131313131303030313131313131303031313131313130303031313131313130303131313131313030303131313131313030313131313131303030313131313131313131313130303030303131313131303031313131313030303030313131313130303131313131303030303031313131313030313131313130303030303131313131313131313130303030303131313131303031313131313030303030313131313130303131313131303030303031313131313030313131313130303030303131313131313131313130303030303131313131303031313131313030303030313131313130303131313131303030303031313131313030313131313130303030303131313131313131313130303030303131313131303031313131313030303030313131313130303131313131303030303031313131313030313131313130303030303131313131313131313131303030313131313131303031313131313130303031313131313130303131313131313030303131313131313030313131313131303030313131313131303131313131313131313131313131303031313131313131313131313131313130303131313131313131313131313131313030313131313131313131313131313131303031313131313131313131313131303030313131313131313131313131313030303031313131313131313131313131303030303131313131313131313131313131303030313131313131303131313131303030303131313131313131313131303030303030313131313131313131313130303030303031313131313131313131313131303030303030303030303131313131303030303030313131313131313030303030303030303031313131313131303030303030303030313131313131303131313131303131313030303030313131313131303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303131313131313131313131313131303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303131313131313131313131313130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303131313131313131313131313030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303031313131313131313130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030a2646970667358221220ed7f5ad08c62fab5418f823981c19168bbff586bc3f7acb1ab252e9874a944cc64736f6c63430008070033

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.