ETH Price: $3,522.62 (+2.97%)
Gas: 5 Gwei

Token

HexAnons (HEXA)
 

Overview

Max Total Supply

102 HEXA

Holders

94

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
mongoon.eth
Balance
1 HEXA
0x5b5b71687e7cb013ae35ac9928dbd5393ea36c63
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
HexAnons

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 9 : HexAnons.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "solmate/tokens/ERC721.sol";
import "solmate/utils/LibString.sol";
import "openzeppelin-contracts/utils/cryptography/MerkleProof.sol";
import "openzeppelin-contracts/access/Ownable.sol";
import "./AnonymiceLibrary.sol";
import "./HexAnonsGenerator.sol";
import "./HexAnonsErrors.sol";

contract HexAnons is HexAnonsErrors, ERC721, Ownable {
    using LibString for uint256;

    uint256 public constant MAX_SUPPLY = 256;
    uint256 public constant PRIORITY_MINT_START = 1679779800;
    uint256 public constant HOLDERS_MINT_START = PRIORITY_MINT_START + 24 hours;
    bytes32 constant PRIORITY_MINT_ROOT =
        0xef0d1359754f96f615b555cc0dc1c50ada628537f90689db0afa9a5276c04ebe;

    bytes32 constant HOLDERS_MINT_ROOT =
        0x7e0744664f3126f12a8a1888ab265ddd02d7ccc68d315e54b6df080a44067ed9;

    address constant toadAddress = 0xE4260Df86f5261A41D19c2066f1Eb2Eb4F009e84;
    address constant irrevAddress = 0x4533d1F65906368ebfd61259dAee561DF3f3559D;
    address constant circolorsAddress = 0x888f8AA938dbb18b28bdD111fa4A0D3B8e10C871;

    uint256 public totalSupply;

    string[] ogCols;

    mapping(address => bool) addressMinted;
    mapping(uint256 => TokenInfo) tokenIdToTokenInfo;
    bool teamMinted;

    HexAnonsGenerator hexAnonsGenerator;


    modifier paintYourOwn(uint256 _tokenId) {
        if (msg.sender != ownerOf(_tokenId)) revert PaintYourOwn();
        _;
    }

    constructor() ERC721("HexAnons", "HEXA") {
        hexAnonsGenerator = new HexAnonsGenerator();
        ogCols = ["FFFFFF"];
    }

    /**
     * @param _a The address to be used within the hash.
     * @param _tokenId, the tokenId the hash is for
     */
    function hashPattern(
        address _a,
        uint256 _tokenId
    ) internal view returns (TokenInfo memory) {
        uint32 _hash = uint32(
            uint256(
                keccak256(
                    abi.encodePacked(
                        block.timestamp,
                        block.difficulty,
                        _a,
                        _tokenId
                    )
                )
            )
        );

        uint8 _pattern = uint8(
            uint256(keccak256(abi.encodePacked(_a, _tokenId))) % 20 + 1
        );

        string[] memory cols;

        return TokenInfo(_pattern, _hash, cols);
    }

    function priorityMint(
        bytes32[] calldata merkleProof
    ) external payable {
        if (addressMinted[msg.sender]) revert AddressMinted();
        if (block.timestamp < PRIORITY_MINT_START) revert NotOpen();

        bytes32 node = keccak256(abi.encodePacked(msg.sender));

        if (!MerkleProof.verify(merkleProof, PRIORITY_MINT_ROOT, node))
            revert NotAllowlisted();

        addressMinted[msg.sender] = true;

        mintInternal(msg.sender);
    }

        function holdersMint(
        bytes32[] calldata merkleProof
    ) external payable {
        if (addressMinted[msg.sender]) revert AddressMinted();
        if (block.timestamp < HOLDERS_MINT_START) revert NotOpen();

        bytes32 node = keccak256(abi.encodePacked(msg.sender));

        if (!MerkleProof.verify(merkleProof, HOLDERS_MINT_ROOT, node))
            revert NotAllowlisted();

        addressMinted[msg.sender] = true;

        mintInternal(msg.sender);
    }

    function teamMint() external onlyOwner {
        if (teamMinted) revert TeamMinted();

        for (uint256 i; i < 5; ++i) {
            mintInternal(toadAddress);
        }
        for (uint256 i; i < 3; ++i) {
            mintInternal(irrevAddress);
        }
                for (uint256 i; i < 2; ++i) {
            mintInternal(circolorsAddress);
        }
    }

    function mintInternal(address _to) internal {
        if (totalSupply >= MAX_SUPPLY) revert SoldOut();
        uint256 nextTokenId = totalSupply;

        tokenIdToTokenInfo[nextTokenId] = hashPattern(_to, nextTokenId);
        ++totalSupply;

        _mint(_to, nextTokenId);
    }

    // Views

    function getTokenInfo(
        uint256 _tokenId
    ) external view returns (TokenInfo memory) {
        TokenInfo memory _info = tokenIdToTokenInfo[_tokenId];
        if (_info.cols.length == 0) {
            _info.cols = ogCols;
        }
        return _info;
    }

    function lickOfPaint(
        uint256 _tokenId,
        string[] memory _cols
    ) external paintYourOwn(_tokenId) {
        tokenIdToTokenInfo[_tokenId].cols = _cols;
    }

    function scrubPaint(uint256 _tokenId) external paintYourOwn(_tokenId) {
        string[] memory wipeCols;
        tokenIdToTokenInfo[_tokenId].cols = wipeCols;
    }

    function trialPaintJob(
        uint256 _tokenId,
        string[] memory _cols
    ) external view returns (string memory) {
        // FIXME: there are no tests for this
        if (_tokenId >= totalSupply) revert NonExistantId();
        TokenInfo memory _info = tokenIdToTokenInfo[_tokenId];
        _info.cols = _cols;
        return hexAnonsGenerator.buildSVG(_info);
    }

    function tokenURI(
        uint256 _tokenId
    ) public view override returns (string memory _URI) {
        if (_tokenId >= totalSupply) revert NonExistantId();
        TokenInfo memory _info = tokenIdToTokenInfo[_tokenId];
        if (_info.cols.length == 0) {
            _info.cols = ogCols;
        }
        return hexAnonsGenerator.buildToken(_tokenId, _info);
    }
}

File 2 of 9 : 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 9 : LibString.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @notice Efficient library for creating string representations of integers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)
/// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/LibString.sol)
library LibString {
    function toString(int256 value) internal pure returns (string memory str) {
        if (value >= 0) return toString(uint256(value));

        unchecked {
            str = toString(uint256(-value));

            /// @solidity memory-safe-assembly
            assembly {
                // Note: This is only safe because we over-allocate memory
                // and write the string from right to left in toString(uint256),
                // and thus can be sure that sub(str, 1) is an unused memory location.

                let length := mload(str) // Load the string length.
                // Put the - character at the start of the string contents.
                mstore(str, 45) // 45 is the ASCII code for the - character.
                str := sub(str, 1) // Move back the string pointer by a byte.
                mstore(str, add(length, 1)) // Update the string length.
            }
        }
    }

    function toString(uint256 value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes
            // to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the
            // trailing zeros padding, and 3 other words for a max of 78 digits. In total: 5 * 32 = 160 bytes.
            let newFreeMemoryPointer := add(mload(0x40), 160)

            // Update the free memory pointer to avoid overriding our string.
            mstore(0x40, newFreeMemoryPointer)

            // Assign str to the end of the zone of newly allocated memory.
            str := sub(newFreeMemoryPointer, 32)

            // Clean the last word of memory it may not be overwritten.
            mstore(str, 0)

            // Cache the end of the memory to calculate the length later.
            let end := str

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            // prettier-ignore
            for { let temp := value } 1 {} {
                // Move the pointer 1 byte to the left.
                str := sub(str, 1)

                // Write the character to the pointer.
                // The ASCII index of the '0' character is 48.
                mstore8(str, add(48, mod(temp, 10)))

                // Keep dividing temp until zero.
                temp := div(temp, 10)

                 // prettier-ignore
                if iszero(temp) { break }
            }

            // Compute and cache the final total length of the string.
            let length := sub(end, str)

            // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 32)

            // Store the string's length at the start of memory allocated for our string.
            mstore(str, length)
        }
    }
}

