ETH Price: $3,434.81 (+2.55%)

Contract

0x71d870A0AB98D2d012A5579642dCbbF447607781
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Approval For...188965862023-12-30 6:33:59329 days ago1703918039IN
0x71d870A0...447607781
0 ETH0.0002975212.27529456
Set Approval For...188964742023-12-30 6:11:11329 days ago1703916671IN
0x71d870A0...447607781
0 ETH0.0006356513.77371262
Set Approval For...188800792023-12-27 22:53:59332 days ago1703717639IN
0x71d870A0...447607781
0 ETH0.0006041525
Transfer From170904652023-04-20 21:55:11583 days ago1682027711IN
0x71d870A0...447607781
0 ETH0.0031913558.5075726
Set Approval For...170277322023-04-11 22:16:47592 days ago1681251407IN
0x71d870A0...447607781
0 ETH0.0013068228.30949023
Set Approval For...170277322023-04-11 22:16:47592 days ago1681251407IN
0x71d870A0...447607781
0 ETH0.0012002126
Set Approval For...170277322023-04-11 22:16:47592 days ago1681251407IN
0x71d870A0...447607781
0 ETH0.0011980226
Set Approval For...170094282023-04-09 7:59:59594 days ago1681027199IN
0x71d870A0...447607781
0 ETH0.000516921.31566562
Safe Transfer Fr...167466462023-03-03 7:58:23631 days ago1677830303IN
0x71d870A0...447607781
0 ETH0.0011156519.47582082
Set Approval For...159092932022-11-06 6:49:35748 days ago1667717375IN
0x71d870A0...447607781
0 ETH0.0002597910.7506217
Safe Transfer Fr...157951372022-10-21 7:58:35764 days ago1666339115IN
0x71d870A0...447607781
0 ETH0.0014609623.53206275
Set Approval For...156918252022-10-06 21:44:23779 days ago1665092663IN
0x71d870A0...447607781
0 ETH0.000368628
Mint_the_ball155931922022-09-23 2:54:59793 days ago1663901699IN
0x71d870A0...447607781
0 ETH0.000511974.77771173
Set Approval For...154034082022-08-24 14:20:28822 days ago1661350828IN
0x71d870A0...447607781
0 ETH0.0004324917.83493297
Set Approval For...154034082022-08-24 14:20:28822 days ago1661350828IN
0x71d870A0...447607781
0 ETH0.0004681617.83493297
Set Approval For...154034052022-08-24 14:19:34822 days ago1661350774IN
0x71d870A0...447607781
0 ETH0.0004434316.89267635
Set Approval For...154034042022-08-24 14:19:05822 days ago1661350745IN
0x71d870A0...447607781
0 ETH0.000368215.18375321
Set Approval For...153633452022-08-18 5:56:37828 days ago1660802197IN
0x71d870A0...447607781
0 ETH0.000252355.46669759
Set Approval For...153525882022-08-16 13:17:35830 days ago1660655855IN
0x71d870A0...447607781
0 ETH0.000276976
Set Approval For...153437282022-08-15 3:33:55831 days ago1660534435IN
0x71d870A0...447607781
0 ETH0.0005839312.6497605
Mint_the_ball153071292022-08-09 9:10:56837 days ago1660036256IN
0x71d870A0...447607781
0 ETH0.000589356.54422176
Mint_the_ball153071242022-08-09 9:10:14837 days ago1660036214IN
0x71d870A0...447607781
0 ETH0.000665867.39375543
Mint_the_ball153071212022-08-09 9:10:01837 days ago1660036201IN
0x71d870A0...447607781
0 ETH0.000716146.69498471
Mint_the_ball153016012022-08-08 12:37:28838 days ago1659962248IN
0x71d870A0...447607781
0 ETH0.0013362514.83774877
Mint_the_ball153016012022-08-08 12:37:28838 days ago1659962248IN
0x71d870A0...447607781
0 ETH0.0013334314.83774877
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ghoulBalls

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 6 : ghoulBalls.sol
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.13;

import {ERC721} from "solmate/tokens/ERC721.sol";
import {Owned} from "solmate/auth/Owned.sol";
import {libImg} from "../src/libImg.sol";
import {png} from "../src/png.sol";
import {json} from "../src/JSON.sol";

interface IBasedGhouls {
    function ownerOf(uint256 id) external view returns (address owner);
}

contract ghoulBalls is ERC721, Owned(msg.sender) {

    uint32 constant WIDTH_AND_HEIGHT = 128;
    int256 constant CIRCLE_RADIUS = 69;

    IBasedGhouls ghouls = IBasedGhouls(0xeF1a89cbfAbE59397FfdA11Fc5DF293E9bC5Db90);

    mapping(uint256 => bytes) internal colours;

    function _hash(bytes memory SAUCE) internal pure returns(bytes memory) {
        return abi.encodePacked(keccak256(SAUCE));
    }

    function toUint256(bytes memory _bytes) internal pure returns (uint256) {
        require(_bytes.length >= 32, "toUint256_outOfBounds");
        uint256 tempUint;

        assembly {
            tempUint := mload(add(_bytes, 0x20))
        }

        return tempUint;
    }

    // Each RGB is 3 bytes, determine number of balls that will be in the PNG then generate the colours
    function _generateColour(uint256 id) internal view returns(bytes memory) {
        uint256 randomish = toUint256(_hash(abi.encodePacked(id, msg.sender, block.timestamp)));

        if((randomish % 69) > 60) {
            return abi.encodePacked((uint144(randomish))); //6
        } else if((randomish % 69) > 50) {
            return abi.encodePacked((uint96(randomish))); //4
        } else if((randomish % 69) > 40) {
            return abi.encodePacked((uint48(randomish))); //2
        } else {
            return abi.encodePacked((uint24(randomish))); //1
        }
        
    }

    function mint_the_ball(uint256 id) public {
        require(id < 10000, "invalid ball.");
        if (id<6666) {
            require(ghouls.ownerOf(id) == msg.sender, "not your ghoul.");
        }
        require(_ownerOf[id] == address(0), "someone else got this ghoulBall.");

        colours[id] = _generateColour(id);

        _mint(msg.sender, id);
    }

    function click_for_utility(uint256 id) public {
        _burn(id);
    }

    function getPalette(uint256 id) internal view returns (bytes3[] memory) {
        bytes memory _coloursArr = colours[id];

        bytes3[] memory palette = new bytes3[](_coloursArr.length/3);

        for(uint256 i = 0; i<palette.length; i++) {
            palette[i] = 
                bytes3(
                    bytes.concat(
                        _coloursArr[i*3],
                        _coloursArr[i*3+1],
                        _coloursArr[i*3+2]
                    )
                );
        }

        return palette;
    }

    function tokenPNG(uint256 id) public view returns (string memory) {
        bytes3[] memory _palette = getPalette(id);

        libImg.IMAGE memory imgPixels = libImg.IMAGE(
            WIDTH_AND_HEIGHT,
            WIDTH_AND_HEIGHT,
            new bytes(WIDTH_AND_HEIGHT*WIDTH_AND_HEIGHT+1)
        );
        
        return png.encodedPNG(WIDTH_AND_HEIGHT, WIDTH_AND_HEIGHT, _palette, libImg.drawImage(imgPixels, _palette.length), true);

    }

    function tokenAttributes(uint256 id) internal view returns (string memory) {
        bytes memory plte = colours[id];

        string memory palettes;
        bool last;

        for (uint256 i = 0; i<plte.length/3; i++) {
            last = (i == (plte.length/3-1)) ? true : false;

            palettes = string.concat(
                palettes,
                json._attr(
                    string.concat('ball ', json.toString(i+1)),
                    string.concat(
                        json.toString(uint8(plte[i*3])),
                        ', ',
                        json.toString(uint8(plte[i*3+1])),
                        ', ',
                        json.toString(uint8(plte[i*3+2]))
                    ),
                    last
                )
            );
        }

        // we attach the number of balls, and colour palette to the ERC721 JSON
        return string.concat(
            json._attr('ball count', json.toString(plte.length/3)),
            palettes
        );

    }

    function tokenURI(uint256 id) public view override returns (string memory) {
        return json.formattedMetadata(
            'ghoulBalls',
            "ghoulBalls are fully onchain PNGs that evolve with every block, absolutely rugging the right-click savers after everyblock. No roadmap, no development, no utility, no marketing, and nothing more. They promise nothing and deliver even less. They're just PNGs.",
            tokenPNG(id),
            tokenAttributes(id)
        );
    }

    //never know if they'll rug us again with a v3
    function updateGhoulAddr(address ghoulAddr) public onlyOwner {
        ghouls = IBasedGhouls(ghoulAddr);
    }
    
    constructor() ERC721("ghoulBalls", unicode"🎊"){}

}

