ETH Price: $3,858.22 (-3.21%)

Token

: XVG (XVG)

Overview

Max Total Supply

0 XVG

Holders

8

Total Transfers

-

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
XVG

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 8 : XVG.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import {ERC721} from "solmate/tokens/ERC721.sol";
import {Owned} from "solmate/auth/Owned.sol";
import {XVGStorage} from "./XVGStorage.sol";
import {XVGMetadata} from "./XVGMetadata.sol";
import {Base64} from "@openzeppelin/contracts/utils/Base64.sol";

contract XVG is ERC721, Owned, XVGMetadata, XVGStorage {
    /* -------------------------------------------------------------------------- */
    /*                                    STATE                                   */
    /* -------------------------------------------------------------------------- */
    bool public MINT_OPEN;
    string private description = "On-chain vector graphics by Area Technology.";

    /* -------------------------------------------------------------------------- */
    /*                              EVENTS AND ERRORS                             */
    /* -------------------------------------------------------------------------- */
    event MetadataUpdate(uint256 _tokenId);
    error InvalidMessageValue();
    error MintNotOpen();
    error MaxSupplyReached();
    error AlreadyMinted();

    /* -------------------------------------------------------------------------- */
    /*                               INITIALIZATION                               */
    /* -------------------------------------------------------------------------- */
    constructor() Owned(msg.sender) ERC721("XVG", "XVG") {
        for (uint256 id = 1; id <= 23; id++) {
            _mint(address(this), id);
        }
    }

    /* -------------------------------------------------------------------------- */
    /*                                    MINT                                    */
    /* -------------------------------------------------------------------------- */
    function mint(uint256 tokenId) public payable {
        if (!MINT_OPEN) revert MintNotOpen();
        if (xvgMeta[tokenId].price == 0) revert MintNotOpen();
        if (msg.value != xvgMeta[tokenId].price) revert InvalidMessageValue();
        if (ownerOf(tokenId) != address(this)) revert AlreadyMinted();

        getApproved[tokenId] = msg.sender;
        transferFrom(address(this), msg.sender, tokenId);
    }

    /* -------------------------------------------------------------------------- */
    /*                                    DATA                                    */
    /* -------------------------------------------------------------------------- */
    function tokenURI(
        uint256 tokenId
    ) public view override returns (string memory) {
        bytes memory dataURI = abi.encodePacked(
            "{",
            '"name": "',
            xvgMeta[tokenId].name,
            '", "description": "',
            description,
            '", "image": "data:image/svg+xml;base64,',
            Base64.encode(bytes(readXVG(tokenId))),
            '"}'
        );
        return
            string(
                abi.encodePacked(
                    "data:application/json;base64,",
                    Base64.encode(dataURI)
                )
            );
    }

    /* -------------------------------------------------------------------------- */
    /*                                    OWNER                                   */
    /* -------------------------------------------------------------------------- */
    function writeXVG(
        uint256 id,
        bytes calldata data,
        uint32 size
    ) external onlyOwner {
        _writeXVG(id, data, size);
    }

    function writeXVGMeta(uint256 id, string memory name) external onlyOwner {
        _writeXVGMeta(id, name);
        emit MetadataUpdate(id);
    }

    function writeXVGPrice(uint256 id, uint256 price) external onlyOwner {
        _writeXVGPrice(id, price);
    }

    function setMintOpen(bool open) external onlyOwner {
        MINT_OPEN = open;
    }

    function setDescription(string memory _description) external onlyOwner {
        description = _description;
    }

    function withdraw(address to) external onlyOwner {
        (bool success, ) = to.call{value: address(this).balance}("");
        require(success, "XVG: withdraw failed");
    }
}

File 2 of 8 : 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/transmissions11/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/transmissions11/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 8 : 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/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event OwnershipTransferred(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 OwnershipTransferred(address(0), _owner);
    }

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

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

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

File 4 of 8 : XVGStorage.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import {SSTORE2} from "solady/utils/SSTORE2.sol";
import {InflateLib} from "inflate-sol/InflateLib.sol";

contract XVGStorage {
    struct XVGAsset {
        uint32 size;
        address[] slots;
    }
    mapping(uint256 => XVGAsset) public xvgData;

    function _writeXVG(uint256 id, bytes calldata data, uint32 size) internal {
        xvgData[id].size = size;

        uint32 partSize = 24_000;
        uint32 zippedSize = uint32(data.length);
        uint32 numParts = (zippedSize + partSize - 1) / partSize;

        for (uint32 i; i < numParts; i++) {
            uint32 start = i * partSize;
            uint32 end = start + partSize > zippedSize
                ? zippedSize
                : start + partSize;
            xvgData[id].slots.push(
                SSTORE2.write(_sliceBytes(data, start, end))
            );
        }
    }

    function readXVG(uint256 id) public view returns (string memory) {
        bytes memory svg;
        for (uint256 i; i < xvgData[id].slots.length; i++) {
            svg = bytes.concat(svg, SSTORE2.read(xvgData[id].slots[i]));
        }
        (, bytes memory output) = InflateLib.puff(svg, xvgData[id].size);
        return string(output);
    }

    function _sliceBytes(
        bytes calldata strBytes,
        uint32 startIndex,
        uint32 endIndex
    ) private pure returns (bytes memory) {
        bytes memory result = new bytes(endIndex - startIndex);
        for (uint256 i = startIndex; i < endIndex; i++) {
            result[i - startIndex] = strBytes[i];
        }
        return result;
    }
}

File 5 of 8 : XVGMetadata.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

contract XVGMetadata {
    struct XVGMeta {
        uint256 price;
        string name;
    }
    mapping(uint256 => XVGMeta) public xvgMeta;

    function _writeXVGMeta(uint256 id, string memory name) internal {
        xvgMeta[id].name = name;
    }

    function _writeXVGPrice(uint256 id, uint256 price) internal {
        xvgMeta[id].price = price;
    }
}

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

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return result;
    }
}

File 7 of 8 : SSTORE2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Read and write to persistent storage at a fraction of the cost.
/// @author Solady (https://github.com/vectorized/solmady/blob/main/src/utils/SSTORE2.sol)
/// @author Saw-mon-and-Natalie (https://github.com/Saw-mon-and-Natalie)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SSTORE2.sol)
/// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol)
library SSTORE2 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev We skip the first byte as it's a STOP opcode,
    /// which ensures the contract can't be called.
    uint256 internal constant DATA_OFFSET = 1;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Unable to deploy the storage contract.
    error DeploymentFailed();

    /// @dev The storage contract address is invalid.
    error InvalidPointer();

    /// @dev Attempt to read outside of the storage contract's bytecode bounds.
    error ReadOutOfBounds();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         WRITE LOGIC                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Writes `data` into the bytecode of a storage contract and returns its address.
    function write(bytes memory data) internal returns (address pointer) {
        /// @solidity memory-safe-assembly
        assembly {
            let originalDataLength := mload(data)

            // Add 1 to data size since we are prefixing it with a STOP opcode.
            let dataSize := add(originalDataLength, DATA_OFFSET)

            /**
             * ------------------------------------------------------------------------------+
             * Opcode      | Mnemonic        | Stack                   | Memory              |
             * ------------------------------------------------------------------------------|
             * 61 dataSize | PUSH2 dataSize  | dataSize                |                     |
             * 80          | DUP1            | dataSize dataSize       |                     |
             * 60 0xa      | PUSH1 0xa       | 0xa dataSize dataSize   |                     |
             * 3D          | RETURNDATASIZE  | 0 0xa dataSize dataSize |                     |
             * 39          | CODECOPY        | dataSize                | [0..dataSize): code |
             * 3D          | RETURNDATASIZE  | 0 dataSize              | [0..dataSize): code |
             * F3          | RETURN          |                         | [0..dataSize): code |
             * 00          | STOP            |                         |                     |
             * ------------------------------------------------------------------------------+
             * @dev Prefix the bytecode with a STOP opcode to ensure it cannot be called.
             * Also PUSH2 is used since max contract size cap is 24,576 bytes which is less than 2 ** 16.
             */
            mstore(
                // Do a out-of-gas revert if `dataSize` is more than 2 bytes.
                // The actual EVM limit may be smaller and may change over time.
                add(data, gt(dataSize, 0xffff)),
                // Left shift `dataSize` by 64 so that it lines up with the 0000 after PUSH2.
                or(0xfd61000080600a3d393df300, shl(0x40, dataSize))
            )

            // Deploy a new contract with the generated creation code.
            pointer := create(0, add(data, 0x15), add(dataSize, 0xa))

            // If `pointer` is zero, revert.
            if iszero(pointer) {
                // Store the function selector of `DeploymentFailed()`.
                mstore(0x00, 0x30116425)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            // Restore original length of the variable size `data`.
            mstore(data, originalDataLength)
        }
    }

    /// @dev Writes `data` into the bytecode of a storage contract with `salt`
    /// and returns its deterministic address.
    function writeDeterministic(bytes memory data, bytes32 salt)
        internal
        returns (address pointer)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let originalDataLength := mload(data)
            let dataSize := add(originalDataLength, DATA_OFFSET)

            mstore(
                // Do a out-of-gas revert if `dataSize` is more than 2 bytes.
                // The actual EVM limit may be smaller and may change over time.
                add(data, gt(dataSize, 0xffff)),
                // Left shift `dataSize` by 64 so that it lines up with the 0000 after PUSH2.
                or(0xfd61000080600a3d393df300, shl(0x40, dataSize))
            )

            // Deploy a new contract with the generated creation code.
            pointer := create2(0, add(data, 0x15), add(dataSize, 0xa), salt)

            // If `pointer` is zero, revert.
            if iszero(pointer) {
                // Store the function selector of `DeploymentFailed()`.
                mstore(0x00, 0x30116425)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            // Restore original length of the variable size `data`.
            mstore(data, originalDataLength)
        }
    }

    /// @dev Returns the initialization code hash of the storage contract for `data`.
    /// Used for mining vanity addresses with create2crunch.
    function initCodeHash(bytes memory data) internal pure returns (bytes32 hash) {
        /// @solidity memory-safe-assembly
        assembly {
            let originalDataLength := mload(data)
            let dataSize := add(originalDataLength, DATA_OFFSET)

            // Do a out-of-gas revert if `dataSize` is more than 2 bytes.
            // The actual EVM limit may be smaller and may change over time.
            returndatacopy(returndatasize(), returndatasize(), shr(16, dataSize))

            mstore(data, or(0x61000080600a3d393df300, shl(0x40, dataSize)))

            hash := keccak256(add(data, 0x15), add(dataSize, 0xa))

            // Restore original length of the variable size `data`.
            mstore(data, originalDataLength)
        }
    }

    /// @dev Returns the address of the storage contract for `data`
    /// deployed with `salt` by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddress(bytes memory data, bytes32 salt, address deployer)
        internal
        pure
        returns (address predicted)
    {
        bytes32 hash = initCodeHash(data);
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and store the bytecode hash.
            mstore8(0x00, 0xff) // Write the prefix.
            mstore(0x35, hash)
            mstore(0x01, shl(96, deployer))
            mstore(0x15, salt)
            predicted := keccak256(0x00, 0x55)
            // Restore the part of the free memory pointer that has been overwritten.
            mstore(0x35, 0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         READ LOGIC                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns all the `data` from the bytecode of the storage contract at `pointer`.
    function read(address pointer) internal view returns (bytes memory data) {
        /// @solidity memory-safe-assembly
        assembly {
            let pointerCodesize := extcodesize(pointer)
            if iszero(pointerCodesize) {
                // Store the function selector of `InvalidPointer()`.
                mstore(0x00, 0x11052bb4)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Offset all indices by 1 to skip the STOP opcode.
            let size := sub(pointerCodesize, DATA_OFFSET)

            // Get the pointer to the free memory and allocate
            // enough 32-byte words for the data and the length of the data,
            // then copy the code to the allocated memory.
            // Masking with 0xffe0 will suffice, since contract size is less than 16 bits.
            data := mload(0x40)
            mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0)))
            mstore(data, size)
            mstore(add(add(data, 0x20), size), 0) // Zeroize the last slot.
            extcodecopy(pointer, add(data, 0x20), DATA_OFFSET, size)
        }
    }

    /// @dev Returns the `data` from the bytecode of the storage contract at `pointer`,
    /// from the byte at `start`, to the end of the data stored.
    function read(address pointer, uint256 start) internal view returns (bytes memory data) {
        /// @solidity memory-safe-assembly
        assembly {
            let pointerCodesize := extcodesize(pointer)
            if iszero(pointerCodesize) {
                // Store the function selector of `InvalidPointer()`.
                mstore(0x00, 0x11052bb4)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            // If `!(pointer.code.size > start)`, reverts.
            // This also handles the case where `start + DATA_OFFSET` overflows.
            if iszero(gt(pointerCodesize, start)) {
                // Store the function selector of `ReadOutOfBounds()`.
                mstore(0x00, 0x84eb0dd1)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            let size := sub(pointerCodesize, add(start, DATA_OFFSET))

            // Get the pointer to the free memory and allocate
            // enough 32-byte words for the data and the length of the data,
            // then copy the code to the allocated memory.
            // Masking with 0xffe0 will suffice, since contract size is less than 16 bits.
            data := mload(0x40)
            mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0)))
            mstore(data, size)
            mstore(add(add(data, 0x20), size), 0) // Zeroize the last slot.
            extcodecopy(pointer, add(data, 0x20), add(start, DATA_OFFSET), size)
        }
    }

    /// @dev Returns the `data` from the bytecode of the storage contract at `pointer`,
    /// from the byte at `start`, to the byte at `end` (exclusive) of the data stored.
    function read(address pointer, uint256 start, uint256 end)
        internal
        view
        returns (bytes memory data)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let pointerCodesize := extcodesize(pointer)
            if iszero(pointerCodesize) {
                // Store the function selector of `InvalidPointer()`.
                mstore(0x00, 0x11052bb4)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            // If `!(pointer.code.size > end) || (start > end)`, revert.
            // This also handles the cases where
            // `end + DATA_OFFSET` or `start + DATA_OFFSET` overflows.
            if iszero(
                and(
                    gt(pointerCodesize, end), // Within bounds.
                    iszero(gt(start, end)) // Valid range.
                )
            ) {
                // Store the function selector of `ReadOutOfBounds()`.
                mstore(0x00, 0x84eb0dd1)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            let size := sub(end, start)

            // Get the pointer to the free memory and allocate
            // enough 32-byte words for the data and the length of the data,
            // then copy the code to the allocated memory.
            // Masking with 0xffe0 will suffice, since contract size is less than 16 bits.
            data := mload(0x40)
            mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0)))
            mstore(data, size)
            mstore(add(add(data, 0x20), size), 0) // Zeroize the last slot.
            extcodecopy(pointer, add(data, 0x20), add(start, DATA_OFFSET), size)
        }
    }
}