File 4 of 9 : MerkleProof.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The tree and the proofs can be generated using our
 * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
 * You will find a quickstart guide in the readme.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 * OpenZeppelin's JavaScript library generates merkle trees that are safe
 * against this attack out of the box.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Calldata version of {verify}
     *
     * _Available since v4.7._
     */
    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Calldata version of {processProof}
     *
     * _Available since v4.7._
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * _Available since v4.7._
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Calldata version of {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

File 5 of 9 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 6 of 9 : AnonymiceLibrary.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library AnonymiceLibrary {
    string internal constant TABLE =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    function encode(bytes memory data) internal pure returns (string memory) {
        if (data.length == 0) return "";

        // load the table into memory
        string memory table = TABLE;

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

        // add some extra buffer at the end required for the writing
        string memory result = new string(encodedLen + 32);

        assembly {
            // set the actual output length
            mstore(result, encodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

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

            // run over the input, 3 bytes at a time
            for {

            } lt(dataPtr, endPtr) {

            } {
                dataPtr := add(dataPtr, 3)

                // read 3 bytes
                let input := mload(dataPtr)

                // write 4 characters
                mstore(
                    resultPtr,
                    shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                )
                resultPtr := add(resultPtr, 1)
                mstore(
                    resultPtr,
                    shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                )
                resultPtr := add(resultPtr, 1)
                mstore(
                    resultPtr,
                    shl(248, mload(add(tablePtr, and(shr(6, input), 0x3F))))
                )
                resultPtr := add(resultPtr, 1)
                mstore(
                    resultPtr,
                    shl(248, mload(add(tablePtr, and(input, 0x3F))))
                )
                resultPtr := add(resultPtr, 1)
            }

            // padding with '='
            switch mod(mload(data), 3)
            case 1 {
                mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
            }
            case 2 {
                mstore(sub(resultPtr, 1), shl(248, 0x3d))
            }
        }

        return result;
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    function parseInt(string memory _a)
        internal
        pure
        returns (uint8 _parsedInt)
    {
        bytes memory bresult = bytes(_a);
        uint8 mint = 0;
        for (uint8 i = 0; i < bresult.length; i++) {
            if (
                (uint8(uint8(bresult[i])) >= 48) &&
                (uint8(uint8(bresult[i])) <= 57)
            ) {
                mint *= 10;
                mint += uint8(bresult[i]) - 48;
            }
        }
        return mint;
    }

    function substring(
        string memory str,
        uint256 startIndex,
        uint256 endIndex
    ) internal pure returns (string memory) {
        bytes memory strBytes = bytes(str);
        bytes memory result = new bytes(endIndex - startIndex);
        for (uint256 i = startIndex; i < endIndex; i++) {
            result[i - startIndex] = strBytes[i];
        }
        return string(result);
    }

    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }
}

File 7 of 9 : HexAnonsGenerator.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "solmate/utils/LibString.sol";
import "./HexAnons.sol";
import "./AnonymiceLibrary.sol";

struct Counts {
    uint64 count;
    uint64 viewCount;
    uint64 colCount;
    uint32 randPos;
}

struct TokenInfo {
    uint8 pattern;
    uint32 seed;
    string[] cols;
}

contract HexAnonsGenerator {
    using LibString for uint256;

    function getPointTwo(
        uint256 _x,
        uint256 _y,
        uint256 count,
        uint256 seed
    ) public pure returns (string memory _pointTwo) {
        uint256 rand = seed * 2 + count;
        uint256 x2 = _x - 14 + (rand % 5);
        uint256 y2 = _y + 29 + (rand % 4);

        _pointTwo = string(
            abi.encodePacked(x2.toString(), ",", y2.toString(), " ")
        );
    }

    function getPointThree(
        uint256 _x,
        uint256 _y,
        uint256 count,
        uint256 seed
    ) public pure returns (string memory _pointThree) {
        uint256 rand = seed * 3 + count;
        uint256 x3 = _x + (rand % 5);
        uint256 y3 = _y + 58 + (rand % 4);

        _pointThree = string(
            abi.encodePacked(x3.toString(), ",", y3.toString(), " ")
        );
    }

    function getPointFour(
        uint256 _x,
        uint256 _y,
        uint256 count,
        uint256 seed
    ) public pure returns (string memory _pointFour) {
        uint256 rand = seed * 4 + count;
        uint256 x4 = _x + 36 + (rand % 5);
        uint256 y4 = _y + 58 + (rand % 4);

        _pointFour = string(
            abi.encodePacked(x4.toString(), ",", y4.toString(), " ")
        );
    }

    function getPointFive(
        uint256 _x,
        uint256 _y,
        uint256 count,
        uint256 seed
    ) public pure returns (string memory _pointFive) {
        uint256 rand = seed * 5 + count;
        uint256 x5 = _x + 50 + (rand % 5);
        uint256 y5 = _y + 29 + (rand % 4);

        _pointFive = string(
            abi.encodePacked(x5.toString(), ",", y5.toString(), " ")
        );
    }

    function getPointSix(
        uint256 _x,
        uint256 _y,
        uint256 count,
        uint256 seed
    ) public pure returns (string memory _pointSix) {
        uint256 rand = seed * 6 + count;
        uint256 x6 = _x + 36 + (rand % 5);
        uint256 y6 = _y + (rand % 4);

        _pointSix = string(abi.encodePacked(x6.toString(), ",", y6.toString()));
    }

    function drawHex(
        uint256 _x,
        uint256 _y,
        string calldata col,
        uint128 face,
        uint256 count,
        uint32 seed
    ) public pure returns (string memory _hex) {

        _hex = string(
            abi.encodePacked(
                "<polygon points='",
                _x.toString(),
                ",",
                _y.toString(),
                " ",
                getPointTwo(_x, _y, count, seed),
                getPointThree(_x, _y, count, seed),
                getPointFour(_x, _y, count, seed),
                getPointFive(_x, _y, count, seed),
                getPointSix(_x, _y, count, seed)
            )
        );

        _hex = string(
            abi.encodePacked(
                _hex,
                "' stroke-width='4' fill='#",
                col,
                "'/><text x='",
                drawFace(_x, _y, face)
            )
        );
    }

    function drawFace(
        uint256 _x,
        uint256 _y,
        uint128 _face
    ) public pure returns (string memory face) {
        string memory faceChoice;
        if (_face == 1) {
            faceChoice = "'-'";
        } else {
            faceChoice = "^-^";
        }

        uint256 xText = _x + 15;
        uint256 yText = _y + 38;

        face = string(
            abi.encodePacked(
                xText.toString(),
                "' y='",
                yText.toString(),
                "'>",
                faceChoice,
                "</text>"
            )
        );
    }

    function drawGrid(
        TokenInfo calldata _info
    ) public pure returns (string memory _grid) {
        Counts memory counts = Counts(0, 0, 0, _info.seed % 100);
        uint128 xFlip;
        uint128 face = 1;

        for (uint256 y = 0; y <= 805; y += 35) {
            for (uint256 x = 50; x < 840; x += 120) {
                if (counts.count % 2 == 0) {
                    xFlip = 1;
                } else {
                    xFlip = 0;
                }

                if (counts.viewCount == counts.randPos) {
                    face = 2;
                } else {
                    face = 1;
                }
                uint256 xPos = x + (xFlip * 6000) / 100;
                _grid = string(
                    abi.encodePacked(
                        _grid,
                        drawHex(
                            xPos,
                            y,
                            _info.cols[counts.colCount],
                            face,
                            counts.count,
                            _info.seed
                        )
                    )
                );
                ++counts.viewCount;
                if (counts.viewCount % _info.pattern == 0) {
                    counts.colCount = ++counts.colCount % uint64(_info.cols.length);
                }
            }
            ++counts.count;
            counts.colCount = ++counts.colCount % uint64(_info.cols.length);
        }
    }

    function buildSVG(TokenInfo calldata _info) public pure returns(string memory _svg) {
        _svg = string(
            abi.encodePacked(
                '"data:image/svg+xml;base64,',
                AnonymiceLibrary.encode(
                    bytes(
                        abi.encodePacked(
                            '<svg width="800" height="800" viewBox="0 0 800 800" style="background-color:white" xmlns="http://www.w3.org/2000/svg"><defs><g id="hexrow" font-family="monospace" stroke="black" transform="none" font-size="130%" font-weight="bold">',
                            drawGrid(_info),
                            '</g></defs><use href="#hexrow" y="-35" x="-50"/></svg>'
                        )
                    )
                )
        ));
    }

    function buildToken(
        uint256 _tokenId,
        TokenInfo calldata _info
    ) external pure returns (string memory _URI) {
        _URI = string(
            abi.encodePacked(
                "data:application/json;base64,",
                AnonymiceLibrary.encode(
                    bytes(
                        string(
                            abi.encodePacked(
                                '{"name": "Hexanons #',
                                AnonymiceLibrary.toString(_tokenId),
                                '","description": "Fully onchain generative art SVG collection. Created by McToady & Circolors."',
                                ',"image":',
                                buildSVG(_info),
                                '"}'
                            )
                        )
                    )
                )
            )
        );
    }
}

File 8 of 9 : HexAnonsErrors.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

interface HexAnonsErrors {
    error AddressMinted();
    error NotAllowlisted();
    error NotOpen();
    error NonExistantId();
    error SoldOut();
    error PaintYourOwn();
    error PaintSixColors();
    error WithdrawFail();
    error TeamMinted();
}

File 9 of 9 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressMinted","type":"error"},{"inputs":[],"name":"NonExistantId","type":"error"},{"inputs":[],"name":"NotAllowlisted","type":"error"},{"inputs":[],"name":"NotOpen","type":"error"},{"inputs":[],"name":"PaintSixColors","type":"error"},{"inputs":[],"name":"PaintYourOwn","type":"error"},{"inputs":[],"name":"SoldOut","type":"error"},{"inputs":[],"name":"TeamMinted","type":"error"},{"inputs":[],"name":"WithdrawFail","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":true,"internalType":"address","name":"previousOwner","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":"HOLDERS_MINT_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRIORITY_MINT_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"uint256","name":"_tokenId","type":"uint256"}],"name":"getTokenInfo","outputs":[{"components":[{"internalType":"uint8","name":"pattern","type":"uint8"},{"internalType":"uint32","name":"seed","type":"uint32"},{"internalType":"string[]","name":"cols","type":"string[]"}],"internalType":"struct TokenInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"holdersMint","outputs":[],"stateMutability":"payable","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"},{"internalType":"string[]","name":"_cols","type":"string[]"}],"name":"lickOfPaint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"priorityMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","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":"uint256","name":"_tokenId","type":"uint256"}],"name":"scrubPaint","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":"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":[],"name":"teamMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"_URI","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"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":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"string[]","name":"_cols","type":"string[]"}],"name":"trialPaintJob","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b5060405180604001604052806008815260200167486578416e6f6e7360c01b815250604051806040016040528060048152602001634845584160e01b8152508160009081620000619190620002fe565b506001620000708282620002fe565b5050506200008d620000876200011e60201b60201c565b62000122565b6040516200009b9062000174565b604051809103906000f080158015620000b8573d6000803e3d6000fd5b50600b80546001600160a01b039290921661010002610100600160a81b0319909216919091179055604080516060810182526006602082019081526523232323232360d11b928201929092529081526200011790600890600162000182565b50620003ca565b3390565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61157480620026b883390190565b828054828255906000526020600020908101928215620001cd579160200282015b82811115620001cd5782518290620001bc9082620002fe565b5091602001919060010190620001a3565b50620001db929150620001df565b5090565b80821115620001db576000620001f6828262000200565b50600101620001df565b5080546200020e906200026f565b6000825580601f106200021f575050565b601f0160209004906000526020600020908101906200023f919062000242565b50565b5b80821115620001db576000815560010162000243565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200028457607f821691505b602082108103620002a557634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002f957600081815260208120601f850160051c81016020861015620002d45750805b601f850160051c820191505b81811015620002f557828155600101620002e0565b5050505b505050565b81516001600160401b038111156200031a576200031a62000259565b62000332816200032b84546200026f565b84620002ab565b602080601f8311600181146200036a5760008415620003515750858301515b600019600386901b1c1916600185901b178555620002f5565b600085815260208120601f198616915b828110156200039b578886015182559484019460019091019084016200037a565b5085821015620003ba5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6122de80620003da6000396000f3fe60806040526004361061019c5760003560e01c8063715018a6116100ec578063a22cb4651161008a578063ba7a86b811610064578063ba7a86b81461048a578063c87b56dd1461049f578063e985e9c5146104bf578063f2fde38b146104fa57600080fd5b8063a22cb46514610432578063a87feb7214610452578063b88d4fde1461046a57600080fd5b80638da5cb5b116100c65780638da5cb5b146103ca57806392a247af146103e857806395d89b41146104085780639b9126541461041d57600080fd5b8063715018a614610375578063822aced71461038a5780638c7a63ae1461039d57600080fd5b80633112a2fa116101595780636352211e116101335780636352211e14610302578063637a39e8146103225780636780dd511461033557806370a082311461035557600080fd5b80633112a2fa146102ac57806332cb6b0c146102cc57806342842e0e146102e257600080fd5b806301ffc9a7146101a157806306fdde03146101d6578063081812fc146101f8578063095ea7b31461024657806318160ddd1461026857806323b872dd1461028c575b600080fd5b3480156101ad57600080fd5b506101c16101bc366004611b1e565b61051a565b60405190151581526020015b60405180910390f35b3480156101e257600080fd5b506101eb61056c565b6040516101cd9190611b8b565b34801561020457600080fd5b5061022e610213366004611b9e565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016101cd565b34801561025257600080fd5b50610266610261366004611bce565b6105fa565b005b34801561027457600080fd5b5061027e60075481565b6040519081526020016101cd565b34801561029857600080fd5b506102666102a7366004611bf8565b6106e1565b3480156102b857600080fd5b506102666102c7366004611ca3565b6108a8565b3480156102d857600080fd5b5061027e61010081565b3480156102ee57600080fd5b506102666102fd366004611bf8565b61090e565b34801561030e57600080fd5b5061022e61031d366004611b9e565b610a06565b610266610330366004611db5565b610a5d565b34801561034157600080fd5b506101eb610350366004611ca3565b610b93565b34801561036157600080fd5b5061027e610370366004611e2a565b610d44565b34801561038157600080fd5b50610266610da7565b610266610398366004611db5565b610dbb565b3480156103a957600080fd5b506103bd6103b8366004611b9e565b610ea5565b6040516101cd9190611ec8565b3480156103d657600080fd5b506006546001600160a01b031661022e565b3480156103f457600080fd5b50610266610403366004611b9e565b6110b1565b34801561041457600080fd5b506101eb611112565b34801561042957600080fd5b5061027e61111f565b34801561043e57600080fd5b5061026661044d366004611edb565b611133565b34801561045e57600080fd5b5061027e63641f67d881565b34801561047657600080fd5b50610266610485366004611f17565b61119f565b34801561049657600080fd5b50610266611287565b3480156104ab57600080fd5b506101eb6104ba366004611b9e565b611363565b3480156104cb57600080fd5b506101c16104da366004611fb2565b600560209081526000928352604080842090915290825290205460ff1681565b34801561050657600080fd5b50610266610515366004611e2a565b6115f7565b60006301ffc9a760e01b6001600160e01b03198316148061054b57506380ac58cd60e01b6001600160e01b03198316145b806105665750635b5e139f60e01b6001600160e01b03198316145b92915050565b6000805461057990611fe5565b80601f01602080910402602001604051908101604052809291908181526020018280546105a590611fe5565b80156105f25780601f106105c7576101008083540402835291602001916105f2565b820191906000526020600020905b8154815290600101906020018083116105d557829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b03163381148061064357506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6106855760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064015b60405180910390fd5b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000818152600260205260409020546001600160a01b038481169116146107375760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b604482015260640161067c565b6001600160a01b0382166107815760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b604482015260640161067c565b336001600160a01b03841614806107bb57506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b806107dc57506000818152600460205260409020546001600160a01b031633145b6108195760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b604482015260640161067c565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b816108b281610a06565b6001600160a01b0316336001600160a01b0316146108e357604051632ebfc27b60e11b815260040160405180910390fd5b6000838152600a60209081526040909120835161090892600190920191850190611a4b565b50505050565b6109198383836106e1565b6001600160a01b0382163b15806109c25750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b6919061201f565b6001600160e01b031916145b610a015760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b604482015260640161067c565b505050565b6000818152600260205260409020546001600160a01b031680610a585760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b604482015260640161067c565b919050565b3360009081526009602052604090205460ff1615610a8e5760405163cc1aa67160e01b815260040160405180910390fd5b610a9f63641f67d862015180612052565b421015610abf57604051631bb5f5b360e31b815260040160405180910390fd5b6040516001600160601b03193360601b166020820152600090603401604051602081830303815290604052805190602001209050610b538383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f7e0744664f3126f12a8a1888ab265ddd02d7ccc68d315e54b6df080a44067ed9925085915061166d9050565b610b70576040516306fb10a960e01b815260040160405180910390fd5b336000818152600960205260409020805460ff19166001179055610a0190611683565b60606007548310610bb75760405163732f483160e11b815260040160405180910390fd5b6000838152600a602090815260408083208151606081018352815460ff81168252610100900463ffffffff1681850152600182018054845181870281018701865281815292959394860193879084015b82821015610cb3578382906000526020600020018054610c2690611fe5565b80601f0160208091040260200160405190810160405280929190818152602001828054610c5290611fe5565b8015610c9f5780601f10610c7457610100808354040283529160200191610c9f565b820191906000526020600020905b815481529060010190602001808311610c8257829003601f168201915b505050505081526020019060010190610c07565b505050915250506040818101859052600b549051632e7221e360e21b815291925061010090046001600160a01b03169063b9c8878c90610cf7908490600401611ec8565b600060405180830381865afa158015610d14573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d3c9190810190612065565b949350505050565b60006001600160a01b038216610d8b5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b604482015260640161067c565b506001600160a01b031660009081526003602052604090205490565b610daf611729565b610db96000611783565b565b3360009081526009602052604090205460ff1615610dec5760405163cc1aa67160e01b815260040160405180910390fd5b63641f67d8421015610e1157604051631bb5f5b360e31b815260040160405180910390fd5b6040516001600160601b03193360601b166020820152600090603401604051602081830303815290604052805190602001209050610b538383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507fef0d1359754f96f615b555cc0dc1c50ada628537f90689db0afa9a5276c04ebe925085915061166d9050565b604080516060808201835260008083526020830152918101919091526000828152600a602090815260408083208151606081018352815460ff81168252610100900463ffffffff1681850152600182018054845181870281018701865281815292959394860193879084015b82821015610fbd578382906000526020600020018054610f3090611fe5565b80601f0160208091040260200160405190810160405280929190818152602001828054610f5c90611fe5565b8015610fa95780601f10610f7e57610100808354040283529160200191610fa9565b820191906000526020600020905b815481529060010190602001808311610f8c57829003601f168201915b505050505081526020019060010190610f11565b50505050815250509050806040015151600003610566576008805480602002602001604051908101604052809291908181526020016000905b828210156110a257838290600052602060002001805461101590611fe5565b80601f016020809104026020016040519081016040528092919081815260200182805461104190611fe5565b801561108e5780601f106110635761010080835404028352916020019161108e565b820191906000526020600020905b81548152906001019060200180831161107157829003601f168201915b505050505081526020019060010190610ff6565b50505050604082015292915050565b806110bb81610a06565b6001600160a01b0316336001600160a01b0316146110ec57604051632ebfc27b60e11b815260040160405180910390fd5b6000828152600a6020526040902060608051909161090891600190910190608090611a4b565b6001805461057990611fe5565b61113063641f67d862015180612052565b81565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6111aa8585856106e1565b6001600160a01b0384163b15806112415750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a02906111f29033908a908990899089906004016120dc565b6020604051808303816000875af1158015611211573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611235919061201f565b6001600160e01b031916145b6112805760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b604482015260640161067c565b5050505050565b61128f611729565b600b5460ff16156112b3576040516388a99d9b60e01b815260040160405180910390fd5b60005b60058110156112ec576112dc73e4260df86f5261a41d19c2066f1eb2eb4f009e84611683565b6112e581612130565b90506112b6565b5060005b600381101561132657611316734533d1f65906368ebfd61259daee561df3f3559d611683565b61131f81612130565b90506112f0565b5060005b60028110156113605761135073888f8aa938dbb18b28bdd111fa4a0d3b8e10c871611683565b61135981612130565b905061132a565b50565b606060075482106113875760405163732f483160e11b815260040160405180910390fd5b6000828152600a602090815260408083208151606081018352815460ff81168252610100900463ffffffff1681850152600182018054845181870281018701865281815292959394860193879084015b828210156114835783829060005260206000200180546113f690611fe5565b80601f016020809104026020016040519081016040528092919081815260200182805461142290611fe5565b801561146f5780601f106114445761010080835404028352916020019161146f565b820191906000526020600020905b81548152906001019060200180831161145257829003601f168201915b5050505050815260200190600101906113d7565b50505050815250509050806040015151600003611572576008805480602002602001604051908101604052809291908181526020016000905b828210156115685783829060005260206000200180546114db90611fe5565b80601f016020809104026020016040519081016040528092919081815260200182805461150790611fe5565b80156115545780601f1061152957610100808354040283529160200191611554565b820191906000526020600020905b81548152906001019060200180831161153757829003601f168201915b5050505050815260200190600101906114bc565b5050505060408201525b600b5460405160016201279160e01b031981526101009091046001600160a01b03169063fffed86f906115ab9086908590600401612149565b600060405180830381865afa1580156115c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115f09190810190612065565b9392505050565b6115ff611729565b6001600160a01b0381166116645760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161067c565b61136081611783565b60008261167a85846117d5565b14949350505050565b610100600754106116a7576040516352df9fe560e01b815260040160405180910390fd5b6007546116b48282611822565b6000828152600a6020908152604091829020835181548584015163ffffffff166101000264ffffffffff1990911660ff909216919091171781559183015180516117049260018501920190611a4b565b5090505060076000815461171790612130565b909155506117258282611914565b5050565b6006546001600160a01b03163314610db95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161067c565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600081815b845181101561181a57611806828683815181106117f9576117f9612162565b6020026020010151611a1f565b91508061181281612130565b9150506117da565b509392505050565b6040805160608082018352600080835260208301529181019190915260004244858560405160200161187a9493929190938452602084019290925260601b6001600160601b0319166040830152605482015260740190565b60408051601f198184030181529082905280516020918201206001600160601b0319606088901b16918301919091526034820185905291506000906014906054016040516020818303038152906040528051906020012060001c6118de9190612178565b6118e9906001612052565b604080516060818101835260ff909316815263ffffffff909416602085015283015250905092915050565b6001600160a01b03821661195e5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b604482015260640161067c565b6000818152600260205260409020546001600160a01b0316156119b45760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b604482015260640161067c565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000818310611a3b5760008281526020849052604090206115f0565b5060009182526020526040902090565b828054828255906000526020600020908101928215611a91579160200282015b82811115611a915782518290611a8190826121e8565b5091602001919060010190611a6b565b50611a9d929150611aa1565b5090565b80821115611a9d576000611ab58282611abe565b50600101611aa1565b508054611aca90611fe5565b6000825580601f10611ada575050565b601f01602090049060005260206000209081019061136091905b80821115611a9d5760008155600101611af4565b6001600160e01b03198116811461136057600080fd5b600060208284031215611b3057600080fd5b81356115f081611b08565b60005b83811015611b56578181015183820152602001611b3e565b50506000910152565b60008151808452611b77816020860160208601611b3b565b601f01601f19169290920160200192915050565b6020815260006115f06020830184611b5f565b600060208284031215611bb057600080fd5b5035919050565b80356001600160a01b0381168114610a5857600080fd5b60008060408385031215611be157600080fd5b611bea83611bb7565b946020939093013593505050565b600080600060608486031215611c0d57600080fd5b611c1684611bb7565b9250611c2460208501611bb7565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611c7357611c73611c34565b604052919050565b600067ffffffffffffffff821115611c9557611c95611c34565b50601f01601f191660200190565b6000806040808486031215611cb757600080fd5b8335925060208085013567ffffffffffffffff80821115611cd757600080fd5b818701915087601f830112611ceb57600080fd5b813581811115611cfd57611cfd611c34565b8060051b611d0c858201611c4a565b918252838101850191858101908b841115611d2657600080fd5b86860192505b83831015611da357823585811115611d445760008081fd5b8601603f81018d13611d565760008081fd5b87810135611d6b611d6682611c7b565b611c4a565b8181528e8b838501011115611d805760008081fd5b818b84018b83013760009181018a01919091528352509186019190860190611d2c565b80985050505050505050509250929050565b60008060208385031215611dc857600080fd5b823567ffffffffffffffff80821115611de057600080fd5b818501915085601f830112611df457600080fd5b813581811115611e0357600080fd5b8660208260051b8501011115611e1857600080fd5b60209290920196919550909350505050565b600060208284031215611e3c57600080fd5b6115f082611bb7565b60006060830160ff8351168452602063ffffffff81850151168186015260408401516060604087015282815180855260808801915060808160051b8901019450838301925060005b81811015611ebb57607f19898703018352611ea9868551611b5f565b95509284019291840191600101611e8d565b5093979650505050505050565b6020815260006115f06020830184611e45565b60008060408385031215611eee57600080fd5b611ef783611bb7565b915060208301358015158114611f0c57600080fd5b809150509250929050565b600080600080600060808688031215611f2f57600080fd5b611f3886611bb7565b9450611f4660208701611bb7565b935060408601359250606086013567ffffffffffffffff80821115611f6a57600080fd5b818801915088601f830112611f7e57600080fd5b813581811115611f8d57600080fd5b896020828501011115611f9f57600080fd5b9699959850939650602001949392505050565b60008060408385031215611fc557600080fd5b611fce83611bb7565b9150611fdc60208401611bb7565b90509250929050565b600181811c90821680611ff957607f821691505b60208210810361201957634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561203157600080fd5b81516115f081611b08565b634e487b7160e01b600052601160045260246000fd5b808201808211156105665761056661203c565b60006020828403121561207757600080fd5b815167ffffffffffffffff81111561208e57600080fd5b8201601f8101841361209f57600080fd5b80516120ad611d6682611c7b565b8181528560208385010111156120c257600080fd5b6120d3826020830160208601611b3b565b95945050505050565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b6000600182016121425761214261203c565b5060010190565b828152604060208201526000610d3c6040830184611e45565b634e487b7160e01b600052603260045260246000fd5b60008261219557634e487b7160e01b600052601260045260246000fd5b500690565b601f821115610a0157600081815260208120601f850160051c810160208610156121c15750805b601f850160051c820191505b818110156121e0578281556001016121cd565b505050505050565b815167ffffffffffffffff81111561220257612202611c34565b612216816122108454611fe5565b8461219a565b602080601f83116001811461224b57600084156122335750858301515b600019600386901b1c1916600185901b1785556121e0565b600085815260208120601f198616915b8281101561227a5788860151825594840194600190910190840161225b565b50858210156122985787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea26469706673582212206ed2590466baaceaab9d07dc5ebff35f39d0b34a9928e6d7d927eace9d054f2964736f6c63430008110033608060405234801561001057600080fd5b50611554806100206000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c80638b8cfe27116100665780638b8cfe2714610118578063b9c8878c1461012b578063ee1f382c1461013e578063fa93543114610151578063fffed86f1461016457600080fd5b80630980facd146100a3578063197cda23146100cc5780631d020d6c146100df578063296db08f146100f257806354edf7d814610105575b600080fd5b6100b66100b1366004610ad6565b610177565b6040516100c39190610b2c565b60405180910390f35b6100b66100da366004610ad6565b61020f565b6100b66100ed366004610b77565b61028b565b6100b6610100366004610bdb565b610533565b6100b6610113366004610ad6565b610605565b6100b6610126366004610ad6565b61065d565b6100b6610139366004610b77565b610691565b6100b661014c366004610c8b565b6106e9565b6100b661015f366004610ad6565b610797565b6100b6610172366004610cc0565b6107d5565b6060600083610187846003610d1c565b6101919190610d39565b905060006101a0600583610d62565b6101aa9088610d39565b905060006101b9600484610d62565b6101c488603a610d39565b6101ce9190610d39565b90506101d982610824565b6101e282610824565b6040516020016101f3929190610d76565b6040516020818303038152906040529350505050949350505050565b606060008361021f846006610d1c565b6102299190610d39565b90506000610238600583610d62565b610243886024610d39565b61024d9190610d39565b9050600061025c600484610d62565b6102669088610d39565b905061027182610824565b61027a82610824565b6040516020016101f3929190610dc0565b60606000604051806080016040528060006001600160401b0316815260200160006001600160401b0316815260200160006001600160401b0316815260200160648560200160208101906102df9190610dfc565b6102e99190610e1e565b63ffffffff169052905060006001815b610325811161052a5760325b6103488110156104bc57845161031d90600290610e41565b6001600160401b0316600003610336576001935061033b565b600093505b846060015163ffffffff1685602001516001600160401b0316036103625760029250610367565b600192505b6000606461037786611770610e5b565b6103819190610e86565b610394906001600160801b031683610d39565b9050866103fa82856103a960408d018d610eac565b8b604001516001600160401b03168181106103c6576103c6610efc565b90506020028101906103d89190610f12565b898c600001516001600160401b03168f60200160208101906101009190610dfc565b60405160200161040b929190610f58565b604051602081830303815290604052965085602001805161042b90610f87565b6001600160401b031690526104436020890189610fad565b60ff1686602001516104559190610e41565b6001600160401b03166000036104a9576104726040890189610eac565b905086604001805161048390610f87565b6001600160401b03169081905261049a9190610e41565b6001600160401b031660408701525b506104b5607882610d39565b9050610305565b50835184906104ca90610f87565b6001600160401b031690526104e26040870187610eac565b90508460400180516104f390610f87565b6001600160401b03169081905261050a9190610e41565b6001600160401b03166040850152610523602382610d39565b90506102f9565b50505050919050565b606061053e88610824565b61054788610824565b6105598a8a878763ffffffff1661065d565b61056b8b8b888863ffffffff16610177565b61057d8c8c898963ffffffff16610797565b61058f8d8d8a8a63ffffffff16610605565b6105a18e8e8b8b63ffffffff1661020f565b6040516020016105b79796959493929190610fd0565b60405160208183030381529060405290508086866105d68b8b896106e9565b6040516020016105e994939291906110a5565b6040516020818303038152906040529050979650505050505050565b6060600083610615846005610d1c565b61061f9190610d39565b9050600061062e600583610d62565b610639886032610d39565b6106439190610d39565b90506000610652600484610d62565b6101c488601d610d39565b606060008361066d846002610d1c565b6106779190610d39565b90506000610686600583610d62565b610639600e8961111f565b60606106c361069f8361028b565b6040516020016106af9190611132565b604051602081830303815290604052610868565b6040516020016106d391906112b3565b6040516020818303038152906040529050919050565b606080826001600160801b031660010361071d5750604080518082019091526003815262272d2760e81b6020820152610739565b506040805180820190915260038152622f16af60e91b60208201525b600061074686600f610d39565b90506000610755866026610d39565b905061076082610824565b61076982610824565b8460405160200161077c939291906112f8565b60405160208183030381529060405293505050509392505050565b60606000836107a7846004610d1c565b6107b19190610d39565b905060006107c0600583610d62565b6107cb886024610d39565b6101aa9190610d39565b60606107fd6107e3846109ce565b6107ec84610691565b6040516020016106af929190611370565b60405160200161080d9190611456565b604051602081830303815290604052905092915050565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a90048061083e5750819003601f19909101908152919050565b6060815160000361088757505060408051602081019091526000815290565b60006040518060600160405280604081526020016114df60409139905060006003845160026108b69190610d39565b6108c0919061149b565b6108cb906004610d1c565b905060006108da826020610d39565b6001600160401b038111156108f1576108f16114af565b6040519080825280601f01601f19166020018201604052801561091b576020820181803683370190505b509050818152600183018586518101602084015b818310156109895760039283018051603f601282901c811687015160f890811b8552600c83901c8216880151811b6001860152600683901c8216880151811b60028601529116860151901b9382019390935260040161092f565b6003895106600181146109a357600281146109b4576109c0565b613d3d60f01b6001198301526109c0565b603d60f81b6000198301525b509398975050505050505050565b6060816000036109f55750506040805180820190915260018152600360fc1b602082015290565b8160005b8115610a1f5780610a09816114c5565b9150610a189050600a8361149b565b91506109f9565b6000816001600160401b03811115610a3957610a396114af565b6040519080825280601f01601f191660200182016040528015610a63576020820181803683370190505b5090505b8415610ace57610a7860018361111f565b9150610a85600a86610d62565b610a90906030610d39565b60f81b818381518110610aa557610aa5610efc565b60200101906001600160f81b031916908160001a905350610ac7600a8661149b565b9450610a67565b949350505050565b60008060008060808587031215610aec57600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610b23578181015183820152602001610b0b565b50506000910152565b6020815260008251806020840152610b4b816040850160208701610b08565b601f01601f19169190910160400192915050565b600060608284031215610b7157600080fd5b50919050565b600060208284031215610b8957600080fd5b81356001600160401b03811115610b9f57600080fd5b610ace84828501610b5f565b80356001600160801b0381168114610bc257600080fd5b919050565b803563ffffffff81168114610bc257600080fd5b600080600080600080600060c0888a031215610bf657600080fd5b873596506020880135955060408801356001600160401b0380821115610c1b57600080fd5b818a0191508a601f830112610c2f57600080fd5b813581811115610c3e57600080fd5b8b6020828501011115610c5057600080fd5b602083019750809650505050610c6860608901610bab565b925060808801359150610c7d60a08901610bc7565b905092959891949750929550565b600080600060608486031215610ca057600080fd5b8335925060208401359150610cb760408501610bab565b90509250925092565b60008060408385031215610cd357600080fd5b8235915060208301356001600160401b03811115610cf057600080fd5b610cfc85828601610b5f565b9150509250929050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610d3357610d33610d06565b92915050565b80820180821115610d3357610d33610d06565b634e487b7160e01b600052601260045260246000fd5b600082610d7157610d71610d4c565b500690565b60008351610d88818460208801610b08565b600b60fa1b9083019081528351610da6816001840160208801610b08565b600160fd1b60019290910191820152600201949350505050565b60008351610dd2818460208801610b08565b600b60fa1b9083019081528351610df0816001840160208801610b08565b01600101949350505050565b600060208284031215610e0e57600080fd5b610e1782610bc7565b9392505050565b600063ffffffff80841680610e3557610e35610d4c565b92169190910692915050565b60006001600160401b0380841680610e3557610e35610d4c565b6001600160801b03818116838216028082169190828114610e7e57610e7e610d06565b505092915050565b60006001600160801b0380841680610ea057610ea0610d4c565b92169190910492915050565b6000808335601e19843603018112610ec357600080fd5b8301803591506001600160401b03821115610edd57600080fd5b6020019150600581901b3603821315610ef557600080fd5b9250929050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112610f2957600080fd5b8301803591506001600160401b03821115610f4357600080fd5b602001915036819003821315610ef557600080fd5b60008351610f6a818460208801610b08565b835190830190610f7e818360208801610b08565b01949350505050565b60006001600160401b03808316818103610fa357610fa3610d06565b6001019392505050565b600060208284031215610fbf57600080fd5b813560ff81168114610e1757600080fd5b703c706f6c79676f6e20706f696e74733d2760781b8152600088516020610ffd8260118601838e01610b08565b600b60fa1b601192850192830152895161101d8160128501848e01610b08565b808301925050600160fd1b60128301526013895161104081838601858e01610b08565b895193019261105481838601858d01610b08565b885193019261106881838601858c01610b08565b875193019261107c81838601858b01610b08565b865193019261109081838601858a01610b08565b929092019091019a9950505050505050505050565b600085516110b7818460208a01610b08565b7f27207374726f6b652d77696474683d2734272066696c6c3d27230000000000009083019081528486601a8301376b272f3e3c7465787420783d2760a01b601a918601918201528351611111816026840160208801610b08565b016026019695505050505050565b81810381811115610d3357610d33610d06565b7f3c7376672077696474683d2238303022206865696768743d223830302220766981527f6577426f783d22302030203830302038303022207374796c653d226261636b6760208201527f726f756e642d636f6c6f723a77686974652220786d6c6e733d22687474703a2f60408201527f2f7777772e77332e6f72672f323030302f737667223e3c646566733e3c67206960608201527f643d22686578726f772220666f6e742d66616d696c793d226d6f6e6f7370616360808201527f6522207374726f6b653d22626c61636b22207472616e73666f726d3d226e6f6e60a08201527f652220666f6e742d73697a653d22313330252220666f6e742d7765696768743d60c082015266113137b632111f60c91b60e08201526000825161125e8160e7850160208701610b08565b7f3c2f673e3c2f646566733e3c75736520687265663d2223686578726f7722207960e7939091019283015250751e9116999a91103c1e91169a9811179f1e17b9bb339f60511b61010782015261011d01919050565b7f22646174613a696d6167652f7376672b786d6c3b6261736536342c00000000008152600082516112eb81601b850160208701610b08565b91909101601b0192915050565b6000845161130a818460208901610b08565b642720793d2760d81b908301908152845161132c816005840160208901610b08565b61139f60f11b60059290910191820152835161134f816007840160208801610b08565b661e17ba32bc3a1f60c91b60079290910191820152600e0195945050505050565b737b226e616d65223a2022486578616e6f6e73202360601b815282516000906113a0816014850160208801610b08565b7f222c226465736372697074696f6e223a202246756c6c79206f6e636861696e206014918401918201527f67656e65726174697665206172742053564720636f6c6c656374696f6e2e204360348201527f726561746564206279204d63546f616479202620436972636f6c6f72732e2200605482015268161134b6b0b3b2911d60b91b6073820152835161143b81607c840160208801610b08565b61227d60f01b607c9290910191820152607e01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161148e81601d850160208701610b08565b91909101601d0192915050565b6000826114aa576114aa610d4c565b500490565b634e487b7160e01b600052604160045260246000fd5b6000600182016114d7576114d7610d06565b506001019056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212200358389288428e7c94a66da258f1dd578dbaf57f78a20282a319be9618f94d7f64736f6c63430008110033