File 2 of 6 : ERC721.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*//////////////////////////////////////////////////////////////
                         METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                      ERC721 BALANCE/OWNER STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) internal _ownerOf;

    mapping(address => uint256) internal _balanceOf;

    function ownerOf(uint256 id) public view virtual returns (address owner) {
        require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
    }

    function balanceOf(address owner) public view virtual returns (uint256) {
        require(owner != address(0), "ZERO_ADDRESS");

        return _balanceOf[owner];
    }

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = _ownerOf[id];

        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        require(from == _ownerOf[id], "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
            "NOT_AUTHORIZED"
        );

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            _balanceOf[from]--;

            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes calldata data
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(_ownerOf[id] == address(0), "ALREADY_MINTED");

        // Counter overflow is incredibly unrealistic.
        unchecked {
            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        emit Transfer(address(0), to, id);
    }

    function _burn(uint256 id) internal virtual {
        address owner = _ownerOf[id];

        require(owner != address(0), "NOT_MINTED");

        // Ownership check above ensures no underflow.
        unchecked {
            _balanceOf[owner]--;
        }

        delete _ownerOf[id];

        delete getApproved[id];

        emit Transfer(owner, address(0), id);
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL SAFE MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _safeMint(address to, uint256 id) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _safeMint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721TokenReceiver {
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC721TokenReceiver.onERC721Received.selector;
    }
}

File 3 of 6 : Owned.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event OwnerUpdated(address indexed user, address indexed newOwner);

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnerUpdated(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function setOwner(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnerUpdated(msg.sender, newOwner);
    }
}

File 4 of 6 : libImg.sol
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.13;

library libImg {

    struct IMAGE{
        uint256 width;
        uint256 height;
        bytes pixels;
    }

    function toIndex(int256 _x, int256 _y, uint256 _width) internal pure returns (uint256 index){
        unchecked{
            index = uint256(_y) * (_width +1) + uint256(_x) + 1;
        }
        
    }

    function assignMidPoint(uint256 seed, uint256 width, uint256 height) internal pure returns (int256 x, int256 y) {

        x = int256(
                (
                    ((seed >> 2*8) % width) +
                    (width / 2)
                ) /2
            );

        y = int256(
                (
                    ((seed) % height) +
                    (height / 2)

                ) /2
            );


    }

    function rasterFilledCircle(IMAGE memory img, int256 xMid, int256 yMid, int256 r, bytes1 idxColour) internal pure returns (IMAGE memory) {

        int256 xSym;
        int256 ySym;
        int256 x = 0;
        int256 y = int(r);

        unchecked {
            for (x = xMid - r ; x <= xMid; x++) {
                for (y = yMid - r ; y <= yMid; y++) {
                    if ((x - xMid)*(x - xMid) + (y - yMid)*(y - yMid) <= r*r) 
                    {
                        xSym = xMid - (x - xMid);
                        ySym = yMid - (y - yMid);
                        // (x, y), (x, ySym), (xSym , y), (xSym, ySym) are in the circle
                        if (x >= 0 && y >= 0) {
                            img.pixels[toIndex(x, y,img.width)] = idxColour;
                        }
                        if (x >= 0 && ySym >= 0) {
                            img.pixels[toIndex(x, ySym,img.width)] = idxColour;
                        }
                        if (xSym >= 0 && y >= 0) {
                            img.pixels[toIndex(xSym, y,img.width)] = idxColour;
                        }
                        if (xSym >= 0 && ySym >= 0) {
                            img.pixels[toIndex(xSym, ySym,img.width)] = idxColour;
                        }
                    }
                }
            }
        }
        return img;
    }

    function drawImage(IMAGE memory img, uint256 circleCount) internal view returns (bytes memory){

        IMAGE memory tempImg;
        int256 xMid;
        int256 yMid;
        uint256 randoSeed;

        for (uint8 i = 0; i<circleCount; i++) {
            randoSeed = uint256(keccak256(abi.encodePacked(block.timestamp, i)));
            (xMid, yMid) = assignMidPoint(randoSeed, img.width, img.height);

            tempImg = rasterFilledCircle(img, xMid, yMid, int256(18), bytes1(i+1));
        }
        
        return tempImg.pixels;

    }

}

File 5 of 6 : png.sol
// SPDX-License-Identifier: Unlicense
/*
 * @title Onchain PNGs
 * @author Colin Platt <[email protected]>
 *
 * @dev PNG encoding tools written in Solidity for producing read-only onchain PNG files.
 */

pragma solidity =0.8.13;

library png {
    
    struct RGBA {
        bytes1 red;
        bytes1 green;
        bytes1 blue;
    }

    function rgbToPalette(bytes1 red, bytes1 green, bytes1 blue) internal pure returns (bytes3) {
        return bytes3(abi.encodePacked(red, green, blue));
    }

    function rgbToPalette(RGBA memory _rgb) internal pure returns (bytes3) {
        return bytes3(abi.encodePacked(_rgb.red, _rgb.green, _rgb.blue));
    }

    function calculateBitDepth(uint256 _length) internal pure returns (uint256) {
        if (_length < 3) {
            return 2;
        } else if(_length < 5) {
            return 4;
        } else if(_length < 17) {
            return 16;
        } else {
            return 256;
        }
    }

    function formatPalette(bytes3[] memory _palette, bool _8bit) internal pure returns (bytes memory) {
        require(_palette.length <= 256, "PNG: Palette too large.");

        uint256 depth = _8bit? uint256(256) : calculateBitDepth(_palette.length);
        bytes memory paletteObj;

        for (uint i = 0; i<_palette.length; i++) {
            paletteObj = abi.encodePacked(paletteObj, _palette[i]);
        }

        for (uint i = _palette.length; i<depth-1; i++) {
            paletteObj = abi.encodePacked(paletteObj, bytes3(0x000000));
        }

        return abi.encodePacked(
            uint32(depth*3),
            'PLTE',
            bytes3(0x000000),
            paletteObj
        );
    }

    function _tRNS(uint256 _bitDepth, uint256 _palette) internal pure returns (bytes memory) {

        bytes memory tRNSObj = abi.encodePacked(bytes1(0x00));

        for (uint i = 0; i<_palette; i++) {
            tRNSObj = abi.encodePacked(tRNSObj, bytes1(0xFF));
        }

        for (uint i = _palette; i<_bitDepth-1; i++) {
            tRNSObj = abi.encodePacked(tRNSObj, bytes1(0x00));
        }

        return abi.encodePacked(
            uint32(_bitDepth),
            'tRNS',
            tRNSObj
        );
    }

    function rawPNG(uint32 width, uint32 height, bytes3[] memory palette, bytes memory pixels, bool force8bit) internal pure returns (bytes memory) {

        uint256[256] memory crcTable = calcCrcTable();

        // Write PLTE
        bytes memory plte = formatPalette(palette, force8bit);

        // Write tRNS
        bytes memory tRNS = png._tRNS(
            force8bit ? 256 : calculateBitDepth(palette.length),
            palette.length
            );

        // Write IHDR
        bytes21 header = bytes21(abi.encodePacked(
                uint32(13),
                'IHDR',
                width,
                height,
                bytes5(0x0803000000)
            )
        );

        bytes7 deflate = bytes7(
            abi.encodePacked(
                bytes2(0x78DA),
                pixels.length > 65535 ? bytes1(0x00) :  bytes1(0x01),
                png.byte2lsb(uint16(pixels.length)),
                ~png.byte2lsb(uint16(pixels.length))
            )
        );

        bytes memory zlib = abi.encodePacked('IDAT', deflate, pixels, _adler32(pixels));

        return abi.encodePacked(
            bytes8(0x89504E470D0A1A0A),
            header, 
            _CRC(crcTable, abi.encodePacked(header),4),
            plte, 
            _CRC(crcTable, abi.encodePacked(plte),4),
            tRNS, 
            _CRC(crcTable, abi.encodePacked(tRNS),4),
            uint32(zlib.length-4),
            zlib,
            _CRC(crcTable, abi.encodePacked(zlib), 0), 
            bytes12(0x0000000049454E44AE426082)
        );

    }

    function encodedPNG(uint32 width, uint32 height, bytes3[] memory palette, bytes memory pixels, bool force8bit) internal pure returns (string memory) {
        return string.concat('data:image/png;base64,', base64encode(rawPNG(width, height, palette, pixels, force8bit)));
    }






    // @dev Does not check out of bounds
    function coordinatesToIndex(uint256 _x, uint256 _y, uint256 _width) internal pure returns (uint256 index) {
            index = _y * (_width + 1) + _x + 1;
	}

    

    








    /////////////////////////// 
    /// Checksums

    // need to check faster ways to do this
    function calcCrcTable() internal pure returns (uint256[256] memory crcTable) {
        uint256 c;

        unchecked{
            for(uint256 n = 0; n < 256; n++) {
                c = n;
                for (uint256 k = 0; k < 8; k++) {
                    if(c & 1 == 1) {
                        c = 0xedb88320 ^ (c >>1);
                    } else {
                        c = c >> 1;
                    }
                }
                crcTable[n] = c;
            }
        }
    }

    function _CRC(uint256[256] memory crcTable, bytes memory chunk, uint256 offset) internal pure returns (bytes4) {

        uint256 len = chunk.length;

        uint32 c = uint32(0xffffffff);
        unchecked{
            for(uint256 n = offset; n < len; n++) {
                c = uint32(crcTable[(c^uint8(chunk[n])) & 0xff] ^ (c >> 8));
            }
        }
        return bytes4(c)^0xffffffff;

    }

    
    function _adler32(bytes memory _data) internal pure returns (bytes4) {
        uint32 a = 1;
        uint32 b = 0;

        uint256 _len = _data.length;

        unchecked {
            for (uint256 i = 0; i < _len; i++) {
                a = (a + uint8(_data[i])) % 65521; //may need to convert to uint32
                b = (b + a) % 65521;
            }
        }

        return bytes4((b << 16) | a);

    }

    /////////////////////////// 
    /// Utilities

    function byte2lsb(uint16 _input) internal pure returns (bytes2) {

        return byte2lsb(bytes2(_input));

    }

    function byte2lsb(bytes2 _input) internal pure returns (bytes2) {

        return bytes2(abi.encodePacked(bytes1(_input << 8), bytes1(_input)));

    }

    function _toBuffer(bytes memory _bytes) internal pure returns (bytes1[] memory) {

        uint256 _length = _bytes.length;

        bytes1[] memory byteArray = new bytes1[](_length);
        bytes memory tempBytes;

        unchecked{
            for (uint256 i = 0; i<_length; i++) {
                assembly {
                    // Get a location of some free memory and store it in tempBytes as
                    // Solidity does for memory variables.
                    tempBytes := mload(0x40)

                    // The first word of the slice result is potentially a partial
                    // word read from the original array. To read it, we calculate
                    // the length of that partial word and start copying that many
                    // bytes into the array. The first word we copy will start with
                    // data we don't care about, but the last `lengthmod` bytes will
                    // land at the beginning of the contents of the new array. When
                    // we're done copying, we overwrite the full first word with
                    // the actual length of the slice.
                    let lengthmod := and(1, 31)

                    // The multiplication in the next line is necessary
                    // because when slicing multiples of 32 bytes (lengthmod == 0)
                    // the following copy loop was copying the origin's length
                    // and then ending prematurely not copying everything it should.
                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                    let end := add(mc, 1)

                    for {
                        // The multiplication in the next line has the same exact purpose
                        // as the one above.
                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), i)
                    } lt(mc, end) {
                        mc := add(mc, 0x20)
                        cc := add(cc, 0x20)
                    } {
                        mstore(mc, mload(cc))
                    }

                    mstore(tempBytes, 1)

                    //update free-memory pointer
                    //allocating the array padded to 32 bytes like the compiler does now
                    mstore(0x40, and(add(mc, 31), not(31)))
                }

                byteArray[i] = bytes1(tempBytes);

            }
        }
        
        return byteArray;
    }

    /**
     * @dev Base64 Encoding/Decoding Table
     */
    string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    /**
     * @dev Converts a `bytes` to its Bytes64 `string` representation.
     */
    function base64encode(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;
    }



}