File 8 of 8 : InflateLib.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0 <0.9.0;

/// @notice Based on https://github.com/madler/zlib/blob/master/contrib/puff
library InflateLib {
    // Maximum bits in a code
    uint256 constant MAXBITS = 15;
    // Maximum number of literal/length codes
    uint256 constant MAXLCODES = 286;
    // Maximum number of distance codes
    uint256 constant MAXDCODES = 30;
    // Maximum codes lengths to read
    uint256 constant MAXCODES = (MAXLCODES + MAXDCODES);
    // Number of fixed literal/length codes
    uint256 constant FIXLCODES = 288;

    // Error codes
    enum ErrorCode {
        ERR_NONE, // 0 successful inflate
        ERR_NOT_TERMINATED, // 1 available inflate data did not terminate
        ERR_OUTPUT_EXHAUSTED, // 2 output space exhausted before completing inflate
        ERR_INVALID_BLOCK_TYPE, // 3 invalid block type (type == 3)
        ERR_STORED_LENGTH_NO_MATCH, // 4 stored block length did not match one's complement
        ERR_TOO_MANY_LENGTH_OR_DISTANCE_CODES, // 5 dynamic block code description: too many length or distance codes
        ERR_CODE_LENGTHS_CODES_INCOMPLETE, // 6 dynamic block code description: code lengths codes incomplete
        ERR_REPEAT_NO_FIRST_LENGTH, // 7 dynamic block code description: repeat lengths with no first length
        ERR_REPEAT_MORE, // 8 dynamic block code description: repeat more than specified lengths
        ERR_INVALID_LITERAL_LENGTH_CODE_LENGTHS, // 9 dynamic block code description: invalid literal/length code lengths
        ERR_INVALID_DISTANCE_CODE_LENGTHS, // 10 dynamic block code description: invalid distance code lengths
        ERR_MISSING_END_OF_BLOCK, // 11 dynamic block code description: missing end-of-block code
        ERR_INVALID_LENGTH_OR_DISTANCE_CODE, // 12 invalid literal/length or distance code in fixed or dynamic block
        ERR_DISTANCE_TOO_FAR, // 13 distance is too far back in fixed or dynamic block
        ERR_CONSTRUCT // 14 internal: error in construct()
    }

    // Input and output state
    struct State {
        //////////////////
        // Output state //
        //////////////////
        // Output buffer
        bytes output;
        // Bytes written to out so far
        uint256 outcnt;
        /////////////////
        // Input state //
        /////////////////
        // Input buffer
        bytes input;
        // Bytes read so far
        uint256 incnt;
        ////////////////
        // Temp state //
        ////////////////
        // Bit buffer
        uint256 bitbuf;
        // Number of bits in bit buffer
        uint256 bitcnt;
        //////////////////////////
        // Static Huffman codes //
        //////////////////////////
        Huffman lencode;
        Huffman distcode;
    }

    // Huffman code decoding tables
    struct Huffman {
        uint256[] counts;
        uint256[] symbols;
    }

    function bits(
        State memory s,
        uint256 need
    ) private pure returns (ErrorCode, uint256) {
        // Bit accumulator (can use up to 20 bits)
        uint256 val;

        // Load at least need bits into val
        val = s.bitbuf;
        while (s.bitcnt < need) {
            if (s.incnt == s.input.length) {
                // Out of input
                return (ErrorCode.ERR_NOT_TERMINATED, 0);
            }

            // Load eight bits
            val |= uint256(uint8(s.input[s.incnt++])) << s.bitcnt;
            s.bitcnt += 8;
        }

        // Drop need bits and update buffer, always zero to seven bits left
        s.bitbuf = val >> need;
        s.bitcnt -= need;

        // Return need bits, zeroing the bits above that
        uint256 ret = (val & ((1 << need) - 1));
        return (ErrorCode.ERR_NONE, ret);
    }

    function _stored(State memory s) private pure returns (ErrorCode) {
        // Length of stored block
        uint256 len;

        // Discard leftover bits from current byte (assumes s.bitcnt < 8)
        s.bitbuf = 0;
        s.bitcnt = 0;

        // Get length and check against its one's complement
        if (s.incnt + 4 > s.input.length) {
            // Not enough input
            return ErrorCode.ERR_NOT_TERMINATED;
        }
        len = uint256(uint8(s.input[s.incnt++]));
        len |= uint256(uint8(s.input[s.incnt++])) << 8;

        if (
            uint8(s.input[s.incnt++]) != (~len & 0xFF) ||
            uint8(s.input[s.incnt++]) != ((~len >> 8) & 0xFF)
        ) {
            // Didn't match complement!
            return ErrorCode.ERR_STORED_LENGTH_NO_MATCH;
        }

        // Copy len bytes from in to out
        if (s.incnt + len > s.input.length) {
            // Not enough input
            return ErrorCode.ERR_NOT_TERMINATED;
        }
        if (s.outcnt + len > s.output.length) {
            // Not enough output space
            return ErrorCode.ERR_OUTPUT_EXHAUSTED;
        }
        while (len != 0) {
            // Note: Solidity reverts on underflow, so we decrement here
            len -= 1;
            s.output[s.outcnt++] = s.input[s.incnt++];
        }

        // Done with a valid stored block
        return ErrorCode.ERR_NONE;
    }

    function _decode(
        State memory s,
        Huffman memory h
    ) private pure returns (ErrorCode, uint256) {
        // Current number of bits in code
        uint256 len;
        // Len bits being decoded
        uint256 code = 0;
        // First code of length len
        uint256 first = 0;
        // Number of codes of length len
        uint256 count;
        // Index of first code of length len in symbol table
        uint256 index = 0;
        // Error code
        ErrorCode err;

        for (len = 1; len <= MAXBITS; len++) {
            // Get next bit
            uint256 tempCode;
            (err, tempCode) = bits(s, 1);
            if (err != ErrorCode.ERR_NONE) {
                return (err, 0);
            }
            code |= tempCode;
            count = h.counts[len];

            // If length len, return symbol
            if (code < first + count) {
                return (ErrorCode.ERR_NONE, h.symbols[index + (code - first)]);
            }
            // Else update for next length
            index += count;
            first += count;
            first <<= 1;
            code <<= 1;
        }

        // Ran out of codes
        return (ErrorCode.ERR_INVALID_LENGTH_OR_DISTANCE_CODE, 0);
    }

    function _construct(
        Huffman memory h,
        uint256[] memory lengths,
        uint256 n,
        uint256 start
    ) private pure returns (ErrorCode) {
        // Current symbol when stepping through lengths[]
        uint256 symbol;
        // Current length when stepping through h.counts[]
        uint256 len;
        // Number of possible codes left of current length
        uint256 left;
        // Offsets in symbol table for each length
        uint256[MAXBITS + 1] memory offs;

        // Count number of codes of each length
        for (len = 0; len <= MAXBITS; len++) {
            h.counts[len] = 0;
        }
        for (symbol = 0; symbol < n; symbol++) {
            // Assumes lengths are within bounds
            h.counts[lengths[start + symbol]]++;
        }
        // No codes!
        if (h.counts[0] == n) {
            // Complete, but decode() will fail
            return (ErrorCode.ERR_NONE);
        }

        // Check for an over-subscribed or incomplete set of lengths

        // One possible code of zero length
        left = 1;

        for (len = 1; len <= MAXBITS; len++) {
            // One more bit, double codes left
            left <<= 1;
            if (left < h.counts[len]) {
                // Over-subscribed--return error
                return ErrorCode.ERR_CONSTRUCT;
            }
            // Deduct count from possible codes

            left -= h.counts[len];
        }

        // Generate offsets into symbol table for each length for sorting
        offs[1] = 0;
        for (len = 1; len < MAXBITS; len++) {
            offs[len + 1] = offs[len] + h.counts[len];
        }

        // Put symbols in table sorted by length, by symbol order within each length
        for (symbol = 0; symbol < n; symbol++) {
            if (lengths[start + symbol] != 0) {
                h.symbols[offs[lengths[start + symbol]]++] = symbol;
            }
        }

        // Left > 0 means incomplete
        return left > 0 ? ErrorCode.ERR_CONSTRUCT : ErrorCode.ERR_NONE;
    }

    function _codes(
        State memory s,
        Huffman memory lencode,
        Huffman memory distcode
    ) private pure returns (ErrorCode) {
        // Decoded symbol
        uint256 symbol;
        // Length for copy
        uint256 len;
        // Distance for copy
        uint256 dist;
        // TODO Solidity doesn't support constant arrays, but these are fixed at compile-time
        // Size base for length codes 257..285
        uint16[29] memory lens = [
            3,
            4,
            5,
            6,
            7,
            8,
            9,
            10,
            11,
            13,
            15,
            17,
            19,
            23,
            27,
            31,
            35,
            43,
            51,
            59,
            67,
            83,
            99,
            115,
            131,
            163,
            195,
            227,
            258
        ];
        // Extra bits for length codes 257..285
        uint8[29] memory lext = [
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            1,
            1,
            1,
            1,
            2,
            2,
            2,
            2,
            3,
            3,
            3,
            3,
            4,
            4,
            4,
            4,
            5,
            5,
            5,
            5,
            0
        ];
        // Offset base for distance codes 0..29
        uint16[30] memory dists = [
            1,
            2,
            3,
            4,
            5,
            7,
            9,
            13,
            17,
            25,
            33,
            49,
            65,
            97,
            129,
            193,
            257,
            385,
            513,
            769,
            1025,
            1537,
            2049,
            3073,
            4097,
            6145,
            8193,
            12289,
            16385,
            24577
        ];
        // Extra bits for distance codes 0..29
        uint8[30] memory dext = [
            0,
            0,
            0,
            0,
            1,
            1,
            2,
            2,
            3,
            3,
            4,
            4,
            5,
            5,
            6,
            6,
            7,
            7,
            8,
            8,
            9,
            9,
            10,
            10,
            11,
            11,
            12,
            12,
            13,
            13
        ];
        // Error code
        ErrorCode err;

        // Decode literals and length/distance pairs
        while (symbol != 256) {
            (err, symbol) = _decode(s, lencode);
            if (err != ErrorCode.ERR_NONE) {
                // Invalid symbol
                return err;
            }

            if (symbol < 256) {
                // Literal: symbol is the byte
                // Write out the literal
                if (s.outcnt == s.output.length) {
                    return ErrorCode.ERR_OUTPUT_EXHAUSTED;
                }
                s.output[s.outcnt] = bytes1(uint8(symbol));
                s.outcnt++;
            } else if (symbol > 256) {
                uint256 tempBits;
                // Length
                // Get and compute length
                symbol -= 257;
                if (symbol >= 29) {
                    // Invalid fixed code
                    return ErrorCode.ERR_INVALID_LENGTH_OR_DISTANCE_CODE;
                }

                (err, tempBits) = bits(s, lext[symbol]);
                if (err != ErrorCode.ERR_NONE) {
                    return err;
                }
                len = lens[symbol] + tempBits;

                // Get and check distance
                (err, symbol) = _decode(s, distcode);
                if (err != ErrorCode.ERR_NONE) {
                    // Invalid symbol
                    return err;
                }
                (err, tempBits) = bits(s, dext[symbol]);
                if (err != ErrorCode.ERR_NONE) {
                    return err;
                }
                dist = dists[symbol] + tempBits;
                if (dist > s.outcnt) {
                    // Distance too far back
                    return ErrorCode.ERR_DISTANCE_TOO_FAR;
                }

                // Copy length bytes from distance bytes back
                if (s.outcnt + len > s.output.length) {
                    return ErrorCode.ERR_OUTPUT_EXHAUSTED;
                }
                while (len != 0) {
                    // Note: Solidity reverts on underflow, so we decrement here
                    len -= 1;
                    s.output[s.outcnt] = s.output[s.outcnt - dist];
                    s.outcnt++;
                }
            } else {
                s.outcnt += len;
            }
        }

        // Done with a valid fixed or dynamic block
        return ErrorCode.ERR_NONE;
    }

    function _build_fixed(State memory s) private pure returns (ErrorCode) {
        // Build fixed Huffman tables
        // TODO this is all a compile-time constant
        uint256 symbol;
        uint256[] memory lengths = new uint256[](FIXLCODES);

        // Literal/length table
        for (symbol = 0; symbol < 144; symbol++) {
            lengths[symbol] = 8;
        }
        for (; symbol < 256; symbol++) {
            lengths[symbol] = 9;
        }
        for (; symbol < 280; symbol++) {
            lengths[symbol] = 7;
        }
        for (; symbol < FIXLCODES; symbol++) {
            lengths[symbol] = 8;
        }

        _construct(s.lencode, lengths, FIXLCODES, 0);

        // Distance table
        for (symbol = 0; symbol < MAXDCODES; symbol++) {
            lengths[symbol] = 5;
        }

        _construct(s.distcode, lengths, MAXDCODES, 0);

        return ErrorCode.ERR_NONE;
    }

    function _fixed(State memory s) private pure returns (ErrorCode) {
        // Decode data until end-of-block code
        return _codes(s, s.lencode, s.distcode);
    }

    function _build_dynamic_lengths(
        State memory s
    ) private pure returns (ErrorCode, uint256[] memory) {
        uint256 ncode;
        // Index of lengths[]
        uint256 index;
        // Descriptor code lengths
        uint256[] memory lengths = new uint256[](MAXCODES);
        // Error code
        ErrorCode err;
        // Permutation of code length codes
        uint8[19] memory order = [
            16,
            17,
            18,
            0,
            8,
            7,
            9,
            6,
            10,
            5,
            11,
            4,
            12,
            3,
            13,
            2,
            14,
            1,
            15
        ];

        (err, ncode) = bits(s, 4);
        if (err != ErrorCode.ERR_NONE) {
            return (err, lengths);
        }
        ncode += 4;

        // Read code length code lengths (really), missing lengths are zero
        for (index = 0; index < ncode; index++) {
            (err, lengths[order[index]]) = bits(s, 3);
            if (err != ErrorCode.ERR_NONE) {
                return (err, lengths);
            }
        }
        for (; index < 19; index++) {
            lengths[order[index]] = 0;
        }

        return (ErrorCode.ERR_NONE, lengths);
    }

    function _build_dynamic(
        State memory s
    ) private pure returns (ErrorCode, Huffman memory, Huffman memory) {
        // Number of lengths in descriptor
        uint256 nlen;
        uint256 ndist;
        // Index of lengths[]
        uint256 index;
        // Error code
        ErrorCode err;
        // Descriptor code lengths
        uint256[] memory lengths = new uint256[](MAXCODES);
        // Length and distance codes
        Huffman memory lencode = Huffman(
            new uint256[](MAXBITS + 1),
            new uint256[](MAXLCODES)
        );
        Huffman memory distcode = Huffman(
            new uint256[](MAXBITS + 1),
            new uint256[](MAXDCODES)
        );
        uint256 tempBits;

        // Get number of lengths in each table, check lengths
        (err, nlen) = bits(s, 5);
        if (err != ErrorCode.ERR_NONE) {
            return (err, lencode, distcode);
        }
        nlen += 257;
        (err, ndist) = bits(s, 5);
        if (err != ErrorCode.ERR_NONE) {
            return (err, lencode, distcode);
        }
        ndist += 1;

        if (nlen > MAXLCODES || ndist > MAXDCODES) {
            // Bad counts
            return (
                ErrorCode.ERR_TOO_MANY_LENGTH_OR_DISTANCE_CODES,
                lencode,
                distcode
            );
        }

        (err, lengths) = _build_dynamic_lengths(s);
        if (err != ErrorCode.ERR_NONE) {
            return (err, lencode, distcode);
        }

        // Build huffman table for code lengths codes (use lencode temporarily)
        err = _construct(lencode, lengths, 19, 0);
        if (err != ErrorCode.ERR_NONE) {
            // Require complete code set here
            return (
                ErrorCode.ERR_CODE_LENGTHS_CODES_INCOMPLETE,
                lencode,
                distcode
            );
        }

        // Read length/literal and distance code length tables
        index = 0;
        while (index < nlen + ndist) {
            // Decoded value
            uint256 symbol;
            // Last length to repeat
            uint256 len;

            (err, symbol) = _decode(s, lencode);
            if (err != ErrorCode.ERR_NONE) {
                // Invalid symbol
                return (err, lencode, distcode);
            }

            if (symbol < 16) {
                // Length in 0..15
                lengths[index++] = symbol;
            } else {
                // Repeat instruction
                // Assume repeating zeros
                len = 0;
                if (symbol == 16) {
                    // Repeat last length 3..6 times
                    if (index == 0) {
                        // No last length!
                        return (
                            ErrorCode.ERR_REPEAT_NO_FIRST_LENGTH,
                            lencode,
                            distcode
                        );
                    }
                    // Last length
                    len = lengths[index - 1];
                    (err, tempBits) = bits(s, 2);
                    if (err != ErrorCode.ERR_NONE) {
                        return (err, lencode, distcode);
                    }
                    symbol = 3 + tempBits;
                } else if (symbol == 17) {
                    // Repeat zero 3..10 times
                    (err, tempBits) = bits(s, 3);
                    if (err != ErrorCode.ERR_NONE) {
                        return (err, lencode, distcode);
                    }
                    symbol = 3 + tempBits;
                } else {
                    // == 18, repeat zero 11..138 times
                    (err, tempBits) = bits(s, 7);
                    if (err != ErrorCode.ERR_NONE) {
                        return (err, lencode, distcode);
                    }
                    symbol = 11 + tempBits;
                }

                if (index + symbol > nlen + ndist) {
                    // Too many lengths!
                    return (ErrorCode.ERR_REPEAT_MORE, lencode, distcode);
                }
                while (symbol != 0) {
                    // Note: Solidity reverts on underflow, so we decrement here
                    symbol -= 1;

                    // Repeat last or zero symbol times
                    lengths[index++] = len;
                }
            }
        }

        // Check for end-of-block code -- there better be one!
        if (lengths[256] == 0) {
            return (ErrorCode.ERR_MISSING_END_OF_BLOCK, lencode, distcode);
        }

        // Build huffman table for literal/length codes
        err = _construct(lencode, lengths, nlen, 0);
        if (
            err != ErrorCode.ERR_NONE &&
            (err == ErrorCode.ERR_NOT_TERMINATED ||
                err == ErrorCode.ERR_OUTPUT_EXHAUSTED ||
                nlen != lencode.counts[0] + lencode.counts[1])
        ) {
            // Incomplete code ok only for single length 1 code
            return (
                ErrorCode.ERR_INVALID_LITERAL_LENGTH_CODE_LENGTHS,
                lencode,
                distcode
            );
        }

        // Build huffman table for distance codes
        err = _construct(distcode, lengths, ndist, nlen);
        if (
            err != ErrorCode.ERR_NONE &&
            (err == ErrorCode.ERR_NOT_TERMINATED ||
                err == ErrorCode.ERR_OUTPUT_EXHAUSTED ||
                ndist != distcode.counts[0] + distcode.counts[1])
        ) {
            // Incomplete code ok only for single length 1 code
            return (
                ErrorCode.ERR_INVALID_DISTANCE_CODE_LENGTHS,
                lencode,
                distcode
            );
        }

        return (ErrorCode.ERR_NONE, lencode, distcode);
    }

    function _dynamic(State memory s) private pure returns (ErrorCode) {
        // Length and distance codes
        Huffman memory lencode;
        Huffman memory distcode;
        // Error code
        ErrorCode err;

        (err, lencode, distcode) = _build_dynamic(s);
        if (err != ErrorCode.ERR_NONE) {
            return err;
        }

        // Decode data until end-of-block code
        return _codes(s, lencode, distcode);
    }

    function puff(
        bytes memory source,
        uint256 destlen
    ) internal pure returns (ErrorCode, bytes memory) {
        // Input/output state
        State memory s = State(
            new bytes(destlen),
            0,
            source,
            0,
            0,
            0,
            Huffman(new uint256[](MAXBITS + 1), new uint256[](FIXLCODES)),
            Huffman(new uint256[](MAXBITS + 1), new uint256[](MAXDCODES))
        );
        // Temp: last bit
        uint256 last;
        // Temp: block type bit
        uint256 t;
        // Error code
        ErrorCode err;

        // Build fixed Huffman tables
        err = _build_fixed(s);
        if (err != ErrorCode.ERR_NONE) {
            return (err, s.output);
        }

        // Process blocks until last block or error
        while (last == 0) {
            // One if last block
            (err, last) = bits(s, 1);
            if (err != ErrorCode.ERR_NONE) {
                return (err, s.output);
            }

            // Block type 0..3
            (err, t) = bits(s, 2);
            if (err != ErrorCode.ERR_NONE) {
                return (err, s.output);
            }

            err = (
                t == 0
                    ? _stored(s)
                    : (
                        t == 1
                            ? _fixed(s)
                            : (
                                t == 2
                                    ? _dynamic(s)
                                    : ErrorCode.ERR_INVALID_BLOCK_TYPE
                            )
                    )
            );
            // type == 3, invalid

            if (err != ErrorCode.ERR_NONE) {
                // Return with error
                break;
            }
        }

        return (err, s.output);
    }
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "inflate-sol/=lib/inflate-sol/contracts/",
    "solady/=lib/solady/src/",
    "solmate/=lib/solmate/src/",
    "zipped-contracts/=lib/zipped-contracts/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyMinted","type":"error"},{"inputs":[],"name":"InvalidMessageValue","type":"error"},{"inputs":[],"name":"MaxSupplyReached","type":"error"},{"inputs":[],"name":"MintNotOpen","type":"error"},{"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":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"MINT_OPEN","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"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":"","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":"tokenId","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","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":"uint256","name":"id","type":"uint256"}],"name":"readXVG","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":"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":"string","name":"_description","type":"string"}],"name":"setDescription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"open","type":"bool"}],"name":"setMintOpen","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"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":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint32","name":"size","type":"uint32"}],"name":"writeXVG","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"name","type":"string"}],"name":"writeXVGMeta","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"writeXVGPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"xvgData","outputs":[{"internalType":"uint32","name":"size","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"xvgMeta","outputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"}]