Deployed Bytecode

0x60806040526004361061019c5760003560e01c8063715018a6116100ec578063a22cb4651161008a578063ba7a86b811610064578063ba7a86b81461048a578063c87b56dd1461049f578063e985e9c5146104bf578063f2fde38b146104fa57600080fd5b8063a22cb46514610432578063a87feb7214610452578063b88d4fde1461046a57600080fd5b80638da5cb5b116100c65780638da5cb5b146103ca57806392a247af146103e857806395d89b41146104085780639b9126541461041d57600080fd5b8063715018a614610375578063822aced71461038a5780638c7a63ae1461039d57600080fd5b80633112a2fa116101595780636352211e116101335780636352211e14610302578063637a39e8146103225780636780dd511461033557806370a082311461035557600080fd5b80633112a2fa146102ac57806332cb6b0c146102cc57806342842e0e146102e257600080fd5b806301ffc9a7146101a157806306fdde03146101d6578063081812fc146101f8578063095ea7b31461024657806318160ddd1461026857806323b872dd1461028c575b600080fd5b3480156101ad57600080fd5b506101c16101bc366004611b1e565b61051a565b60405190151581526020015b60405180910390f35b3480156101e257600080fd5b506101eb61056c565b6040516101cd9190611b8b565b34801561020457600080fd5b5061022e610213366004611b9e565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016101cd565b34801561025257600080fd5b50610266610261366004611bce565b6105fa565b005b34801561027457600080fd5b5061027e60075481565b6040519081526020016101cd565b34801561029857600080fd5b506102666102a7366004611bf8565b6106e1565b3480156102b857600080fd5b506102666102c7366004611ca3565b6108a8565b3480156102d857600080fd5b5061027e61010081565b3480156102ee57600080fd5b506102666102fd366004611bf8565b61090e565b34801561030e57600080fd5b5061022e61031d366004611b9e565b610a06565b610266610330366004611db5565b610a5d565b34801561034157600080fd5b506101eb610350366004611ca3565b610b93565b34801561036157600080fd5b5061027e610370366004611e2a565b610d44565b34801561038157600080fd5b50610266610da7565b610266610398366004611db5565b610dbb565b3480156103a957600080fd5b506103bd6103b8366004611b9e565b610ea5565b6040516101cd9190611ec8565b3480156103d657600080fd5b506006546001600160a01b031661022e565b3480156103f457600080fd5b50610266610403366004611b9e565b6110b1565b34801561041457600080fd5b506101eb611112565b34801561042957600080fd5b5061027e61111f565b34801561043e57600080fd5b5061026661044d366004611edb565b611133565b34801561045e57600080fd5b5061027e63641f67d881565b34801561047657600080fd5b50610266610485366004611f17565b61119f565b34801561049657600080fd5b50610266611287565b3480156104ab57600080fd5b506101eb6104ba366004611b9e565b611363565b3480156104cb57600080fd5b506101c16104da366004611fb2565b600560209081526000928352604080842090915290825290205460ff1681565b34801561050657600080fd5b50610266610515366004611e2a565b6115f7565b60006301ffc9a760e01b6001600160e01b03198316148061054b57506380ac58cd60e01b6001600160e01b03198316145b806105665750635b5e139f60e01b6001600160e01b03198316145b92915050565b6000805461057990611fe5565b80601f01602080910402602001604051908101604052809291908181526020018280546105a590611fe5565b80156105f25780601f106105c7576101008083540402835291602001916105f2565b820191906000526020600020905b8154815290600101906020018083116105d557829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b03163381148061064357506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6106855760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064015b60405180910390fd5b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000818152600260205260409020546001600160a01b038481169116146107375760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b604482015260640161067c565b6001600160a01b0382166107815760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b604482015260640161067c565b336001600160a01b03841614806107bb57506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b806107dc57506000818152600460205260409020546001600160a01b031633145b6108195760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b604482015260640161067c565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b816108b281610a06565b6001600160a01b0316336001600160a01b0316146108e357604051632ebfc27b60e11b815260040160405180910390fd5b6000838152600a60209081526040909120835161090892600190920191850190611a4b565b50505050565b6109198383836106e1565b6001600160a01b0382163b15806109c25750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b6919061201f565b6001600160e01b031916145b610a015760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b604482015260640161067c565b505050565b6000818152600260205260409020546001600160a01b031680610a585760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b604482015260640161067c565b919050565b3360009081526009602052604090205460ff1615610a8e5760405163cc1aa67160e01b815260040160405180910390fd5b610a9f63641f67d862015180612052565b421015610abf57604051631bb5f5b360e31b815260040160405180910390fd5b6040516001600160601b03193360601b166020820152600090603401604051602081830303815290604052805190602001209050610b538383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f7e0744664f3126f12a8a1888ab265ddd02d7ccc68d315e54b6df080a44067ed9925085915061166d9050565b610b70576040516306fb10a960e01b815260040160405180910390fd5b336000818152600960205260409020805460ff19166001179055610a0190611683565b60606007548310610bb75760405163732f483160e11b815260040160405180910390fd5b6000838152600a602090815260408083208151606081018352815460ff81168252610100900463ffffffff1681850152600182018054845181870281018701865281815292959394860193879084015b82821015610cb3578382906000526020600020018054610c2690611fe5565b80601f0160208091040260200160405190810160405280929190818152602001828054610c5290611fe5565b8015610c9f5780601f10610c7457610100808354040283529160200191610c9f565b820191906000526020600020905b815481529060010190602001808311610c8257829003601f168201915b505050505081526020019060010190610c07565b505050915250506040818101859052600b549051632e7221e360e21b815291925061010090046001600160a01b03169063b9c8878c90610cf7908490600401611ec8565b600060405180830381865afa158015610d14573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d3c9190810190612065565b949350505050565b60006001600160a01b038216610d8b5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b604482015260640161067c565b506001600160a01b031660009081526003602052604090205490565b610daf611729565b610db96000611783565b565b3360009081526009602052604090205460ff1615610dec5760405163cc1aa67160e01b815260040160405180910390fd5b63641f67d8421015610e1157604051631bb5f5b360e31b815260040160405180910390fd5b6040516001600160601b03193360601b166020820152600090603401604051602081830303815290604052805190602001209050610b538383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507fef0d1359754f96f615b555cc0dc1c50ada628537f90689db0afa9a5276c04ebe925085915061166d9050565b604080516060808201835260008083526020830152918101919091526000828152600a602090815260408083208151606081018352815460ff81168252610100900463ffffffff1681850152600182018054845181870281018701865281815292959394860193879084015b82821015610fbd578382906000526020600020018054610f3090611fe5565b80601f0160208091040260200160405190810160405280929190818152602001828054610f5c90611fe5565b8015610fa95780601f10610f7e57610100808354040283529160200191610fa9565b820191906000526020600020905b815481529060010190602001808311610f8c57829003601f168201915b505050505081526020019060010190610f11565b50505050815250509050806040015151600003610566576008805480602002602001604051908101604052809291908181526020016000905b828210156110a257838290600052602060002001805461101590611fe5565b80601f016020809104026020016040519081016040528092919081815260200182805461104190611fe5565b801561108e5780601f106110635761010080835404028352916020019161108e565b820191906000526020600020905b81548152906001019060200180831161107157829003601f168201915b505050505081526020019060010190610ff6565b50505050604082015292915050565b806110bb81610a06565b6001600160a01b0316336001600160a01b0316146110ec57604051632ebfc27b60e11b815260040160405180910390fd5b6000828152600a6020526040902060608051909161090891600190910190608090611a4b565b6001805461057990611fe5565b61113063641f67d862015180612052565b81565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6111aa8585856106e1565b6001600160a01b0384163b15806112415750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a02906111f29033908a908990899089906004016120dc565b6020604051808303816000875af1158015611211573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611235919061201f565b6001600160e01b031916145b6112805760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b604482015260640161067c565b5050505050565b61128f611729565b600b5460ff16156112b3576040516388a99d9b60e01b815260040160405180910390fd5b60005b60058110156112ec576112dc73e4260df86f5261a41d19c2066f1eb2eb4f009e84611683565b6112e581612130565b90506112b6565b5060005b600381101561132657611316734533d1f65906368ebfd61259daee561df3f3559d611683565b61131f81612130565b90506112f0565b5060005b60028110156113605761135073888f8aa938dbb18b28bdd111fa4a0d3b8e10c871611683565b61135981612130565b905061132a565b50565b606060075482106113875760405163732f483160e11b815260040160405180910390fd5b6000828152600a602090815260408083208151606081018352815460ff81168252610100900463ffffffff1681850152600182018054845181870281018701865281815292959394860193879084015b828210156114835783829060005260206000200180546113f690611fe5565b80601f016020809104026020016040519081016040528092919081815260200182805461142290611fe5565b801561146f5780601f106114445761010080835404028352916020019161146f565b820191906000526020600020905b81548152906001019060200180831161145257829003601f168201915b5050505050815260200190600101906113d7565b50505050815250509050806040015151600003611572576008805480602002602001604051908101604052809291908181526020016000905b828210156115685783829060005260206000200180546114db90611fe5565b80601f016020809104026020016040519081016040528092919081815260200182805461150790611fe5565b80156115545780601f1061152957610100808354040283529160200191611554565b820191906000526020600020905b81548152906001019060200180831161153757829003601f168201915b5050505050815260200190600101906114bc565b5050505060408201525b600b5460405160016201279160e01b031981526101009091046001600160a01b03169063fffed86f906115ab9086908590600401612149565b600060405180830381865afa1580156115c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115f09190810190612065565b9392505050565b6115ff611729565b6001600160a01b0381166116645760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161067c565b61136081611783565b60008261167a85846117d5565b14949350505050565b610100600754106116a7576040516352df9fe560e01b815260040160405180910390fd5b6007546116b48282611822565b6000828152600a6020908152604091829020835181548584015163ffffffff166101000264ffffffffff1990911660ff909216919091171781559183015180516117049260018501920190611a4b565b5090505060076000815461171790612130565b909155506117258282611914565b5050565b6006546001600160a01b03163314610db95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161067c565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600081815b845181101561181a57611806828683815181106117f9576117f9612162565b6020026020010151611a1f565b91508061181281612130565b9150506117da565b509392505050565b6040805160608082018352600080835260208301529181019190915260004244858560405160200161187a9493929190938452602084019290925260601b6001600160601b0319166040830152605482015260740190565b60408051601f198184030181529082905280516020918201206001600160601b0319606088901b16918301919091526034820185905291506000906014906054016040516020818303038152906040528051906020012060001c6118de9190612178565b6118e9906001612052565b604080516060818101835260ff909316815263ffffffff909416602085015283015250905092915050565b6001600160a01b03821661195e5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b604482015260640161067c565b6000818152600260205260409020546001600160a01b0316156119b45760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b604482015260640161067c565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000818310611a3b5760008281526020849052604090206115f0565b5060009182526020526040902090565b828054828255906000526020600020908101928215611a91579160200282015b82811115611a915782518290611a8190826121e8565b5091602001919060010190611a6b565b50611a9d929150611aa1565b5090565b80821115611a9d576000611ab58282611abe565b50600101611aa1565b508054611aca90611fe5565b6000825580601f10611ada575050565b601f01602090049060005260206000209081019061136091905b80821115611a9d5760008155600101611af4565b6001600160e01b03198116811461136057600080fd5b600060208284031215611b3057600080fd5b81356115f081611b08565b60005b83811015611b56578181015183820152602001611b3e565b50506000910152565b60008151808452611b77816020860160208601611b3b565b601f01601f19169290920160200192915050565b6020815260006115f06020830184611b5f565b600060208284031215611bb057600080fd5b5035919050565b80356001600160a01b0381168114610a5857600080fd5b60008060408385031215611be157600080fd5b611bea83611bb7565b946020939093013593505050565b600080600060608486031215611c0d57600080fd5b611c1684611bb7565b9250611c2460208501611bb7565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611c7357611c73611c34565b604052919050565b600067ffffffffffffffff821115611c9557611c95611c34565b50601f01601f191660200190565b6000806040808486031215611cb757600080fd5b8335925060208085013567ffffffffffffffff80821115611cd757600080fd5b818701915087601f830112611ceb57600080fd5b813581811115611cfd57611cfd611c34565b8060051b611d0c858201611c4a565b918252838101850191858101908b841115611d2657600080fd5b86860192505b83831015611da357823585811115611d445760008081fd5b8601603f81018d13611d565760008081fd5b87810135611d6b611d6682611c7b565b611c4a565b8181528e8b838501011115611d805760008081fd5b818b84018b83013760009181018a01919091528352509186019190860190611d2c565b80985050505050505050509250929050565b60008060208385031215611dc857600080fd5b823567ffffffffffffffff80821115611de057600080fd5b818501915085601f830112611df457600080fd5b813581811115611e0357600080fd5b8660208260051b8501011115611e1857600080fd5b60209290920196919550909350505050565b600060208284031215611e3c57600080fd5b6115f082611bb7565b60006060830160ff8351168452602063ffffffff81850151168186015260408401516060604087015282815180855260808801915060808160051b8901019450838301925060005b81811015611ebb57607f19898703018352611ea9868551611b5f565b95509284019291840191600101611e8d565b5093979650505050505050565b6020815260006115f06020830184611e45565b60008060408385031215611eee57600080fd5b611ef783611bb7565b915060208301358015158114611f0c57600080fd5b809150509250929050565b600080600080600060808688031215611f2f57600080fd5b611f3886611bb7565b9450611f4660208701611bb7565b935060408601359250606086013567ffffffffffffffff80821115611f6a57600080fd5b818801915088601f830112611f7e57600080fd5b813581811115611f8d57600080fd5b896020828501011115611f9f57600080fd5b9699959850939650602001949392505050565b60008060408385031215611fc557600080fd5b611fce83611bb7565b9150611fdc60208401611bb7565b90509250929050565b600181811c90821680611ff957607f821691505b60208210810361201957634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561203157600080fd5b81516115f081611b08565b634e487b7160e01b600052601160045260246000fd5b808201808211156105665761056661203c565b60006020828403121561207757600080fd5b815167ffffffffffffffff81111561208e57600080fd5b8201601f8101841361209f57600080fd5b80516120ad611d6682611c7b565b8181528560208385010111156120c257600080fd5b6120d3826020830160208601611b3b565b95945050505050565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b6000600182016121425761214261203c565b5060010190565b828152604060208201526000610d3c6040830184611e45565b634e487b7160e01b600052603260045260246000fd5b60008261219557634e487b7160e01b600052601260045260246000fd5b500690565b601f821115610a0157600081815260208120601f850160051c810160208610156121c15750805b601f850160051c820191505b818110156121e0578281556001016121cd565b505050505050565b815167ffffffffffffffff81111561220257612202611c34565b612216816122108454611fe5565b8461219a565b602080601f83116001811461224b57600084156122335750858301515b600019600386901b1c1916600185901b1785556121e0565b600085815260208120601f198616915b8281101561227a5788860151825594840194600190910190840161225b565b50858210156122985787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea26469706673582212206ed2590466baaceaab9d07dc5ebff35f39d0b34a9928e6d7d927eace9d054f2964736f6c63430008110033

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