File 6 of 6 : JSON.sol
//SPDX-License-Identifier: Unlicense
/*
 * @title ERC721 JSON metadata
 * @author Colin Platt <[email protected]>
 *
 * @dev JSON utilities for base64 encoded ERC721 JSON metadata schema
 */
pragma solidity ^0.8.12;

library json {
    
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @dev JSON requires that double quotes be escaped or JSONs will not build correctly
    /// string.concat also requires an escape, use \\" or the constant DOUBLE_QUOTES to represent " in JSON
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////

    string constant DOUBLE_QUOTES = '\\"';

    function formattedMetadata(
        string memory name,
        string memory description,
        string memory pngImg,
        string memory attributes
    )   internal
        pure
        returns (string memory)
    {
        return string.concat(
            'data:application/json;base64,',
            encode(
                bytes(
                    string.concat(
                    '{',
                    _prop('name', name),
                    _prop('description', description),
                    _xmlImage(pngImg),
                    _objectSq('attributes', attributes),
                    '}'
                    )
                )
            )
        );
    }
    
    function _xmlImage(string memory _pngImg)
        internal
        pure
        returns (string memory) 
    {
        return _prop(
                        'image',
                        string.concat(
                            'data:image/svg+xml;base64,',
                            encode(
                                bytes(string.concat(
                                    '<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">  <image x="0" y="0" width="128" height="128" preserveAspectRatio="xMidYMid" xlink:href="',
                                    _pngImg,
                                    '"/></svg>'
                                ))
                            )
                        ),
                        false
        );
    }

    function _prop(string memory _key, string memory _val)
        internal
        pure
        returns (string memory)
    {
        return string.concat('"', _key, '": ', '"', _val, '", ');
    }

    function _prop(string memory _key, string memory _val, bool last)
        internal
        pure
        returns (string memory)
    {
        if(last) {
            return string.concat('"', _key, '": ', '"', _val, '"');
        } else {
            return string.concat('"', _key, '": ', '"', _val, '", ');
        }
        
    }

    function _object(string memory _key, string memory _val)
        internal
        pure
        returns (string memory)
    {
        return string.concat('"', _key, '": ', '{', _val, '}');
    }

    function _objectSq(string memory _key, string memory _val)
        internal
        pure
        returns (string memory)
    {
        return string.concat('"', _key, '": ', '[', _val, ']');
    }

    function _attr(string memory _trait_type, string memory _value)
        internal
        pure
        returns (string memory)
    {
        return string.concat('{"trait_type": "', _trait_type, '", ', '"value" : "', _value, '"}, ');
    }

    function _attr(string memory _trait_type, string memory _value, bool last)
        internal
        pure
        returns (string memory)
    {
        if (last) {
            return string.concat('{"trait_type": "', _trait_type, '", ', '"value" : "', _value, '"}');
        } else {
            return string.concat('{"trait_type": "', _trait_type, '", ', '"value" : "', _value, '"}, ');
        }
        
    }

     
     /**
     * taken from Openzeppelin
     * @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;
    }

    /**
     * taken from Openzeppelin
     * @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);
    }

}

Settings
{
  "remappings": [
    "ds-test/=lib/solmate/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "solidity-trigonometry/=lib/solidity-trigonometry/src/",
    "solmate/=lib/solmate/src/",
    "src/=src/",
    "test/=test/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"click_for_utility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"mint_the_ball","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenPNG","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"ghoulAddr","type":"address"}],"name":"updateGhoulAddr","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052600780546001600160a01b03191673ef1a89cbfabe59397ffda11fc5df293e9bc5db901790553480156200003757600080fd5b50604080518082018252600a81526967686f756c42616c6c7360b01b602080830191825283518085019094526004845263784fc74560e11b908401528151339391620000879160009190620000f2565b5080516200009d906001906020840190620000f2565b5050600680546001600160a01b0319166001600160a01b0384169081179091556040519091506000907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a350620001d4565b828054620001009062000198565b90600052602060002090601f0160209004810192826200012457600085556200016f565b82601f106200013f57805160ff19168380011785556200016f565b828001600101855582156200016f579182015b828111156200016f57825182559160200191906001019062000152565b506200017d92915062000181565b5090565b5b808211156200017d576000815560010162000182565b600181811c90821680620001ad57607f821691505b602082108103620001ce57634e487b7160e01b600052602260045260246000fd5b50919050565b61328580620001e46000396000f3fe608060405234801561001057600080fd5b50600436106101205760003560e01c80636352211e116100ad578063a8ce53a011610071578063a8ce53a014610279578063b88d4fde1461028c578063c87b56dd1461029f578063d79d93d4146102b2578063e985e9c5146102c557600080fd5b80636352211e1461021757806370a082311461022a5780638da5cb5b1461024b57806395d89b411461025e578063a22cb4651461026657600080fd5b8063095ea7b3116100f4578063095ea7b3146101b857806313af4035146101cb57806323b872dd146101de57806335842845146101f157806342842e0e1461020457600080fd5b806223a12e1461012557806301ffc9a71461013a57806306fdde0314610162578063081812fc14610177575b600080fd5b610138610133366004612422565b6102f3565b005b61014d610148366004612455565b610363565b60405190151581526020015b60405180910390f35b61016a6103b5565b60405161015991906124a2565b6101a06101853660046124d5565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610159565b6101386101c63660046124ee565b610443565b6101386101d9366004612422565b610525565b6101386101ec36600461251a565b6105ba565b61016a6101ff3660046124d5565b610781565b61013861021236600461251a565b61083e565b6101a06102253660046124d5565b610936565b61023d610238366004612422565b61098d565b604051908152602001610159565b6006546101a0906001600160a01b031681565b61016a6109f0565b61013861027436600461255b565b6109fd565b6101386102873660046124d5565b610a69565b61013861029a366004612599565b610a75565b61016a6102ad3660046124d5565b610b5d565b6101386102c03660046124d5565b610bb8565b61014d6102d3366004612638565b600560209081526000928352604080842090915290825290205460ff1681565b6006546001600160a01b031633146103415760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064015b60405180910390fd5b600780546001600160a01b0319166001600160a01b0392909216919091179055565b60006301ffc9a760e01b6001600160e01b03198316148061039457506380ac58cd60e01b6001600160e01b03198316145b806103af5750635b5e139f60e01b6001600160e01b03198316145b92915050565b600080546103c290612666565b80601f01602080910402602001604051908101604052809291908181526020018280546103ee90612666565b801561043b5780601f106104105761010080835404028352916020019161043b565b820191906000526020600020905b81548152906001019060200180831161041e57829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b03163381148061048c57506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6104c95760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610338565b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6006546001600160a01b0316331461056e5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610338565b600680546001600160a01b0319166001600160a01b03831690811790915560405133907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a350565b6000818152600260205260409020546001600160a01b038481169116146106105760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b6044820152606401610338565b6001600160a01b03821661065a5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610338565b336001600160a01b038416148061069457506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b806106b557506000818152600460205260409020546001600160a01b031633145b6106f25760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610338565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6060600061078e83610d54565b905060006040518060600160405280608063ffffffff168152602001608063ffffffff1681526020016080806107c491906126b0565b6107cf9060016126dc565b63ffffffff1667ffffffffffffffff8111156107ed576107ed612704565b6040519080825280601f01601f191660200182016040528015610817576020820181803683370190505b5081525090506108366080808461082f858751610f66565b600161102c565b949350505050565b6108498383836105ba565b6001600160a01b0382163b15806108f25750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af11580156108c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e6919061271a565b6001600160e01b031916145b6109315760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610338565b505050565b6000818152600260205260409020546001600160a01b0316806109885760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606401610338565b919050565b60006001600160a01b0382166109d45760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401610338565b506001600160a01b031660009081526003602052604090205490565b600180546103c290612666565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610a728161106d565b50565b610a808585856105ba565b6001600160a01b0384163b1580610b175750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290610ac89033908a90899089908990600401612737565b6020604051808303816000875af1158015610ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0b919061271a565b6001600160e01b031916145b610b565760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610338565b5050505050565b60606103af6040518060400160405280600a81526020016967686f756c42616c6c7360b01b815250604051806101400160405280610102815260200161310e6101029139610baa85610781565b610bb38661113a565b61137e565b6127108110610bf95760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b2103130b6361760991b6044820152606401610338565b611a0a811015610cb8576007546040516331a9108f60e11b81526004810183905233916001600160a01b031690636352211e90602401602060405180830381865afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c70919061278b565b6001600160a01b031614610cb85760405162461bcd60e51b815260206004820152600f60248201526e3737ba103cb7bab91033b437bab61760891b6044820152606401610338565b6000818152600260205260409020546001600160a01b031615610d1d5760405162461bcd60e51b815260206004820181905260248201527f736f6d656f6e6520656c736520676f7420746869732067686f756c42616c6c2e6044820152606401610338565b610d268161145b565b60008281526008602090815260409091208251610d499391929190910190612354565b50610a72338261158d565b600081815260086020526040812080546060929190610d7290612666565b80601f0160208091040260200160405190810160405280929190818152602001828054610d9e90612666565b8015610deb5780601f10610dc057610100808354040283529160200191610deb565b820191906000526020600020905b815481529060010190602001808311610dce57829003601f168201915b50505050509050600060038251610e0291906127be565b67ffffffffffffffff811115610e1a57610e1a612704565b604051908082528060200260200182016040528015610e43578160200160208202803683370190505b50905060005b8151811015610f5e5782610e5e8260036127d2565b81518110610e6e57610e6e6127f1565b01602001516001600160f81b03191683610e898360036127d2565b610e94906001612807565b81518110610ea457610ea46127f1565b01602001516001600160f81b03191684610ebf8460036127d2565b610eca906002612807565b81518110610eda57610eda6127f1565b016020908101516040516001600160f81b031994851692810192909252918316602182015291166022820152602301604051602081830303815290604052610f219061281f565b828281518110610f3357610f336127f1565b6001600160e81b03199092166020928302919091019091015280610f5681612856565b915050610e49565b509392505050565b60408051606081810183526000808352602083015291810182905260008080805b868160ff16101561101d574281604051602001610fbb92919091825260f81b6001600160f81b031916602082015260210190565b6040516020818303038152906040528051906020012060001c9150610fe98289600001518a60200151611698565b9094509250611009888585601261100186600161286f565b60f81b6116ff565b94508061101581612894565b915050610f87565b50505050604001519392505050565b606061104361103e87878787876118cc565b611b1a565b60405160200161105391906128cf565b604051602081830303815290604052905095945050505050565b6000818152600260205260409020546001600160a01b0316806110bf5760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606401610338565b6001600160a01b038116600081815260036020908152604080832080546000190190558583526002825280832080546001600160a01b031990811690915560049092528083208054909216909155518492907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b60008181526008602052604081208054606092919061115890612666565b80601f016020809104026020016040519081016040528092919081815260200182805461118490612666565b80156111d15780601f106111a6576101008083540402835291602001916111d1565b820191906000526020600020905b8154815290600101906020018083116111b457829003601f168201915b505050505090506060600080600090505b600384516111f091906127be565b8110156113165760016003855161120791906127be565b611211919061290d565b811461121e576000611221565b60015b9150826112e161123a611235846001612807565b611c6d565b60405160200161124a9190612924565b60408051601f19818403018152919052611286876112698660036127d2565b81518110611279576112796127f1565b016020015160f81c611c6d565b6112a0886112958760036127d2565b611269906001612807565b6112ba896112af8860036127d2565b611269906002612807565b6040516020016112cc93929190612951565b60405160208183030381529060405285611d6e565b6040516020016112f29291906129ac565b6040516020818303038152906040529250808061130e90612856565b9150506111e2565b506113536040518060400160405280600a81526020016918985b1b0818dbdd5b9d60b21b81525061134e6003865161123591906127be565b611db9565b826040516020016113659291906129ac565b6040516020818303038152906040529350505050919050565b60606114326113a9604051806040016040528060048152602001636e616d6560e01b81525087611de5565b6113d66040518060400160405280600b81526020016a3232b9b1b934b83a34b7b760a91b81525087611de5565b6113df86611dfa565b61140b6040518060400160405280600a8152602001696174747269627574657360b01b81525087611e57565b60405160200161141e94939291906129d2565b604051602081830303815290604052611b1a565b6040516020016114429190612a48565b6040516020818303038152906040529050949350505050565b606060006114b66114b184334260405160200161149d9392919092835260609190911b6bffffffffffffffffffffffff19166020830152603482015260540190565b604051602081830303815290604052611e6c565b611e9e565b9050603c6114c5604583612a8d565b1115611504576040516dffffffffffffffffffffffffffff19607083901b1660208201526032015b604051602081830303815290604052915050919050565b6032611511604583612a8d565b1115611536576040516001600160a01b031960a083901b166020820152602c016114ed565b6028611543604583612a8d565b1115611568576040516001600160d01b031960d083901b1660208201526026016114ed565b6040516001600160e81b031960e883901b1660208201526023016114ed565b50919050565b6001600160a01b0382166115d75760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610338565b6000818152600260205260409020546001600160a01b03161561162d5760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606401610338565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60008060026116a781866127be565b6116b586601089901c612a8d565b6116bf9190612807565b6116c991906127be565b915060026116d781856127be565b6116e18588612a8d565b6116eb9190612807565b6116f591906127be565b9050935093915050565b61172360405180606001604052806000815260200160008152602001606081525090565b600080848703855b8882136118be57508587035b8781136118b3578680028983038002898303800201136118ab57888203890393508781038803925060008212158015611771575060008112155b156117b25760408a01518a51879190600190810184028501018151811061179a5761179a6127f1565b60200101906001600160f81b031916908160001a9053505b600082121580156117c4575060008312155b156118055760408a01518a5187919060019081018602850101815181106117ed576117ed6127f1565b60200101906001600160f81b031916908160001a9053505b60008412158015611817575060008112155b156118585760408a01518a518791906001908101840287010181518110611840576118406127f1565b60200101906001600160f81b031916908160001a9053505b6000841215801561186a575060008312155b156118ab5760408a01518a518791906001908101860287010181518110611893576118936127f1565b60200101906001600160f81b031916908160001a9053505b600101611737565b60019091019061172b565b509798975050505050505050565b606060006118d8611ef2565b905060006118e68685611f6b565b9050600061190c85611901576118fc88516120c2565b611905565b6101005b8851612100565b604051600d60e01b60208201526324a4222960e11b60248201526001600160e01b031960e08c811b821660288401528b901b16602c82015261080360f01b603082015290915060009060350160405160208183030381529060405261197090612aa1565b905060006178da60f01b61ffff89511161198e57600160f81b611991565b60005b61199b8a516121e6565b6119a58b516121e6565b6040516001600160f01b031994851660208201526001600160f81b031990931660228401529083166023830152199190911660258201526027016040516020818303038152906040526119f790612ad8565b905060008189611a068b6121f4565b604051602001611a1893929190612b0b565b60408051601f19818403018152908290526affffffffffffffffffffff198516602083015291506744a8272386850d0560c11b908490611a6e9089906035015b604051602081830303815290604052600461226c565b87611a848a8a604051602001611a589190612b5e565b88611a9a8c8b604051602001611a589190612b5e565b60048851611aa8919061290d565b88611ad48f8b604051602001611abe9190612b5e565b604051602081830303815290604052600061226c565b604051611afa9a999897969594939291906724a2a7225721304160a11b90602001612b7a565b604051602081830303815290604052965050505050505095945050505050565b60608151600003611b3957505060408051602081019091526000815290565b60006040518060600160405280604081526020016132106040913990506000600384516002611b689190612807565b611b7291906127be565b611b7d9060046127d2565b67ffffffffffffffff811115611b9557611b95612704565b6040519080825280601f01601f191660200182016040528015611bbf576020820181803683370190505b509050600182016020820185865187015b80821015611c2b576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f8116850151845350600183019250611bd0565b5050600386510660018114611c475760028114611c5a57611c62565b603d6001830353603d6002830353611c62565b603d60018303535b509195945050505050565b606081600003611c945750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611cbe5780611ca881612856565b9150611cb79050600a836127be565b9150611c98565b60008167ffffffffffffffff811115611cd957611cd9612704565b6040519080825280601f01601f191660200182016040528015611d03576020820181803683370190505b5090505b841561083657611d1860018361290d565b9150611d25600a86612a8d565b611d30906030612807565b60f81b818381518110611d4557611d456127f1565b60200101906001600160f81b031916908160001a905350611d67600a866127be565b9450611d07565b60608115611d9f578383604051602001611d89929190612c4f565b6040516020818303038152906040529050611db2565b8383604051602001611d89929190612ccd565b9392505050565b60608282604051602001611dce929190612ccd565b604051602081830303815290604052905092915050565b60608282604051602001611dce929190612d4d565b60606103af60405180604001604052806005815260200164696d61676560d81b815250611e318460405160200161141e9190612db2565b604051602001611e419190612ee6565b60405160208183030381529060405260006122e9565b60608282604051602001611dce929190612f2b565b60608180519060200120604051602001611e8891815260200190565b6040516020818303038152906040529050919050565b6000602082511015611eea5760405162461bcd60e51b8152602060048201526015602482015274746f55696e743235365f6f75744f66426f756e647360581b6044820152606401610338565b506020015190565b611efa6123d8565b6000805b610100811015611f665780915060005b6008811015611f445782600116600103611f3457600183901c63edb88320189250611f3c565b600183901c92505b600101611f0e565b508183826101008110611f5957611f596127f1565b6020020152600101611efe565b505090565b606061010083511115611fc05760405162461bcd60e51b815260206004820152601760248201527f504e473a2050616c6574746520746f6f206c617267652e0000000000000000006044820152606401610338565b600082611fd657611fd184516120c2565b611fda565b6101005b9050606060005b855181101561203a5781868281518110611ffd57611ffd6127f1565b6020026020010151604051602001612016929190612f8f565b6040516020818303038152906040529150808061203290612856565b915050611fe1565b5084515b61204960018461290d565b81101561208857604051612064908390600090602001612f8f565b6040516020818303038152906040529150808061208090612856565b91505061203e565b506120948260036127d2565b6040516120a991906000908490602001612fbe565b6040516020818303038152906040529250505092915050565b600060038210156120d557506002919050565b60058210156120e657506004919050565b60118210156120f757506010919050565b50610100919050565b604051600060208201819052606091602101604051602081830303815290604052905060005b8381101561216d576040516121499083906001600160f81b031990602001613011565b6040516020818303038152906040529150808061216590612856565b915050612126565b50825b61217b60018661290d565b8110156121ba57604051612196908390600090602001613011565b604051602081830303815290604052915080806121b290612856565b915050612170565b5083816040516020016121ce929190613040565b60405160208183030381529060405291505092915050565b60006103af8260f01b612317565b80516000906001908290815b818110156122555761fff186828151811061221d5761221d6127f1565b60209101015160f81c850163ffffffff168161223b5761223b6127a8565b06935061fff163ffffffff84860116069250600101612200565b505060101b65ffffffff0000161760e01b92915050565b815160009063ffffffff835b828110156122d25760088263ffffffff16901c63ffffffff16878783815181106122a4576122a46127f1565b016020015160f81c841860ff1661010081106122c2576122c26127f1565b6020020151189150600101612278565b5060e01b6001600160e01b03191895945050505050565b60608115612304578383604051602001611d8992919061307f565b8383604051602001611d89929190612d4d565b6040516001600160f81b0319600883901b81166020830152821660218201526000906022016040516020818303038152906040526103af906130da565b82805461236090612666565b90600052602060002090601f01602090048101928261238257600085556123c8565b82601f1061239b57805160ff19168380011785556123c8565b828001600101855582156123c8579182015b828111156123c85782518255916020019190600101906123ad565b506123d49291506123f8565b5090565b604051806120000160405280610100906020820280368337509192915050565b5b808211156123d457600081556001016123f9565b6001600160a01b0381168114610a7257600080fd5b60006020828403121561243457600080fd5b8135611db28161240d565b6001600160e01b031981168114610a7257600080fd5b60006020828403121561246757600080fd5b8135611db28161243f565b60005b8381101561248d578181015183820152602001612475565b8381111561249c576000848401525b50505050565b60208152600082518060208401526124c1816040850160208701612472565b601f01601f19169190910160400192915050565b6000602082840312156124e757600080fd5b5035919050565b6000806040838503121561250157600080fd5b823561250c8161240d565b946020939093013593505050565b60008060006060848603121561252f57600080fd5b833561253a8161240d565b9250602084013561254a8161240d565b929592945050506040919091013590565b6000806040838503121561256e57600080fd5b82356125798161240d565b91506020830135801515811461258e57600080fd5b809150509250929050565b6000806000806000608086880312156125b157600080fd5b85356125bc8161240d565b945060208601356125cc8161240d565b935060408601359250606086013567ffffffffffffffff808211156125f057600080fd5b818801915088601f83011261260457600080fd5b81358181111561261357600080fd5b89602082850101111561262557600080fd5b9699959850939650602001949392505050565b6000806040838503121561264b57600080fd5b82356126568161240d565b9150602083013561258e8161240d565b600181811c9082168061267a57607f821691505b60208210810361158757634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff808316818516818304811182151516156126d3576126d361269a565b02949350505050565b600063ffffffff8083168185168083038211156126fb576126fb61269a565b01949350505050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561272c57600080fd5b8151611db28161243f565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b60006020828403121561279d57600080fd5b8151611db28161240d565b634e487b7160e01b600052601260045260246000fd5b6000826127cd576127cd6127a8565b500490565b60008160001904831182151516156127ec576127ec61269a565b500290565b634e487b7160e01b600052603260045260246000fd5b6000821982111561281a5761281a61269a565b500190565b805160208201516001600160e81b0319808216929190600383101561284e5780818460030360031b1b83161693505b505050919050565b6000600182016128685761286861269a565b5060010190565b600060ff821660ff84168060ff0382111561288c5761288c61269a565b019392505050565b600060ff821660ff81036128aa576128aa61269a565b60010192915050565b600081516128c5818560208601612472565b9290920192915050565b7519185d184e9a5b5859d94bdc1b99ced8985cd94d8d0b60521b815260008251612900816016850160208701612472565b9190910160160192915050565b60008282101561291f5761291f61269a565b500390565b6403130b636160dd1b815260008251612944816005850160208701612472565b9190910160050192915050565b60008451612963818460208901612472565b808301905061016160f51b8082528551612984816002850160208a01612472565b6002920191820152835161299f816004840160208801612472565b0160040195945050505050565b600083516129be818460208801612472565b8351908301906126fb818360208801612472565b607b60f81b8152600085516129ee816001850160208a01612472565b855190830190612a05816001840160208a01612472565b8551910190612a1b816001840160208901612472565b8451910160010190612a31818360208801612472565b607d60f81b91019081526001019695505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000815260008251612a8081601d850160208701612472565b91909101601d0192915050565b600082612a9c57612a9c6127a8565b500690565b805160208201516affffffffffffffffffffff19808216929190601583101561284e5760159290920360031b82901b161692915050565b805160208201516001600160c81b0319808216929190600783101561284e5760079290920360031b82901b161692915050565b631251105560e21b81526001600160c81b0319841660048201528251600090612b3b81600b850160208801612472565b6001600160e01b03199390931691909201600b810191909152600f019392505050565b60008251612b70818460208701612472565b9190910192915050565b6001600160c01b03198c1681526affffffffffffffffffffff198b1660088201526001600160e01b03198a8116601d830152895160009190612bc3816021860160208f01612472565b8a82166021918501918201528951612be2816025840160208e01612472565b89831660259290910191820152612c08602982018960e01b6001600160e01b0319169052565b612c15602d8201886128b3565b915050612c2b81866001600160e01b0319169052565b6001600160a01b0319841660048201526010019d9c50505050505050505050505050565b6f3d913a3930b4ba2fba3cb832911d101160811b81528251600090612c7b816010850160208801612472565b6201116160ed1b6010918401918201526a113b30b63ab291101d101160a91b60138201528351612cb281601e840160208801612472565b61227d60f01b601e9290910191820152602001949350505050565b6f3d913a3930b4ba2fba3cb832911d101160811b81528251600090612cf9816010850160208801612472565b6201116160ed1b6010918401918201526a113b30b63ab291101d101160a91b60138201528351612d3081601e840160208801612472565b630113e96160e51b601e9290910191820152602201949350505050565b6000601160f91b8083528451612d6a816001860160208901612472565b620111d160ed1b6001918501918201526004810191909152835190612d96826005830160208801612472565b6201116160ed1b91016005810191909152600801949350505050565b7f3c7376672077696474683d223130302522206865696768743d2231303025222081527f76657273696f6e3d22312e312220786d6c6e733d22687474703a2f2f7777772e60208201527f77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687460408201527f74703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e20203c6960608201527f6d61676520783d22302220793d2230222077696474683d22313238222068656960808201527f6768743d2231323822207072657365727665417370656374526174696f3d227860a08201527426b4b22ca6b4b211103c3634b7359d343932b31e9160591b60c082015260008251612ec68160d5850160208701612472565b6811179f1e17b9bb339f60b91b60d593909101928301525060de01919050565b7f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000815260008251612f1e81601a850160208701612472565b91909101601a0192915050565b601160f91b81528251600090612f48816001850160208801612472565b620111d160ed1b600191840191820152605b60f81b60048201528351612f75816005840160208801612472565b605d60f81b60059290910191820152600601949350505050565b60008351612fa1818460208801612472565b6001600160e81b0319939093169190920190815260030192915050565b60e084901b6001600160e01b031916815263504c544560e01b60048201526001600160e81b031983166008820152815160009061300281600b850160208701612472565b91909101600b01949350505050565b60008351613023818460208801612472565b6001600160f81b0319939093169190920190815260010192915050565b63ffffffff60e01b8360e01b1681526374524e5360e01b600482015260008251613071816008850160208701612472565b919091016008019392505050565b6000601160f91b808352845161309c816001860160208901612472565b620111d160ed1b6001918501918201526004810182905284516130c6816005840160208901612472565b016005810191909152600601949350505050565b805160208201516001600160f01b0319808216929190600283101561284e5760029290920360031b82901b16169291505056fe67686f756c42616c6c73206172652066756c6c79206f6e636861696e20504e477320746861742065766f6c7665207769746820657665727920626c6f636b2c206162736f6c7574656c792072756767696e67207468652072696768742d636c69636b20736176657273206166746572206576657279626c6f636b2e204e6f20726f61646d61702c206e6f20646576656c6f706d656e742c206e6f207574696c6974792c206e6f206d61726b6574696e672c20616e64206e6f7468696e67206d6f72652e20546865792070726f6d697365206e6f7468696e6720616e642064656c69766572206576656e206c6573732e2054686579277265206a75737420504e47732e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122029efa5ef6f32d59491e214790b5c34e578eb26a758ca0d692398a0399c6cf39e64736f6c634300080d0033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101205760003560e01c80636352211e116100ad578063a8ce53a011610071578063a8ce53a014610279578063b88d4fde1461028c578063c87b56dd1461029f578063d79d93d4146102b2578063e985e9c5146102c557600080fd5b80636352211e1461021757806370a082311461022a5780638da5cb5b1461024b57806395d89b411461025e578063a22cb4651461026657600080fd5b8063095ea7b3116100f4578063095ea7b3146101b857806313af4035146101cb57806323b872dd146101de57806335842845146101f157806342842e0e1461020457600080fd5b806223a12e1461012557806301ffc9a71461013a57806306fdde0314610162578063081812fc14610177575b600080fd5b610138610133366004612422565b6102f3565b005b61014d610148366004612455565b610363565b60405190151581526020015b60405180910390f35b61016a6103b5565b60405161015991906124a2565b6101a06101853660046124d5565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610159565b6101386101c63660046124ee565b610443565b6101386101d9366004612422565b610525565b6101386101ec36600461251a565b6105ba565b61016a6101ff3660046124d5565b610781565b61013861021236600461251a565b61083e565b6101a06102253660046124d5565b610936565b61023d610238366004612422565b61098d565b604051908152602001610159565b6006546101a0906001600160a01b031681565b61016a6109f0565b61013861027436600461255b565b6109fd565b6101386102873660046124d5565b610a69565b61013861029a366004612599565b610a75565b61016a6102ad3660046124d5565b610b5d565b6101386102c03660046124d5565b610bb8565b61014d6102d3366004612638565b600560209081526000928352604080842090915290825290205460ff1681565b6006546001600160a01b031633146103415760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064015b60405180910390fd5b600780546001600160a01b0319166001600160a01b0392909216919091179055565b60006301ffc9a760e01b6001600160e01b03198316148061039457506380ac58cd60e01b6001600160e01b03198316145b806103af5750635b5e139f60e01b6001600160e01b03198316145b92915050565b600080546103c290612666565b80601f01602080910402602001604051908101604052809291908181526020018280546103ee90612666565b801561043b5780601f106104105761010080835404028352916020019161043b565b820191906000526020600020905b81548152906001019060200180831161041e57829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b03163381148061048c57506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6104c95760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610338565b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6006546001600160a01b0316331461056e5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610338565b600680546001600160a01b0319166001600160a01b03831690811790915560405133907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a350565b6000818152600260205260409020546001600160a01b038481169116146106105760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b6044820152606401610338565b6001600160a01b03821661065a5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610338565b336001600160a01b038416148061069457506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b806106b557506000818152600460205260409020546001600160a01b031633145b6106f25760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610338565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6060600061078e83610d54565b905060006040518060600160405280608063ffffffff168152602001608063ffffffff1681526020016080806107c491906126b0565b6107cf9060016126dc565b63ffffffff1667ffffffffffffffff8111156107ed576107ed612704565b6040519080825280601f01601f191660200182016040528015610817576020820181803683370190505b5081525090506108366080808461082f858751610f66565b600161102c565b949350505050565b6108498383836105ba565b6001600160a01b0382163b15806108f25750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af11580156108c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e6919061271a565b6001600160e01b031916145b6109315760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610338565b505050565b6000818152600260205260409020546001600160a01b0316806109885760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606401610338565b919050565b60006001600160a01b0382166109d45760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401610338565b506001600160a01b031660009081526003602052604090205490565b600180546103c290612666565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610a728161106d565b50565b610a808585856105ba565b6001600160a01b0384163b1580610b175750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290610ac89033908a90899089908990600401612737565b6020604051808303816000875af1158015610ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0b919061271a565b6001600160e01b031916145b610b565760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610338565b5050505050565b60606103af6040518060400160405280600a81526020016967686f756c42616c6c7360b01b815250604051806101400160405280610102815260200161310e6101029139610baa85610781565b610bb38661113a565b61137e565b6127108110610bf95760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b2103130b6361760991b6044820152606401610338565b611a0a811015610cb8576007546040516331a9108f60e11b81526004810183905233916001600160a01b031690636352211e90602401602060405180830381865afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c70919061278b565b6001600160a01b031614610cb85760405162461bcd60e51b815260206004820152600f60248201526e3737ba103cb7bab91033b437bab61760891b6044820152606401610338565b6000818152600260205260409020546001600160a01b031615610d1d5760405162461bcd60e51b815260206004820181905260248201527f736f6d656f6e6520656c736520676f7420746869732067686f756c42616c6c2e6044820152606401610338565b610d268161145b565b60008281526008602090815260409091208251610d499391929190910190612354565b50610a72338261158d565b600081815260086020526040812080546060929190610d7290612666565b80601f0160208091040260200160405190810160405280929190818152602001828054610d9e90612666565b8015610deb5780601f10610dc057610100808354040283529160200191610deb565b820191906000526020600020905b815481529060010190602001808311610dce57829003601f168201915b50505050509050600060038251610e0291906127be565b67ffffffffffffffff811115610e1a57610e1a612704565b604051908082528060200260200182016040528015610e43578160200160208202803683370190505b50905060005b8151811015610f5e5782610e5e8260036127d2565b81518110610e6e57610e6e6127f1565b01602001516001600160f81b03191683610e898360036127d2565b610e94906001612807565b81518110610ea457610ea46127f1565b01602001516001600160f81b03191684610ebf8460036127d2565b610eca906002612807565b81518110610eda57610eda6127f1565b016020908101516040516001600160f81b031994851692810192909252918316602182015291166022820152602301604051602081830303815290604052610f219061281f565b828281518110610f3357610f336127f1565b6001600160e81b03199092166020928302919091019091015280610f5681612856565b915050610e49565b509392505050565b60408051606081810183526000808352602083015291810182905260008080805b868160ff16101561101d574281604051602001610fbb92919091825260f81b6001600160f81b031916602082015260210190565b6040516020818303038152906040528051906020012060001c9150610fe98289600001518a60200151611698565b9094509250611009888585601261100186600161286f565b60f81b6116ff565b94508061101581612894565b915050610f87565b50505050604001519392505050565b606061104361103e87878787876118cc565b611b1a565b60405160200161105391906128cf565b604051602081830303815290604052905095945050505050565b6000818152600260205260409020546001600160a01b0316806110bf5760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606401610338565b6001600160a01b038116600081815260036020908152604080832080546000190190558583526002825280832080546001600160a01b031990811690915560049092528083208054909216909155518492907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b60008181526008602052604081208054606092919061115890612666565b80601f016020809104026020016040519081016040528092919081815260200182805461118490612666565b80156111d15780601f106111a6576101008083540402835291602001916111d1565b820191906000526020600020905b8154815290600101906020018083116111b457829003601f168201915b505050505090506060600080600090505b600384516111f091906127be565b8110156113165760016003855161120791906127be565b611211919061290d565b811461121e576000611221565b60015b9150826112e161123a611235846001612807565b611c6d565b60405160200161124a9190612924565b60408051601f19818403018152919052611286876112698660036127d2565b81518110611279576112796127f1565b016020015160f81c611c6d565b6112a0886112958760036127d2565b611269906001612807565b6112ba896112af8860036127d2565b611269906002612807565b6040516020016112cc93929190612951565b60405160208183030381529060405285611d6e565b6040516020016112f29291906129ac565b6040516020818303038152906040529250808061130e90612856565b9150506111e2565b506113536040518060400160405280600a81526020016918985b1b0818dbdd5b9d60b21b81525061134e6003865161123591906127be565b611db9565b826040516020016113659291906129ac565b6040516020818303038152906040529350505050919050565b60606114326113a9604051806040016040528060048152602001636e616d6560e01b81525087611de5565b6113d66040518060400160405280600b81526020016a3232b9b1b934b83a34b7b760a91b81525087611de5565b6113df86611dfa565b61140b6040518060400160405280600a8152602001696174747269627574657360b01b81525087611e57565b60405160200161141e94939291906129d2565b604051602081830303815290604052611b1a565b6040516020016114429190612a48565b6040516020818303038152906040529050949350505050565b606060006114b66114b184334260405160200161149d9392919092835260609190911b6bffffffffffffffffffffffff19166020830152603482015260540190565b604051602081830303815290604052611e6c565b611e9e565b9050603c6114c5604583612a8d565b1115611504576040516dffffffffffffffffffffffffffff19607083901b1660208201526032015b604051602081830303815290604052915050919050565b6032611511604583612a8d565b1115611536576040516001600160a01b031960a083901b166020820152602c016114ed565b6028611543604583612a8d565b1115611568576040516001600160d01b031960d083901b1660208201526026016114ed565b6040516001600160e81b031960e883901b1660208201526023016114ed565b50919050565b6001600160a01b0382166115d75760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610338565b6000818152600260205260409020546001600160a01b03161561162d5760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606401610338565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60008060026116a781866127be565b6116b586601089901c612a8d565b6116bf9190612807565b6116c991906127be565b915060026116d781856127be565b6116e18588612a8d565b6116eb9190612807565b6116f591906127be565b9050935093915050565b61172360405180606001604052806000815260200160008152602001606081525090565b600080848703855b8882136118be57508587035b8781136118b3578680028983038002898303800201136118ab57888203890393508781038803925060008212158015611771575060008112155b156117b25760408a01518a51879190600190810184028501018151811061179a5761179a6127f1565b60200101906001600160f81b031916908160001a9053505b600082121580156117c4575060008312155b156118055760408a01518a5187919060019081018602850101815181106117ed576117ed6127f1565b60200101906001600160f81b031916908160001a9053505b60008412158015611817575060008112155b156118585760408a01518a518791906001908101840287010181518110611840576118406127f1565b60200101906001600160f81b031916908160001a9053505b6000841215801561186a575060008312155b156118ab5760408a01518a518791906001908101860287010181518110611893576118936127f1565b60200101906001600160f81b031916908160001a9053505b600101611737565b60019091019061172b565b509798975050505050505050565b606060006118d8611ef2565b905060006118e68685611f6b565b9050600061190c85611901576118fc88516120c2565b611905565b6101005b8851612100565b604051600d60e01b60208201526324a4222960e11b60248201526001600160e01b031960e08c811b821660288401528b901b16602c82015261080360f01b603082015290915060009060350160405160208183030381529060405261197090612aa1565b905060006178da60f01b61ffff89511161198e57600160f81b611991565b60005b61199b8a516121e6565b6119a58b516121e6565b6040516001600160f01b031994851660208201526001600160f81b031990931660228401529083166023830152199190911660258201526027016040516020818303038152906040526119f790612ad8565b905060008189611a068b6121f4565b604051602001611a1893929190612b0b565b60408051601f19818403018152908290526affffffffffffffffffffff198516602083015291506744a8272386850d0560c11b908490611a6e9089906035015b604051602081830303815290604052600461226c565b87611a848a8a604051602001611a589190612b5e565b88611a9a8c8b604051602001611a589190612b5e565b60048851611aa8919061290d565b88611ad48f8b604051602001611abe9190612b5e565b604051602081830303815290604052600061226c565b604051611afa9a999897969594939291906724a2a7225721304160a11b90602001612b7a565b604051602081830303815290604052965050505050505095945050505050565b60608151600003611b3957505060408051602081019091526000815290565b60006040518060600160405280604081526020016132106040913990506000600384516002611b689190612807565b611b7291906127be565b611b7d9060046127d2565b67ffffffffffffffff811115611b9557611b95612704565b6040519080825280601f01601f191660200182016040528015611bbf576020820181803683370190505b509050600182016020820185865187015b80821015611c2b576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f8116850151845350600183019250611bd0565b5050600386510660018114611c475760028114611c5a57611c62565b603d6001830353603d6002830353611c62565b603d60018303535b509195945050505050565b606081600003611c945750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611cbe5780611ca881612856565b9150611cb79050600a836127be565b9150611c98565b60008167ffffffffffffffff811115611cd957611cd9612704565b6040519080825280601f01601f191660200182016040528015611d03576020820181803683370190505b5090505b841561083657611d1860018361290d565b9150611d25600a86612a8d565b611d30906030612807565b60f81b818381518110611d4557611d456127f1565b60200101906001600160f81b031916908160001a905350611d67600a866127be565b9450611d07565b60608115611d9f578383604051602001611d89929190612c4f565b6040516020818303038152906040529050611db2565b8383604051602001611d89929190612ccd565b9392505050565b60608282604051602001611dce929190612ccd565b604051602081830303815290604052905092915050565b60608282604051602001611dce929190612d4d565b60606103af60405180604001604052806005815260200164696d61676560d81b815250611e318460405160200161141e9190612db2565b604051602001611e419190612ee6565b60405160208183030381529060405260006122e9565b60608282604051602001611dce929190612f2b565b60608180519060200120604051602001611e8891815260200190565b6040516020818303038152906040529050919050565b6000602082511015611eea5760405162461bcd60e51b8152602060048201526015602482015274746f55696e743235365f6f75744f66426f756e647360581b6044820152606401610338565b506020015190565b611efa6123d8565b6000805b610100811015611f665780915060005b6008811015611f445782600116600103611f3457600183901c63edb88320189250611f3c565b600183901c92505b600101611f0e565b508183826101008110611f5957611f596127f1565b6020020152600101611efe565b505090565b606061010083511115611fc05760405162461bcd60e51b815260206004820152601760248201527f504e473a2050616c6574746520746f6f206c617267652e0000000000000000006044820152606401610338565b600082611fd657611fd184516120c2565b611fda565b6101005b9050606060005b855181101561203a5781868281518110611ffd57611ffd6127f1565b6020026020010151604051602001612016929190612f8f565b6040516020818303038152906040529150808061203290612856565b915050611fe1565b5084515b61204960018461290d565b81101561208857604051612064908390600090602001612f8f565b6040516020818303038152906040529150808061208090612856565b91505061203e565b506120948260036127d2565b6040516120a991906000908490602001612fbe565b6040516020818303038152906040529250505092915050565b600060038210156120d557506002919050565b60058210156120e657506004919050565b60118210156120f757506010919050565b50610100919050565b604051600060208201819052606091602101604051602081830303815290604052905060005b8381101561216d576040516121499083906001600160f81b031990602001613011565b6040516020818303038152906040529150808061216590612856565b915050612126565b50825b61217b60018661290d565b8110156121ba57604051612196908390600090602001613011565b604051602081830303815290604052915080806121b290612856565b915050612170565b5083816040516020016121ce929190613040565b60405160208183030381529060405291505092915050565b60006103af8260f01b612317565b80516000906001908290815b818110156122555761fff186828151811061221d5761221d6127f1565b60209101015160f81c850163ffffffff168161223b5761223b6127a8565b06935061fff163ffffffff84860116069250600101612200565b505060101b65ffffffff0000161760e01b92915050565b815160009063ffffffff835b828110156122d25760088263ffffffff16901c63ffffffff16878783815181106122a4576122a46127f1565b016020015160f81c841860ff1661010081106122c2576122c26127f1565b6020020151189150600101612278565b5060e01b6001600160e01b03191895945050505050565b60608115612304578383604051602001611d8992919061307f565b8383604051602001611d89929190612d4d565b6040516001600160f81b0319600883901b81166020830152821660218201526000906022016040516020818303038152906040526103af906130da565b82805461236090612666565b90600052602060002090601f01602090048101928261238257600085556123c8565b82601f1061239b57805160ff19168380011785556123c8565b828001600101855582156123c8579182015b828111156123c85782518255916020019190600101906123ad565b506123d49291506123f8565b5090565b604051806120000160405280610100906020820280368337509192915050565b5b808211156123d457600081556001016123f9565b6001600160a01b0381168114610a7257600080fd5b60006020828403121561243457600080fd5b8135611db28161240d565b6001600160e01b031981168114610a7257600080fd5b60006020828403121561246757600080fd5b8135611db28161243f565b60005b8381101561248d578181015183820152602001612475565b8381111561249c576000848401525b50505050565b60208152600082518060208401526124c1816040850160208701612472565b601f01601f19169190910160400192915050565b6000602082840312156124e757600080fd5b5035919050565b6000806040838503121561250157600080fd5b823561250c8161240d565b946020939093013593505050565b60008060006060848603121561252f57600080fd5b833561253a8161240d565b9250602084013561254a8161240d565b929592945050506040919091013590565b6000806040838503121561256e57600080fd5b82356125798161240d565b91506020830135801515811461258e57600080fd5b809150509250929050565b6000806000806000608086880312156125b157600080fd5b85356125bc8161240d565b945060208601356125cc8161240d565b935060408601359250606086013567ffffffffffffffff808211156125f057600080fd5b818801915088601f83011261260457600080fd5b81358181111561261357600080fd5b89602082850101111561262557600080fd5b9699959850939650602001949392505050565b6000806040838503121561264b57600080fd5b82356126568161240d565b9150602083013561258e8161240d565b600181811c9082168061267a57607f821691505b60208210810361158757634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff808316818516818304811182151516156126d3576126d361269a565b02949350505050565b600063ffffffff8083168185168083038211156126fb576126fb61269a565b01949350505050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561272c57600080fd5b8151611db28161243f565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b60006020828403121561279d57600080fd5b8151611db28161240d565b634e487b7160e01b600052601260045260246000fd5b6000826127cd576127cd6127a8565b500490565b60008160001904831182151516156127ec576127ec61269a565b500290565b634e487b7160e01b600052603260045260246000fd5b6000821982111561281a5761281a61269a565b500190565b805160208201516001600160e81b0319808216929190600383101561284e5780818460030360031b1b83161693505b505050919050565b6000600182016128685761286861269a565b5060010190565b600060ff821660ff84168060ff0382111561288c5761288c61269a565b019392505050565b600060ff821660ff81036128aa576128aa61269a565b60010192915050565b600081516128c5818560208601612472565b9290920192915050565b7519185d184e9a5b5859d94bdc1b99ced8985cd94d8d0b60521b815260008251612900816016850160208701612472565b9190910160160192915050565b60008282101561291f5761291f61269a565b500390565b6403130b636160dd1b815260008251612944816005850160208701612472565b9190910160050192915050565b60008451612963818460208901612472565b808301905061016160f51b8082528551612984816002850160208a01612472565b6002920191820152835161299f816004840160208801612472565b0160040195945050505050565b600083516129be818460208801612472565b8351908301906126fb818360208801612472565b607b60f81b8152600085516129ee816001850160208a01612472565b855190830190612a05816001840160208a01612472565b8551910190612a1b816001840160208901612472565b8451910160010190612a31818360208801612472565b607d60f81b91019081526001019695505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000815260008251612a8081601d850160208701612472565b91909101601d0192915050565b600082612a9c57612a9c6127a8565b500690565b805160208201516affffffffffffffffffffff19808216929190601583101561284e5760159290920360031b82901b161692915050565b805160208201516001600160c81b0319808216929190600783101561284e5760079290920360031b82901b161692915050565b631251105560e21b81526001600160c81b0319841660048201528251600090612b3b81600b850160208801612472565b6001600160e01b03199390931691909201600b810191909152600f019392505050565b60008251612b70818460208701612472565b9190910192915050565b6001600160c01b03198c1681526affffffffffffffffffffff198b1660088201526001600160e01b03198a8116601d830152895160009190612bc3816021860160208f01612472565b8a82166021918501918201528951612be2816025840160208e01612472565b89831660259290910191820152612c08602982018960e01b6001600160e01b0319169052565b612c15602d8201886128b3565b915050612c2b81866001600160e01b0319169052565b6001600160a01b0319841660048201526010019d9c50505050505050505050505050565b6f3d913a3930b4ba2fba3cb832911d101160811b81528251600090612c7b816010850160208801612472565b6201116160ed1b6010918401918201526a113b30b63ab291101d101160a91b60138201528351612cb281601e840160208801612472565b61227d60f01b601e9290910191820152602001949350505050565b6f3d913a3930b4ba2fba3cb832911d101160811b81528251600090612cf9816010850160208801612472565b6201116160ed1b6010918401918201526a113b30b63ab291101d101160a91b60138201528351612d3081601e840160208801612472565b630113e96160e51b601e9290910191820152602201949350505050565b6000601160f91b8083528451612d6a816001860160208901612472565b620111d160ed1b6001918501918201526004810191909152835190612d96826005830160208801612472565b6201116160ed1b91016005810191909152600801949350505050565b7f3c7376672077696474683d223130302522206865696768743d2231303025222081527f76657273696f6e3d22312e312220786d6c6e733d22687474703a2f2f7777772e60208201527f77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687460408201527f74703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e20203c6960608201527f6d61676520783d22302220793d2230222077696474683d22313238222068656960808201527f6768743d2231323822207072657365727665417370656374526174696f3d227860a08201527426b4b22ca6b4b211103c3634b7359d343932b31e9160591b60c082015260008251612ec68160d5850160208701612472565b6811179f1e17b9bb339f60b91b60d593909101928301525060de01919050565b7f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000815260008251612f1e81601a850160208701612472565b91909101601a0192915050565b601160f91b81528251600090612f48816001850160208801612472565b620111d160ed1b600191840191820152605b60f81b60048201528351612f75816005840160208801612472565b605d60f81b60059290910191820152600601949350505050565b60008351612fa1818460208801612472565b6001600160e81b0319939093169190920190815260030192915050565b60e084901b6001600160e01b031916815263504c544560e01b60048201526001600160e81b031983166008820152815160009061300281600b850160208701612472565b91909101600b01949350505050565b60008351613023818460208801612472565b6001600160f81b0319939093169190920190815260010192915050565b63ffffffff60e01b8360e01b1681526374524e5360e01b600482015260008251613071816008850160208701612472565b919091016008019392505050565b6000601160f91b808352845161309c816001860160208901612472565b620111d160ed1b6001918501918201526004810182905284516130c6816005840160208901612472565b016005810191909152600601949350505050565b805160208201516001600160f01b0319808216929190600283101561284e5760029290920360031b82901b16169291505056fe67686f756c42616c6c73206172652066756c6c79206f6e636861696e20504e477320746861742065766f6c7665207769746820657665727920626c6f636b2c206162736f6c7574656c792072756767696e67207468652072696768742d636c69636b20736176657273206166746572206576657279626c6f636b2e204e6f20726f61646d61702c206e6f20646576656c6f706d656e742c206e6f207574696c6974792c206e6f206d61726b6574696e672c20616e64206e6f7468696e67206d6f72652e20546865792070726f6d697365206e6f7468696e6720616e642064656c69766572206576656e206c6573732e2054686579277265206a75737420504e47732e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122029efa5ef6f32d59491e214790b5c34e578eb26a758ca0d692398a0399c6cf39e64736f6c634300080d0033

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.