60e0604052602c60808181529062003ea760a039600a90620000229082620002b9565b503480156200003057600080fd5b5060408051808201825260038082526258564760e81b6020808401829052845180860190955291845290830152339160006200006d8382620002b9565b5060016200007c8282620002b9565b5050600680546001600160a01b0319166001600160a01b0384169081179091556040519091506000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35060015b60178111620000f857620000e33082620000ff565b80620000ef8162000385565b915050620000ce565b50620003ad565b6001600160a01b0382166200014f5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b60448201526064015b60405180910390fd5b6000818152600260205260409020546001600160a01b031615620001a75760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b604482015260640162000146565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200023d57607f821691505b6020821081036200025e57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002b4576000816000526020600020601f850160051c810160208610156200028f5750805b601f850160051c820191505b81811015620002b0578281556001016200029b565b5050505b505050565b81516001600160401b03811115620002d557620002d562000212565b620002ed81620002e6845462000228565b8462000264565b602080601f8311600181146200032557600084156200030c5750858301515b600019600386901b1c1916600185901b178555620002b0565b600085815260208120601f198616915b82811015620003565788860151825594840194600190910190840162000335565b5085821015620003755787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060018201620003a657634e487b7160e01b600052601160045260246000fd5b5060010190565b613aea80620003bd6000396000f3fe6080604052600436106101815760003560e01c806390c3f38f116100d1578063b88d4fde1161008a578063e985e9c511610064578063e985e9c5146104b3578063ed5fd146146104ee578063f2fde38b1461050e578063f8004d311461052e57600080fd5b8063b88d4fde14610453578063c87b56dd14610473578063d609b5e11461049357600080fd5b806390c3f38f146103ab57806390f5368a146103cb57806395d89b41146103eb578063a0712d6814610400578063a22cb46514610413578063af5878901461043357600080fd5b806329b3264f1161013e5780635ca21123116101185780635ca21123146102f55780636352211e1461033d57806370a082311461035d5780638da5cb5b1461038b57600080fd5b806329b3264f1461028757806342842e0e146102b557806351cff8d9146102d557600080fd5b806301ffc9a71461018657806306fdde03146101bb578063081812fc146101dd578063088b69431461022b578063095ea7b31461024557806323b872dd14610267575b600080fd5b34801561019257600080fd5b506101a66101a1366004613187565b61054e565b60405190151581526020015b60405180910390f35b3480156101c757600080fd5b506101d06105a0565b6040516101b291906131f4565b3480156101e957600080fd5b506102136101f8366004613207565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016101b2565b34801561023757600080fd5b506009546101a69060ff1681565b34801561025157600080fd5b50610265610260366004613237565b61062e565b005b34801561027357600080fd5b50610265610282366004613261565b610715565b34801561029357600080fd5b506102a76102a2366004613207565b6108dc565b6040516101b292919061329d565b3480156102c157600080fd5b506102656102d0366004613261565b610981565b3480156102e157600080fd5b506102656102f03660046132b6565b610a79565b34801561030157600080fd5b50610328610310366004613207565b60086020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016101b2565b34801561034957600080fd5b50610213610358366004613207565b610b41565b34801561036957600080fd5b5061037d6103783660046132b6565b610b98565b6040519081526020016101b2565b34801561039757600080fd5b50600654610213906001600160a01b031681565b3480156103b757600080fd5b506102656103c6366004613373565b610bfb565b3480156103d757600080fd5b506101d06103e6366004613207565b610c31565b3480156103f757600080fd5b506101d0610ce8565b61026561040e366004613207565b610cf5565b34801561041f57600080fd5b5061026561042e3660046133b7565b610dd5565b34801561043f57600080fd5b5061026561044e3660046133ea565b610e41565b34801561045f57600080fd5b5061026561046e36600461344d565b610e7d565b34801561047f57600080fd5b506101d061048e366004613207565b610f65565b34801561049f57600080fd5b506102656104ae3660046134bb565b610fe0565b3480156104bf57600080fd5b506101a66104ce366004613501565b600560209081526000928352604080842090915290825290205460ff1681565b3480156104fa57600080fd5b5061026561050936600461352b565b61104b565b34801561051a57600080fd5b506102656105293660046132b6565b611087565b34801561053a57600080fd5b50610265610549366004613592565b6110fd565b60006301ffc9a760e01b6001600160e01b03198316148061057f57506380ac58cd60e01b6001600160e01b03198316145b8061059a5750635b5e139f60e01b6001600160e01b03198316145b92915050565b600080546105ad906135ad565b80601f01602080910402602001604051908101604052809291908181526020018280546105d9906135ad565b80156106265780601f106105fb57610100808354040283529160200191610626565b820191906000526020600020905b81548152906001019060200180831161060957829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b03163381148061067757506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6106b95760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064015b60405180910390fd5b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000818152600260205260409020546001600160a01b0384811691161461076b5760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b60448201526064016106b0565b6001600160a01b0382166107b55760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b60448201526064016106b0565b336001600160a01b03841614806107ef57506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b8061081057506000818152600460205260409020546001600160a01b031633145b61084d5760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016106b0565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600760205260009081526040902080546001820180549192916108fe906135ad565b80601f016020809104026020016040519081016040528092919081815260200182805461092a906135ad565b80156109775780601f1061094c57610100808354040283529160200191610977565b820191906000526020600020905b81548152906001019060200180831161095a57829003601f168201915b5050505050905082565b61098c838383610715565b6001600160a01b0382163b1580610a355750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610a05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2991906135e7565b6001600160e01b031916145b610a745760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016106b0565b505050565b6006546001600160a01b03163314610aa35760405162461bcd60e51b81526004016106b090613604565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b3d5760405162461bcd60e51b8152602060048201526014602482015273161591ce881dda5d1a191c985dc819985a5b195960621b60448201526064016106b0565b5050565b6000818152600260205260409020546001600160a01b031680610b935760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b60448201526064016106b0565b919050565b60006001600160a01b038216610bdf5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b60448201526064016106b0565b506001600160a01b031660009081526003602052604090205490565b6006546001600160a01b03163314610c255760405162461bcd60e51b81526004016106b090613604565b600a610b3d828261367a565b60608060005b600084815260086020526040902060010154811015610cbe57600084815260086020526040902060010180548391610c939184908110610c7957610c79613739565b6000918252602090912001546001600160a01b031661113a565b604051602001610ca492919061374f565b60408051601f198184030181529190529150600101610c37565b50600083815260086020526040812054610cdf90839063ffffffff16611184565b95945050505050565b600180546105ad906135ad565b60095460ff16610d185760405163951b974f60e01b815260040160405180910390fd5b6000818152600760205260408120549003610d465760405163951b974f60e01b815260040160405180910390fd5b6000818152600760205260409020543414610d745760405163d5e6876b60e01b815260040160405180910390fd5b30610d7e82610b41565b6001600160a01b031614610da557604051631bbdf5c560e31b815260040160405180910390fd5b600081815260046020526040902080546001600160a01b03191633908117909155610dd290309083610715565b50565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6006546001600160a01b03163314610e6b5760405162461bcd60e51b81526004016106b090613604565b60009182526007602052604090912055565b610e88858585610715565b6001600160a01b0384163b1580610f1f5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290610ed09033908a9089908990899060040161377e565b6020604051808303816000875af1158015610eef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1391906135e7565b6001600160e01b031916145b610f5e5760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016106b0565b5050505050565b600081815260076020526040812060609190600101600a610f8d610f8886610c31565b61142f565b604051602001610f9f93929190613845565b6040516020818303038152906040529050610fb98161142f565b604051602001610fc991906138f7565b604051602081830303815290604052915050919050565b6006546001600160a01b0316331461100a5760405162461bcd60e51b81526004016106b090613604565b6110148282611581565b6040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b6006546001600160a01b031633146110755760405162461bcd60e51b81526004016106b090613604565b6110818484848461159c565b50505050565b6006546001600160a01b031633146110b15760405162461bcd60e51b81526004016106b090613604565b600680546001600160a01b0319166001600160a01b03831690811790915560405133907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b6006546001600160a01b031633146111275760405162461bcd60e51b81526004016106b090613604565b6009805460ff1916911515919091179055565b6060813b80611151576311052bb46000526004601cfd5b600181039050604051915061ffe0603f820116820160405280825260008160208401015280600160208401853c50919050565b600060606000604051806101000160405280856001600160401b038111156111ae576111ae6132d1565b6040519080825280601f01601f1916602001820160405280156111d8576020820181803683370190505b508152602001600081526020018681526020016000815260200160008152602001600081526020016040518060400160405280600f60016112199190613952565b6001600160401b03811115611230576112306132d1565b604051908082528060200260200182016040528015611259578160200160208202803683370190505b5081526040805161012080825261242082019092526020928301929091908201612400803683370190505081525081526020016040518060400160405280600f60016112a59190613952565b6001600160401b038111156112bc576112bc6132d1565b6040519080825280602002602001820160405280156112e5578160200160208202803683370190505b50815260408051601e8082526103e0820190925260209283019290919082016103c08036833750505090529052905060008080611321846116ab565b9050600081600e81111561133757611337613965565b1461134c579251929450919250611428915050565b8260000361141d5761135f846001611812565b93509050600081600e81111561137757611377613965565b1461138c579251929450919250611428915050565b611397846002611812565b92509050600081600e8111156113af576113af613965565b146113c4579251929450919250611428915050565b81156113f857816001146113ef57816002146113e1576003611401565b6113ea846118e2565b611401565b6113ea84611953565b61140184611968565b9050600081600e81111561141757611417613965565b1461134c575b925192945091925050505b9250929050565b6060815160000361144e57505060408051602081019091526000815290565b6000604051806060016040528060408152602001613a75604091399050600060038451600261147d9190613952565b6114879190613991565b6114929060046139a5565b6001600160401b038111156114a9576114a96132d1565b6040519080825280601f01601f1916602001820160405280156114d3576020820181803683370190505b509050600182016020820185865187015b8082101561153f576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506114e4565b505060038651066001811461155b576002811461156e57611576565b603d6001830353603d6002830353611576565b603d60018303535b509195945050505050565b6000828152600760205260409020600101610a74828261367a565b6000848152600860205260408120805463ffffffff191663ffffffff8416179055615dc09083908260016115d082856139bc565b6115da91906139e0565b6115e491906139fd565b905060005b8163ffffffff168163ffffffff1610156116a15760006116098583613a20565b9050600063ffffffff851661161e87846139bc565b63ffffffff16116116385761163386836139bc565b61163a565b845b60008b815260086020526040902090915060010161166261165d8b8b8686611b78565b611c50565b815460018082018455600093845260209093200180546001600160a01b0319166001600160a01b03929092169190911790559290920191506115e99050565b5050505050505050565b604080516101208082526124208201909252600091829182916020820161240080368337019050509050600091505b609082101561170d5760088183815181106116f7576116f7613739565b60209081029190910101526001909101906116da565b61010082101561174157600981838151811061172b5761172b613739565b602090810291909101015260019091019061170d565b61011882101561177557600781838151811061175f5761175f613739565b6020908102919091010152600190910190611741565b6101208210156117a957600881838151811061179357611793613739565b6020908102919091010152600190910190611775565b6117bc8460c00151826101206000611c99565b50600091505b601e8210156117f55760058183815181106117df576117df613739565b60209081029190910101526001909101906117c2565b6118078460e0015182601e6000611c99565b506000949350505050565b608082015160009081905b838560a0015110156118a55784604001515185606001510361184757600160009250925050611428565b60a085015160408601516060870180519061186182613a48565b90528151811061187357611873613739565b602001015160f81c60f81b60f81c60ff16901b8117905060088560a00181815161189d9190613952565b90525061181d565b80841c608086015260a0850180518591906118c1908390613a61565b90525060006118d3600180871b613a61565b60009792169550909350505050565b6000611901604051806040016040528060608152602001606081525090565b6040805180820190915260608082526020820152600061192085611f4c565b90945092509050600081600e81111561193b5761193b613965565b1461194857949350505050565b610cdf858484612603565b600061059a828360c001518460e00151612603565b60006080820181905260a082018190526040820151516060830151829190611991906004613952565b11156119a05750600192915050565b6040830151606084018051906119b582613a48565b9052815181106119c7576119c7613739565b0160200151604084015160608501805160f89390931c9350600892906119ec82613a48565b9052815181106119fe576119fe613739565b602001015160f81c60f81b60f81c60ff16901b81179050801960ff168360400151846060018051809190611a3190613a48565b905281518110611a4357611a43613739565b016020015160f81c141580611a8e5750604083015160608401805160ff841960081c169291611a7182613a48565b905281518110611a8357611a83613739565b016020015160f81c14155b15611a9c5750600492915050565b826040015151818460600151611ab29190613952565b1115611ac15750600192915050565b8251516020840151611ad4908390613952565b1115611ae35750600292915050565b8015611b6f57611af4600182613a61565b90508260400151836060018051809190611b0d90613a48565b905281518110611b1f57611b1f613739565b602001015160f81c60f81b8360000151846020018051809190611b4190613a48565b905281518110611b5357611b53613739565b60200101906001600160f81b031916908160001a905350611ae3565b50600092915050565b60606000611b8684846139e0565b63ffffffff166001600160401b03811115611ba357611ba36132d1565b6040519080825280601f01601f191660200182016040528015611bcd576020820181803683370190505b50905063ffffffff84165b8363ffffffff16811015611c4457868682818110611bf857611bf8613739565b9050013560f81c60f81b828663ffffffff1683611c159190613a61565b81518110611c2557611c25613739565b60200101906001600160f81b031916908160001a905350600101611bd8565b5090505b949350505050565b60008151600181018060401b6bfd61000080600a3d393df3001761ffff8211850152600a8101601585016000f092505081611c935763301164256000526004601cfd5b90915290565b600080600080611ca7613152565b600092505b600f8311611ce957600089600001518481518110611ccc57611ccc613739565b602090810291909101015282611ce181613a48565b935050611cac565b600093505b86841015611d4e57885188611d038689613952565b81518110611d1357611d13613739565b602002602001015181518110611d2b57611d2b613739565b602002602001018051809190611d4090613a48565b905250600190930192611cee565b868960000151600081518110611d6657611d66613739565b602002602001015103611d80576000945050505050611c48565b60019150600192505b600f8311611e03578851805160019390931b9284908110611dac57611dac613739565b6020026020010151821015611dc857600e945050505050611c48565b8851805184908110611ddc57611ddc613739565b602002602001015182611def9190613a61565b915082611dfb81613a48565b935050611d89565b60006020820152600192505b600f831015611e81578851805184908110611e2c57611e2c613739565b6020026020010151818460108110611e4657611e46613739565b6020020151611e559190613952565b81611e61856001613952565b60108110611e7157611e71613739565b6020020152600190920191611e0f565b600093505b86841015611f2d5787611e998588613952565b81518110611ea957611ea9613739565b6020026020010151600014611f225760208901518490828a611ecb848b613952565b81518110611edb57611edb613739565b602002602001015160108110611ef357611ef3613739565b60200201805190611f0382613a48565b905281518110611f1557611f15613739565b6020026020010181815250505b600190930192611e86565b60008211611f3c576000611f3f565b600e5b9998505050505050505050565b6000611f6b604051806040016040528060608152602001606081525090565b6040805180820190915260608082526020820152600080808080611f92601e61011e613952565b6001600160401b03811115611fa957611fa96132d1565b604051908082528060200260200182016040528015611fd2578160200160208202803683370190505b50905060006040518060400160405280600f6001611ff09190613952565b6001600160401b03811115612007576120076132d1565b604051908082528060200260200182016040528015612030578160200160208202803683370190505b5081526040805161011e8082526123e0820190925260209283019290919082016123c08036833701905050815250905060006040518060400160405280600f600161207b9190613952565b6001600160401b03811115612092576120926132d1565b6040519080825280602002602001820160405280156120bb578160200160208202803683370190505b50815260408051601e8082526103e0820190925260209283019290919082016103c0803683375050509052905060006120f58c6005611812565b98509450600085600e81111561210d5761210d613965565b14612125575092985096509094506125fc9350505050565b61213161010189613952565b975061213e8c6005611812565b97509450600085600e81111561215657612156613965565b1461216e575092985096509094506125fc9350505050565b612179600188613952565b965061011e88118061218b5750601e87115b156121a557506005995090975095506125fc945050505050565b6121ae8c612e2f565b9095509350600085600e8111156121c7576121c7613965565b146121df575092985096509094506125fc9350505050565b6121ed838560136000611c99565b9450600085600e81111561220357612203613965565b1461221d57506006995090975095506125fc945050505050565b600095505b61222c8789613952565b861015612427576000806122408e86613043565b9097509150600087600e81111561225957612259613965565b146122735750949a5091985096506125fc95505050505050565b60108210156122ab5781868961228881613a48565b9a508151811061229a5761229a613739565b602002602001018181525050612420565b600090508160100361234d57876000036122d7575060079b509299509097506125fc9650505050505050565b856122e360018a613a61565b815181106122f3576122f3613739565b602002602001015190506123088e6002611812565b9097509250600087600e81111561232157612321613965565b1461233b5750949a5091985096506125fc95505050505050565b612346836003613952565b91506123ac565b81601103612360576123088e6003611812565b61236b8e6007611812565b9097509250600087600e81111561238457612384613965565b1461239e5750949a5091985096506125fc95505050505050565b6123a983600b613952565b91505b6123b6898b613952565b6123c0838a613952565b11156123de575060089b509299509097506125fc9650505050505050565b8115612420576123ef600183613a61565b91508086896123fd81613a48565b9a508151811061240f5761240f613739565b6020026020010181815250506123de565b5050612222565b836101008151811061243b5761243b613739565b602002602001015160000361245f5750600b995090975095506125fc945050505050565b61246c83858a6000611c99565b9450600085600e81111561248257612482613965565b1415801561250c5750600185600e81111561249f5761249f613965565b14806124bc5750600285600e8111156124ba576124ba613965565b145b8061250c57508251805160019081106124d7576124d7613739565b602002602001015183600001516000815181106124f6576124f6613739565b60200260200101516125089190613952565b8814155b1561252657506009995090975095506125fc945050505050565b6125328285898b611c99565b9450600085600e81111561254857612548613965565b141580156125d25750600185600e81111561256557612565613965565b14806125825750600285600e81111561258057612580613965565b145b806125d2575081518051600190811061259d5761259d613739565b602002602001015182600001516000815181106125bc576125bc613739565b60200260200101516125ce9190613952565b8714155b156125ec5750600a995090975095506125fc945050505050565b5060009950909750955050505050505b9193909250565b6000806000806000604051806103a00160405280600361ffff168152602001600461ffff168152602001600561ffff168152602001600661ffff168152602001600761ffff168152602001600861ffff168152602001600961ffff168152602001600a61ffff168152602001600b61ffff168152602001600d61ffff168152602001600f61ffff168152602001601161ffff168152602001601361ffff168152602001601761ffff168152602001601b61ffff168152602001601f61ffff168152602001602361ffff168152602001602b61ffff168152602001603361ffff168152602001603b61ffff168152602001604361ffff168152602001605361ffff168152602001606361ffff168152602001607361ffff168152602001608361ffff16815260200160a361ffff16815260200160c361ffff16815260200160e361ffff16815260200161010261ffff1681525090506000604051806103a00160405280600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600160ff168152602001600160ff168152602001600160ff168152602001600160ff168152602001600260ff168152602001600260ff168152602001600260ff168152602001600260ff168152602001600360ff168152602001600360ff168152602001600360ff168152602001600360ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600560ff168152602001600560ff168152602001600560ff168152602001600560ff168152602001600060ff1681525090506000604051806103c00160405280600161ffff168152602001600261ffff168152602001600361ffff168152602001600461ffff168152602001600561ffff168152602001600761ffff168152602001600961ffff168152602001600d61ffff168152602001601161ffff168152602001601961ffff168152602001602161ffff168152602001603161ffff168152602001604161ffff168152602001606161ffff168152602001608161ffff16815260200160c161ffff16815260200161010161ffff16815260200161018161ffff16815260200161020161ffff16815260200161030161ffff16815260200161040161ffff16815260200161060161ffff16815260200161080161ffff168152602001610c0161ffff16815260200161100161ffff16815260200161180161ffff16815260200161200161ffff16815260200161300161ffff16815260200161400161ffff16815260200161600161ffff1681525090506000604051806103c00160405280600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600160ff168152602001600160ff168152602001600260ff168152602001600260ff168152602001600360ff168152602001600360ff168152602001600460ff168152602001600460ff168152602001600560ff168152602001600560ff168152602001600660ff168152602001600660ff168152602001600760ff168152602001600760ff168152602001600860ff168152602001600860ff168152602001600960ff168152602001600960ff168152602001600a60ff168152602001600a60ff168152602001600b60ff168152602001600b60ff168152602001600c60ff168152602001600c60ff168152602001600d60ff168152602001600d60ff16815250905060005b8761010014612e1b57612b3d8c8c613043565b98509050600081600e811115612b5557612b55613965565b14612b69579750612e289650505050505050565b610100881015612bde578b515160208d015103612b9157600298505050505050505050612e28565b8760f81b8c600001518d6020015181518110612baf57612baf613739565b60200101906001600160f81b031916908160001a90535060208c01805190612bd682613a48565b905250612b2a565b610100881115612e09576000612bf66101018a613a61565b9850601d8910612c1257600c9950505050505050505050612e28565b612c358d868b601d8110612c2857612c28613739565b602002015160ff16611812565b9092509050600082600e811115612c4e57612c4e613965565b14612c6357509750612e289650505050505050565b80868a601d8110612c7657612c76613739565b602002015161ffff16612c899190613952565b9750612c958d8c613043565b99509150600082600e811115612cad57612cad613965565b14612cc257509750612e289650505050505050565b612cd88d848b601e8110612c2857612c28613739565b9092509050600082600e811115612cf157612cf1613965565b14612d0657509750612e289650505050505050565b80848a601e8110612d1957612d19613739565b602002015161ffff16612d2c9190613952565b96508c60200151871115612d4c57600d9950505050505050505050612e28565b8c515160208e0151612d5f908a90613952565b1115612d775760029950505050505050505050612e28565b8715612e0357612d88600189613a61565b97508c60000151878e60200151612d9f9190613a61565b81518110612daf57612daf613739565b602001015160f81c60f81b8d600001518e6020015181518110612dd457612dd4613739565b60200101906001600160f81b031916908160001a90535060208d01805190612dfb82613a48565b905250612d77565b50612b2a565b868c602001818151612bd69190613952565b6000985050505050505050505b9392505050565b60006060818080612e43601e61011e613952565b6001600160401b03811115612e5a57612e5a6132d1565b604051908082528060200260200182016040528015612e83578160200160208202803683370190505b506040805161026081018252601081526011602082015260129181019190915260006060820181905260086080830152600760a0830152600960c0830152600660e0830152600a6101008301526005610120830152600b61014083015260046101608301819052600c61018084015260036101a0840152600d6101c084015260026101e0840152600e6102008401526001610220840152600f61024084015292935091612f31908990611812565b95509150600082600e811115612f4957612f49613965565b14612f5a5750969095509350505050565b612f65600486613952565b9450600093505b84841015612fe757612f7f886003611812565b84838760138110612f9257612f92613739565b602002015160ff1681518110612faa57612faa613739565b60209081029190910101529150600082600e811115612fcb57612fcb613965565b14612fdc5750969095509350505050565b600190930192612f6c565b60138410156130335760008382866013811061300557613005613739565b602002015160ff168151811061301d5761301d613739565b6020908102919091010152600190930192612fe7565b5060009791965090945050505050565b600080600181808080805b600f861161313f5760006130638b6001611812565b9092509050600082600e81111561307c5761307c613965565b146130935750965060009550611428945050505050565b8951805196821796889081106130ab576130ab613739565b6020026020010151935083856130c19190613952565b86101561310c5760208a01516000906130da8789613a61565b6130e49086613952565b815181106130f4576130f4613739565b60200260200101519850985050505050505050611428565b6131168484613952565b92506131228486613952565b600196871b961b945086905061313781613a48565b96505061304e565b50600c9960009950975050505050505050565b6040518061020001604052806010906020820280368337509192915050565b6001600160e01b031981168114610dd257600080fd5b60006020828403121561319957600080fd5b8135612e2881613171565b60005b838110156131bf5781810151838201526020016131a7565b50506000910152565b600081518084526131e08160208601602086016131a4565b601f01601f19169290920160200192915050565b602081526000612e2860208301846131c8565b60006020828403121561321957600080fd5b5035919050565b80356001600160a01b0381168114610b9357600080fd5b6000806040838503121561324a57600080fd5b61325383613220565b946020939093013593505050565b60008060006060848603121561327657600080fd5b61327f84613220565b925061328d60208501613220565b9150604084013590509250925092565b828152604060208201526000611c4860408301846131c8565b6000602082840312156132c857600080fd5b612e2882613220565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126132f857600080fd5b81356001600160401b0380821115613312576133126132d1565b604051601f8301601f19908116603f0116810190828211818310171561333a5761333a6132d1565b8160405283815286602085880101111561335357600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006020828403121561338557600080fd5b81356001600160401b0381111561339b57600080fd5b611c48848285016132e7565b80358015158114610b9357600080fd5b600080604083850312156133ca57600080fd5b6133d383613220565b91506133e1602084016133a7565b90509250929050565b600080604083850312156133fd57600080fd5b50508035926020909101359150565b60008083601f84011261341e57600080fd5b5081356001600160401b0381111561343557600080fd5b60208301915083602082850101111561142857600080fd5b60008060008060006080868803121561346557600080fd5b61346e86613220565b945061347c60208701613220565b93506040860135925060608601356001600160401b0381111561349e57600080fd5b6134aa8882890161340c565b969995985093965092949392505050565b600080604083850312156134ce57600080fd5b8235915060208301356001600160401b038111156134eb57600080fd5b6134f7858286016132e7565b9150509250929050565b6000806040838503121561351457600080fd5b61351d83613220565b91506133e160208401613220565b6000806000806060858703121561354157600080fd5b8435935060208501356001600160401b0381111561355e57600080fd5b61356a8782880161340c565b909450925050604085013563ffffffff8116811461358757600080fd5b939692955090935050565b6000602082840312156135a457600080fd5b612e28826133a7565b600181811c908216806135c157607f821691505b6020821081036135e157634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156135f957600080fd5b8151612e2881613171565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b601f821115610a74576000816000526020600020601f850160051c810160208610156136535750805b601f850160051c820191505b818110156136725782815560010161365f565b505050505050565b81516001600160401b03811115613693576136936132d1565b6136a7816136a184546135ad565b8461362a565b602080601f8311600181146136dc57600084156136c45750858301515b600019600386901b1c1916600185901b178555613672565b600085815260208120601f198616915b8281101561370b578886015182559484019460019091019084016136ec565b50858210156137295787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b600083516137618184602088016131a4565b8351908301906137758183602088016131a4565b01949350505050565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b600081546137df816135ad565b600182811680156137f7576001811461380c5761383b565b60ff198416875282151583028701945061383b565b8560005260208060002060005b858110156138325781548a820152908401908201613819565b50505082870194505b5050505092915050565b607b60f81b815268113730b6b2911d101160b91b6001820152600061386d600a8301866137d2565b72111610113232b9b1b934b83a34b7b7111d101160691b815261389360138201866137d2565b90507f222c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b81526618985cd94d8d0b60ca1b602082015283516138db8160278401602088016131a4565b61227d60f01b6027929091019182015260290195945050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161392f81601d8501602087016131a4565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561059a5761059a61393c565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6000826139a0576139a061397b565b500490565b808202811582820484141761059a5761059a61393c565b63ffffffff8181168382160190808211156139d9576139d961393c565b5092915050565b63ffffffff8281168282160390808211156139d9576139d961393c565b600063ffffffff80841680613a1457613a1461397b565b92169190910492915050565b63ffffffff818116838216028082169190828114613a4057613a4061393c565b505092915050565b600060018201613a5a57613a5a61393c565b5060010190565b8181038181111561059a5761059a61393c56fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122072f1a3c52ebb498bf1d46b4ce3a11cb431f9df9739096688f3f34adc6cdba32864736f6c634300081700334f6e2d636861696e20766563746f72206772617068696373206279204172656120546563686e6f6c6f67792e

Deployed Bytecode

0x6080604052600436106101815760003560e01c806390c3f38f116100d1578063b88d4fde1161008a578063e985e9c511610064578063e985e9c5146104b3578063ed5fd146146104ee578063f2fde38b1461050e578063f8004d311461052e57600080fd5b8063b88d4fde14610453578063c87b56dd14610473578063d609b5e11461049357600080fd5b806390c3f38f146103ab57806390f5368a146103cb57806395d89b41146103eb578063a0712d6814610400578063a22cb46514610413578063af5878901461043357600080fd5b806329b3264f1161013e5780635ca21123116101185780635ca21123146102f55780636352211e1461033d57806370a082311461035d5780638da5cb5b1461038b57600080fd5b806329b3264f1461028757806342842e0e146102b557806351cff8d9146102d557600080fd5b806301ffc9a71461018657806306fdde03146101bb578063081812fc146101dd578063088b69431461022b578063095ea7b31461024557806323b872dd14610267575b600080fd5b34801561019257600080fd5b506101a66101a1366004613187565b61054e565b60405190151581526020015b60405180910390f35b3480156101c757600080fd5b506101d06105a0565b6040516101b291906131f4565b3480156101e957600080fd5b506102136101f8366004613207565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016101b2565b34801561023757600080fd5b506009546101a69060ff1681565b34801561025157600080fd5b50610265610260366004613237565b61062e565b005b34801561027357600080fd5b50610265610282366004613261565b610715565b34801561029357600080fd5b506102a76102a2366004613207565b6108dc565b6040516101b292919061329d565b3480156102c157600080fd5b506102656102d0366004613261565b610981565b3480156102e157600080fd5b506102656102f03660046132b6565b610a79565b34801561030157600080fd5b50610328610310366004613207565b60086020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016101b2565b34801561034957600080fd5b50610213610358366004613207565b610b41565b34801561036957600080fd5b5061037d6103783660046132b6565b610b98565b6040519081526020016101b2565b34801561039757600080fd5b50600654610213906001600160a01b031681565b3480156103b757600080fd5b506102656103c6366004613373565b610bfb565b3480156103d757600080fd5b506101d06103e6366004613207565b610c31565b3480156103f757600080fd5b506101d0610ce8565b61026561040e366004613207565b610cf5565b34801561041f57600080fd5b5061026561042e3660046133b7565b610dd5565b34801561043f57600080fd5b5061026561044e3660046133ea565b610e41565b34801561045f57600080fd5b5061026561046e36600461344d565b610e7d565b34801561047f57600080fd5b506101d061048e366004613207565b610f65565b34801561049f57600080fd5b506102656104ae3660046134bb565b610fe0565b3480156104bf57600080fd5b506101a66104ce366004613501565b600560209081526000928352604080842090915290825290205460ff1681565b3480156104fa57600080fd5b5061026561050936600461352b565b61104b565b34801561051a57600080fd5b506102656105293660046132b6565b611087565b34801561053a57600080fd5b50610265610549366004613592565b6110fd565b60006301ffc9a760e01b6001600160e01b03198316148061057f57506380ac58cd60e01b6001600160e01b03198316145b8061059a5750635b5e139f60e01b6001600160e01b03198316145b92915050565b600080546105ad906135ad565b80601f01602080910402602001604051908101604052809291908181526020018280546105d9906135ad565b80156106265780601f106105fb57610100808354040283529160200191610626565b820191906000526020600020905b81548152906001019060200180831161060957829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b03163381148061067757506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6106b95760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064015b60405180910390fd5b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000818152600260205260409020546001600160a01b0384811691161461076b5760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b60448201526064016106b0565b6001600160a01b0382166107b55760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b60448201526064016106b0565b336001600160a01b03841614806107ef57506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b8061081057506000818152600460205260409020546001600160a01b031633145b61084d5760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016106b0565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600760205260009081526040902080546001820180549192916108fe906135ad565b80601f016020809104026020016040519081016040528092919081815260200182805461092a906135ad565b80156109775780601f1061094c57610100808354040283529160200191610977565b820191906000526020600020905b81548152906001019060200180831161095a57829003601f168201915b5050505050905082565b61098c838383610715565b6001600160a01b0382163b1580610a355750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610a05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2991906135e7565b6001600160e01b031916145b610a745760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016106b0565b505050565b6006546001600160a01b03163314610aa35760405162461bcd60e51b81526004016106b090613604565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b3d5760405162461bcd60e51b8152602060048201526014602482015273161591ce881dda5d1a191c985dc819985a5b195960621b60448201526064016106b0565b5050565b6000818152600260205260409020546001600160a01b031680610b935760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b60448201526064016106b0565b919050565b60006001600160a01b038216610bdf5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b60448201526064016106b0565b506001600160a01b031660009081526003602052604090205490565b6006546001600160a01b03163314610c255760405162461bcd60e51b81526004016106b090613604565b600a610b3d828261367a565b60608060005b600084815260086020526040902060010154811015610cbe57600084815260086020526040902060010180548391610c939184908110610c7957610c79613739565b6000918252602090912001546001600160a01b031661113a565b604051602001610ca492919061374f565b60408051601f198184030181529190529150600101610c37565b50600083815260086020526040812054610cdf90839063ffffffff16611184565b95945050505050565b600180546105ad906135ad565b60095460ff16610d185760405163951b974f60e01b815260040160405180910390fd5b6000818152600760205260408120549003610d465760405163951b974f60e01b815260040160405180910390fd5b6000818152600760205260409020543414610d745760405163d5e6876b60e01b815260040160405180910390fd5b30610d7e82610b41565b6001600160a01b031614610da557604051631bbdf5c560e31b815260040160405180910390fd5b600081815260046020526040902080546001600160a01b03191633908117909155610dd290309083610715565b50565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6006546001600160a01b03163314610e6b5760405162461bcd60e51b81526004016106b090613604565b60009182526007602052604090912055565b610e88858585610715565b6001600160a01b0384163b1580610f1f5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290610ed09033908a9089908990899060040161377e565b6020604051808303816000875af1158015610eef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1391906135e7565b6001600160e01b031916145b610f5e5760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016106b0565b5050505050565b600081815260076020526040812060609190600101600a610f8d610f8886610c31565b61142f565b604051602001610f9f93929190613845565b6040516020818303038152906040529050610fb98161142f565b604051602001610fc991906138f7565b604051602081830303815290604052915050919050565b6006546001600160a01b0316331461100a5760405162461bcd60e51b81526004016106b090613604565b6110148282611581565b6040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b6006546001600160a01b031633146110755760405162461bcd60e51b81526004016106b090613604565b6110818484848461159c565b50505050565b6006546001600160a01b031633146110b15760405162461bcd60e51b81526004016106b090613604565b600680546001600160a01b0319166001600160a01b03831690811790915560405133907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b6006546001600160a01b031633146111275760405162461bcd60e51b81526004016106b090613604565b6009805460ff1916911515919091179055565b6060813b80611151576311052bb46000526004601cfd5b600181039050604051915061ffe0603f820116820160405280825260008160208401015280600160208401853c50919050565b600060606000604051806101000160405280856001600160401b038111156111ae576111ae6132d1565b6040519080825280601f01601f1916602001820160405280156111d8576020820181803683370190505b508152602001600081526020018681526020016000815260200160008152602001600081526020016040518060400160405280600f60016112199190613952565b6001600160401b03811115611230576112306132d1565b604051908082528060200260200182016040528015611259578160200160208202803683370190505b5081526040805161012080825261242082019092526020928301929091908201612400803683370190505081525081526020016040518060400160405280600f60016112a59190613952565b6001600160401b038111156112bc576112bc6132d1565b6040519080825280602002602001820160405280156112e5578160200160208202803683370190505b50815260408051601e8082526103e0820190925260209283019290919082016103c08036833750505090529052905060008080611321846116ab565b9050600081600e81111561133757611337613965565b1461134c579251929450919250611428915050565b8260000361141d5761135f846001611812565b93509050600081600e81111561137757611377613965565b1461138c579251929450919250611428915050565b611397846002611812565b92509050600081600e8111156113af576113af613965565b146113c4579251929450919250611428915050565b81156113f857816001146113ef57816002146113e1576003611401565b6113ea846118e2565b611401565b6113ea84611953565b61140184611968565b9050600081600e81111561141757611417613965565b1461134c575b925192945091925050505b9250929050565b6060815160000361144e57505060408051602081019091526000815290565b6000604051806060016040528060408152602001613a75604091399050600060038451600261147d9190613952565b6114879190613991565b6114929060046139a5565b6001600160401b038111156114a9576114a96132d1565b6040519080825280601f01601f1916602001820160405280156114d3576020820181803683370190505b509050600182016020820185865187015b8082101561153f576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506114e4565b505060038651066001811461155b576002811461156e57611576565b603d6001830353603d6002830353611576565b603d60018303535b509195945050505050565b6000828152600760205260409020600101610a74828261367a565b6000848152600860205260408120805463ffffffff191663ffffffff8416179055615dc09083908260016115d082856139bc565b6115da91906139e0565b6115e491906139fd565b905060005b8163ffffffff168163ffffffff1610156116a15760006116098583613a20565b9050600063ffffffff851661161e87846139bc565b63ffffffff16116116385761163386836139bc565b61163a565b845b60008b815260086020526040902090915060010161166261165d8b8b8686611b78565b611c50565b815460018082018455600093845260209093200180546001600160a01b0319166001600160a01b03929092169190911790559290920191506115e99050565b5050505050505050565b604080516101208082526124208201909252600091829182916020820161240080368337019050509050600091505b609082101561170d5760088183815181106116f7576116f7613739565b60209081029190910101526001909101906116da565b61010082101561174157600981838151811061172b5761172b613739565b602090810291909101015260019091019061170d565b61011882101561177557600781838151811061175f5761175f613739565b6020908102919091010152600190910190611741565b6101208210156117a957600881838151811061179357611793613739565b6020908102919091010152600190910190611775565b6117bc8460c00151826101206000611c99565b50600091505b601e8210156117f55760058183815181106117df576117df613739565b60209081029190910101526001909101906117c2565b6118078460e0015182601e6000611c99565b506000949350505050565b608082015160009081905b838560a0015110156118a55784604001515185606001510361184757600160009250925050611428565b60a085015160408601516060870180519061186182613a48565b90528151811061187357611873613739565b602001015160f81c60f81b60f81c60ff16901b8117905060088560a00181815161189d9190613952565b90525061181d565b80841c608086015260a0850180518591906118c1908390613a61565b90525060006118d3600180871b613a61565b60009792169550909350505050565b6000611901604051806040016040528060608152602001606081525090565b6040805180820190915260608082526020820152600061192085611f4c565b90945092509050600081600e81111561193b5761193b613965565b1461194857949350505050565b610cdf858484612603565b600061059a828360c001518460e00151612603565b60006080820181905260a082018190526040820151516060830151829190611991906004613952565b11156119a05750600192915050565b6040830151606084018051906119b582613a48565b9052815181106119c7576119c7613739565b0160200151604084015160608501805160f89390931c9350600892906119ec82613a48565b9052815181106119fe576119fe613739565b602001015160f81c60f81b60f81c60ff16901b81179050801960ff168360400151846060018051809190611a3190613a48565b905281518110611a4357611a43613739565b016020015160f81c141580611a8e5750604083015160608401805160ff841960081c169291611a7182613a48565b905281518110611a8357611a83613739565b016020015160f81c14155b15611a9c5750600492915050565b826040015151818460600151611ab29190613952565b1115611ac15750600192915050565b8251516020840151611ad4908390613952565b1115611ae35750600292915050565b8015611b6f57611af4600182613a61565b90508260400151836060018051809190611b0d90613a48565b905281518110611b1f57611b1f613739565b602001015160f81c60f81b8360000151846020018051809190611b4190613a48565b905281518110611b5357611b53613739565b60200101906001600160f81b031916908160001a905350611ae3565b50600092915050565b60606000611b8684846139e0565b63ffffffff166001600160401b03811115611ba357611ba36132d1565b6040519080825280601f01601f191660200182016040528015611bcd576020820181803683370190505b50905063ffffffff84165b8363ffffffff16811015611c4457868682818110611bf857611bf8613739565b9050013560f81c60f81b828663ffffffff1683611c159190613a61565b81518110611c2557611c25613739565b60200101906001600160f81b031916908160001a905350600101611bd8565b5090505b949350505050565b60008151600181018060401b6bfd61000080600a3d393df3001761ffff8211850152600a8101601585016000f092505081611c935763301164256000526004601cfd5b90915290565b600080600080611ca7613152565b600092505b600f8311611ce957600089600001518481518110611ccc57611ccc613739565b602090810291909101015282611ce181613a48565b935050611cac565b600093505b86841015611d4e57885188611d038689613952565b81518110611d1357611d13613739565b602002602001015181518110611d2b57611d2b613739565b602002602001018051809190611d4090613a48565b905250600190930192611cee565b868960000151600081518110611d6657611d66613739565b602002602001015103611d80576000945050505050611c48565b60019150600192505b600f8311611e03578851805160019390931b9284908110611dac57611dac613739565b6020026020010151821015611dc857600e945050505050611c48565b8851805184908110611ddc57611ddc613739565b602002602001015182611def9190613a61565b915082611dfb81613a48565b935050611d89565b60006020820152600192505b600f831015611e81578851805184908110611e2c57611e2c613739565b6020026020010151818460108110611e4657611e46613739565b6020020151611e559190613952565b81611e61856001613952565b60108110611e7157611e71613739565b6020020152600190920191611e0f565b600093505b86841015611f2d5787611e998588613952565b81518110611ea957611ea9613739565b6020026020010151600014611f225760208901518490828a611ecb848b613952565b81518110611edb57611edb613739565b602002602001015160108110611ef357611ef3613739565b60200201805190611f0382613a48565b905281518110611f1557611f15613739565b6020026020010181815250505b600190930192611e86565b60008211611f3c576000611f3f565b600e5b9998505050505050505050565b6000611f6b604051806040016040528060608152602001606081525090565b6040805180820190915260608082526020820152600080808080611f92601e61011e613952565b6001600160401b03811115611fa957611fa96132d1565b604051908082528060200260200182016040528015611fd2578160200160208202803683370190505b50905060006040518060400160405280600f6001611ff09190613952565b6001600160401b03811115612007576120076132d1565b604051908082528060200260200182016040528015612030578160200160208202803683370190505b5081526040805161011e8082526123e0820190925260209283019290919082016123c08036833701905050815250905060006040518060400160405280600f600161207b9190613952565b6001600160401b03811115612092576120926132d1565b6040519080825280602002602001820160405280156120bb578160200160208202803683370190505b50815260408051601e8082526103e0820190925260209283019290919082016103c0803683375050509052905060006120f58c6005611812565b98509450600085600e81111561210d5761210d613965565b14612125575092985096509094506125fc9350505050565b61213161010189613952565b975061213e8c6005611812565b97509450600085600e81111561215657612156613965565b1461216e575092985096509094506125fc9350505050565b612179600188613952565b965061011e88118061218b5750601e87115b156121a557506005995090975095506125fc945050505050565b6121ae8c612e2f565b9095509350600085600e8111156121c7576121c7613965565b146121df575092985096509094506125fc9350505050565b6121ed838560136000611c99565b9450600085600e81111561220357612203613965565b1461221d57506006995090975095506125fc945050505050565b600095505b61222c8789613952565b861015612427576000806122408e86613043565b9097509150600087600e81111561225957612259613965565b146122735750949a5091985096506125fc95505050505050565b60108210156122ab5781868961228881613a48565b9a508151811061229a5761229a613739565b602002602001018181525050612420565b600090508160100361234d57876000036122d7575060079b509299509097506125fc9650505050505050565b856122e360018a613a61565b815181106122f3576122f3613739565b602002602001015190506123088e6002611812565b9097509250600087600e81111561232157612321613965565b1461233b5750949a5091985096506125fc95505050505050565b612346836003613952565b91506123ac565b81601103612360576123088e6003611812565b61236b8e6007611812565b9097509250600087600e81111561238457612384613965565b1461239e5750949a5091985096506125fc95505050505050565b6123a983600b613952565b91505b6123b6898b613952565b6123c0838a613952565b11156123de575060089b509299509097506125fc9650505050505050565b8115612420576123ef600183613a61565b91508086896123fd81613a48565b9a508151811061240f5761240f613739565b6020026020010181815250506123de565b5050612222565b836101008151811061243b5761243b613739565b602002602001015160000361245f5750600b995090975095506125fc945050505050565b61246c83858a6000611c99565b9450600085600e81111561248257612482613965565b1415801561250c5750600185600e81111561249f5761249f613965565b14806124bc5750600285600e8111156124ba576124ba613965565b145b8061250c57508251805160019081106124d7576124d7613739565b602002602001015183600001516000815181106124f6576124f6613739565b60200260200101516125089190613952565b8814155b1561252657506009995090975095506125fc945050505050565b6125328285898b611c99565b9450600085600e81111561254857612548613965565b141580156125d25750600185600e81111561256557612565613965565b14806125825750600285600e81111561258057612580613965565b145b806125d2575081518051600190811061259d5761259d613739565b602002602001015182600001516000815181106125bc576125bc613739565b60200260200101516125ce9190613952565b8714155b156125ec5750600a995090975095506125fc945050505050565b5060009950909750955050505050505b9193909250565b6000806000806000604051806103a00160405280600361ffff168152602001600461ffff168152602001600561ffff168152602001600661ffff168152602001600761ffff168152602001600861ffff168152602001600961ffff168152602001600a61ffff168152602001600b61ffff168152602001600d61ffff168152602001600f61ffff168152602001601161ffff168152602001601361ffff168152602001601761ffff168152602001601b61ffff168152602001601f61ffff168152602001602361ffff168152602001602b61ffff168152602001603361ffff168152602001603b61ffff168152602001604361ffff168152602001605361ffff168152602001606361ffff168152602001607361ffff168152602001608361ffff16815260200160a361ffff16815260200160c361ffff16815260200160e361ffff16815260200161010261ffff1681525090506000604051806103a00160405280600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600160ff168152602001600160ff168152602001600160ff168152602001600160ff168152602001600260ff168152602001600260ff168152602001600260ff168152602001600260ff168152602001600360ff168152602001600360ff168152602001600360ff168152602001600360ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600560ff168152602001600560ff168152602001600560ff168152602001600560ff168152602001600060ff1681525090506000604051806103c00160405280600161ffff168152602001600261ffff168152602001600361ffff168152602001600461ffff168152602001600561ffff168152602001600761ffff168152602001600961ffff168152602001600d61ffff168152602001601161ffff168152602001601961ffff168152602001602161ffff168152602001603161ffff168152602001604161ffff168152602001606161ffff168152602001608161ffff16815260200160c161ffff16815260200161010161ffff16815260200161018161ffff16815260200161020161ffff16815260200161030161ffff16815260200161040161ffff16815260200161060161ffff16815260200161080161ffff168152602001610c0161ffff16815260200161100161ffff16815260200161180161ffff16815260200161200161ffff16815260200161300161ffff16815260200161400161ffff16815260200161600161ffff1681525090506000604051806103c00160405280600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600160ff168152602001600160ff168152602001600260ff168152602001600260ff168152602001600360ff168152602001600360ff168152602001600460ff168152602001600460ff168152602001600560ff168152602001600560ff168152602001600660ff168152602001600660ff168152602001600760ff168152602001600760ff168152602001600860ff168152602001600860ff168152602001600960ff168152602001600960ff168152602001600a60ff168152602001600a60ff168152602001600b60ff168152602001600b60ff168152602001600c60ff168152602001600c60ff168152602001600d60ff168152602001600d60ff16815250905060005b8761010014612e1b57612b3d8c8c613043565b98509050600081600e811115612b5557612b55613965565b14612b69579750612e289650505050505050565b610100881015612bde578b515160208d015103612b9157600298505050505050505050612e28565b8760f81b8c600001518d6020015181518110612baf57612baf613739565b60200101906001600160f81b031916908160001a90535060208c01805190612bd682613a48565b905250612b2a565b610100881115612e09576000612bf66101018a613a61565b9850601d8910612c1257600c9950505050505050505050612e28565b612c358d868b601d8110612c2857612c28613739565b602002015160ff16611812565b9092509050600082600e811115612c4e57612c4e613965565b14612c6357509750612e289650505050505050565b80868a601d8110612c7657612c76613739565b602002015161ffff16612c899190613952565b9750612c958d8c613043565b99509150600082600e811115612cad57612cad613965565b14612cc257509750612e289650505050505050565b612cd88d848b601e8110612c2857612c28613739565b9092509050600082600e811115612cf157612cf1613965565b14612d0657509750612e289650505050505050565b80848a601e8110612d1957612d19613739565b602002015161ffff16612d2c9190613952565b96508c60200151871115612d4c57600d9950505050505050505050612e28565b8c515160208e0151612d5f908a90613952565b1115612d775760029950505050505050505050612e28565b8715612e0357612d88600189613a61565b97508c60000151878e60200151612d9f9190613a61565b81518110612daf57612daf613739565b602001015160f81c60f81b8d600001518e6020015181518110612dd457612dd4613739565b60200101906001600160f81b031916908160001a90535060208d01805190612dfb82613a48565b905250612d77565b50612b2a565b868c602001818151612bd69190613952565b6000985050505050505050505b9392505050565b60006060818080612e43601e61011e613952565b6001600160401b03811115612e5a57612e5a6132d1565b604051908082528060200260200182016040528015612e83578160200160208202803683370190505b506040805161026081018252601081526011602082015260129181019190915260006060820181905260086080830152600760a0830152600960c0830152600660e0830152600a6101008301526005610120830152600b61014083015260046101608301819052600c61018084015260036101a0840152600d6101c084015260026101e0840152600e6102008401526001610220840152600f61024084015292935091612f31908990611812565b95509150600082600e811115612f4957612f49613965565b14612f5a5750969095509350505050565b612f65600486613952565b9450600093505b84841015612fe757612f7f886003611812565b84838760138110612f9257612f92613739565b602002015160ff1681518110612faa57612faa613739565b60209081029190910101529150600082600e811115612fcb57612fcb613965565b14612fdc5750969095509350505050565b600190930192612f6c565b60138410156130335760008382866013811061300557613005613739565b602002015160ff168151811061301d5761301d613739565b6020908102919091010152600190930192612fe7565b5060009791965090945050505050565b600080600181808080805b600f861161313f5760006130638b6001611812565b9092509050600082600e81111561307c5761307c613965565b146130935750965060009550611428945050505050565b8951805196821796889081106130ab576130ab613739565b6020026020010151935083856130c19190613952565b86101561310c5760208a01516000906130da8789613a61565b6130e49086613952565b815181106130f4576130f4613739565b60200260200101519850985050505050505050611428565b6131168484613952565b92506131228486613952565b600196871b961b945086905061313781613a48565b96505061304e565b50600c9960009950975050505050505050565b6040518061020001604052806010906020820280368337509192915050565b6001600160e01b031981168114610dd257600080fd5b60006020828403121561319957600080fd5b8135612e2881613171565b60005b838110156131bf5781810151838201526020016131a7565b50506000910152565b600081518084526131e08160208601602086016131a4565b601f01601f19169290920160200192915050565b602081526000612e2860208301846131c8565b60006020828403121561321957600080fd5b5035919050565b80356001600160a01b0381168114610b9357600080fd5b6000806040838503121561324a57600080fd5b61325383613220565b946020939093013593505050565b60008060006060848603121561327657600080fd5b61327f84613220565b925061328d60208501613220565b9150604084013590509250925092565b828152604060208201526000611c4860408301846131c8565b6000602082840312156132c857600080fd5b612e2882613220565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126132f857600080fd5b81356001600160401b0380821115613312576133126132d1565b604051601f8301601f19908116603f0116810190828211818310171561333a5761333a6132d1565b8160405283815286602085880101111561335357600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006020828403121561338557600080fd5b81356001600160401b0381111561339b57600080fd5b611c48848285016132e7565b80358015158114610b9357600080fd5b600080604083850312156133ca57600080fd5b6133d383613220565b91506133e1602084016133a7565b90509250929050565b600080604083850312156133fd57600080fd5b50508035926020909101359150565b60008083601f84011261341e57600080fd5b5081356001600160401b0381111561343557600080fd5b60208301915083602082850101111561142857600080fd5b60008060008060006080868803121561346557600080fd5b61346e86613220565b945061347c60208701613220565b93506040860135925060608601356001600160401b0381111561349e57600080fd5b6134aa8882890161340c565b969995985093965092949392505050565b600080604083850312156134ce57600080fd5b8235915060208301356001600160401b038111156134eb57600080fd5b6134f7858286016132e7565b9150509250929050565b6000806040838503121561351457600080fd5b61351d83613220565b91506133e160208401613220565b6000806000806060858703121561354157600080fd5b8435935060208501356001600160401b0381111561355e57600080fd5b61356a8782880161340c565b909450925050604085013563ffffffff8116811461358757600080fd5b939692955090935050565b6000602082840312156135a457600080fd5b612e28826133a7565b600181811c908216806135c157607f821691505b6020821081036135e157634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156135f957600080fd5b8151612e2881613171565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b601f821115610a74576000816000526020600020601f850160051c810160208610156136535750805b601f850160051c820191505b818110156136725782815560010161365f565b505050505050565b81516001600160401b03811115613693576136936132d1565b6136a7816136a184546135ad565b8461362a565b602080601f8311600181146136dc57600084156136c45750858301515b600019600386901b1c1916600185901b178555613672565b600085815260208120601f198616915b8281101561370b578886015182559484019460019091019084016136ec565b50858210156137295787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b600083516137618184602088016131a4565b8351908301906137758183602088016131a4565b01949350505050565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b600081546137df816135ad565b600182811680156137f7576001811461380c5761383b565b60ff198416875282151583028701945061383b565b8560005260208060002060005b858110156138325781548a820152908401908201613819565b50505082870194505b5050505092915050565b607b60f81b815268113730b6b2911d101160b91b6001820152600061386d600a8301866137d2565b72111610113232b9b1b934b83a34b7b7111d101160691b815261389360138201866137d2565b90507f222c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b81526618985cd94d8d0b60ca1b602082015283516138db8160278401602088016131a4565b61227d60f01b6027929091019182015260290195945050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161392f81601d8501602087016131a4565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561059a5761059a61393c565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6000826139a0576139a061397b565b500490565b808202811582820484141761059a5761059a61393c565b63ffffffff8181168382160190808211156139d9576139d961393c565b5092915050565b63ffffffff8281168282160390808211156139d9576139d961393c565b600063ffffffff80841680613a1457613a1461397b565b92169190910492915050565b63ffffffff818116838216028082169190828114613a4057613a4061393c565b505092915050565b600060018201613a5a57613a5a61393c565b5060010190565b8181038181111561059a5761059a61393c56fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122072f1a3c52ebb498bf1d46b4ce3a11cb431f9df9739096688f3f34adc6cdba32864736f6c63430008170033

[ Download: CSV Export  ]
[ Download: CSV Export  ]

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