ETH Price: $3,151.75 (+1.64%)

Token

Mutytes (TYTE)
 

Overview

Max Total Supply

1,721 TYTE

Holders

321

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
broping.eth
Balance
1 TYTE
0x5fd8f613be904b065e421f2e2f0fcb1a4f350559
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
Mutytes

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 79 : Mutytes.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * ################################################################################
 * ################################################################################
 * ################################################################################
 * ################################################################################
 * ################################################################################
 * #######################################   ######################################
 * #####################################       ####################################
 * ###################################           ##################################
 * #################################               ################################
 * ################################################################################
 * ################################################################################
 * ################       ####                           ###        ###############
 * ################      ####        #############        ####      ###############
 * ################     ####          ###########          ####     ###############
 * ################    ###     ##       #######       ##    ####    ###############
 * ################  ####    ######      #####      ######    ####  ###############
 * ################ ####                                       #### ###############
 * ####################                #########                ###################
 * ################                     #######                     ###############
 * ################   ###############             ##############   ################
 * #################   #############               ############   #################
 * ###################   ##########                 ##########   ##################
 * ####################    #######                   #######    ###################
 * ######################     ###                     ###    ######################
 * ##########################                             #########################
 * #############################                       ############################
 * ################################################################################
 * ################################################################################
 * ################################################################################
 * ################################################################################
 * ################################################################################
 * ################################################################################
 *
 * The Mutytes have invaded Ethernia! We hereby extend access to the lab and its
 * facilities to any individual or party that may locate and retrieve a Mutyte sample.
 * We believe their mutated Bit Signatures hold the key to unraveling great mysteries.
 * Join our efforts in capturing and understanding these creatures!
 *
 * - For Ethernia!
 *
 * Founders: @tuyumoo & @nftyte
 */

import { MutytesTokenProxy } from "./token/MutytesTokenProxy.sol";
import { SafeOwnableProxy } from "../core/access/ownable/safe/SafeOwnableProxy.sol";
import { ProxyFacetedController as ProxyFaceted } from "../core/proxy/faceted/ProxyFacetedController.sol";
import { Proxy } from "../core/proxy/Proxy.sol";

contract Mutytes is MutytesTokenProxy, SafeOwnableProxy, ProxyFaceted, Proxy {
    constructor(address init, bytes memory data) {
        MutytesToken_();
        Ownable_();
        Proxy_(init, data);
    }
}

File 2 of 79 : MutytesTokenProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IMutytesToken } from "./IMutytesToken.sol";
import { MutytesTokenController } from "./MutytesTokenController.sol";
import { ERC165Proxy } from "../../core/introspection/ERC165Proxy.sol";
import { ERC721Proxy } from "../../core/token/ERC721/ERC721Proxy.sol";
import { ERC721MetadataProxy } from "../../core/token/ERC721/metadata/ERC721MetadataProxy.sol";
import { ERC721EnumerableProxy } from "../../core/token/ERC721/enumerable/ERC721EnumerableProxy.sol";
import { ERC721MintableProxy } from "../../core/token/ERC721/mintable/ERC721MintableProxy.sol";
import { ERC721MintableController, ERC721MintableModel } from "../../core/token/ERC721/mintable/ERC721MintableController.sol";
import { ERC721BurnableProxy, ERC721BurnableController } from "../../core/token/ERC721/burnable/ERC721BurnableProxy.sol";

/**
 * @title Mutytes token implementation
 * @dev Note: Upgradable implementation
 */
abstract contract MutytesTokenProxy is
    IMutytesToken,
    ERC165Proxy,
    ERC721Proxy,
    ERC721MetadataProxy,
    ERC721EnumerableProxy,
    ERC721MintableProxy,
    ERC721BurnableProxy,
    MutytesTokenController
{
    /**
     * @inheritdoc IMutytesToken
     */
    function availableSupply() external virtual upgradable returns (uint256) {
        return _availableSupply();
    }

    /**
     * @inheritdoc IMutytesToken
     */
    function mintBalanceOf(address owner) external virtual upgradable returns (uint256) {
        return mintBalanceOf_(owner);
    }

    function _burn_(address owner, uint256 tokenId)
        internal
        virtual
        override(ERC721BurnableController, MutytesTokenController)
    {
        super._burn_(owner, tokenId);
    }

    function _maxMintBalance()
        internal
        pure
        virtual
        override(ERC721MintableModel, MutytesTokenController)
        returns (uint256)
    {
        return super._maxMintBalance();
    }
}

File 3 of 79 : SafeOwnableProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ISafeOwnable } from "./ISafeOwnable.sol";
import { SafeOwnableController } from "./SafeOwnableController.sol";
import { OwnableProxy, IERC173 } from "../OwnableProxy.sol";

/**
 * @title ERC173 safe ownership access control implementation
 * @dev Note: Upgradable implementation
 */
abstract contract SafeOwnableProxy is ISafeOwnable, OwnableProxy, SafeOwnableController {
    /**
     * @inheritdoc ISafeOwnable
     */
    function nomineeOwner() external virtual upgradable returns (address) {
        return nomineeOwner_();
    }

    /**
     * @inheritdoc ISafeOwnable
     */
    function acceptOwnership() external virtual upgradable onlyNomineeOwner {
        acceptOwnership_();
    }

    /**
     * @inheritdoc IERC173
     */
    function transferOwnership(address newOwner)
        external
        virtual
        override(IERC173, OwnableProxy)
        upgradable
        onlyOwner
    {
        _setNomineeOwner(newOwner);
    }
}

File 4 of 79 : ProxyFacetedController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ProxyFacetedModel } from "./ProxyFacetedModel.sol";
import { ProxyController } from "../ProxyController.sol";
import { AddressUtils } from "../../utils/AddressUtils.sol";

abstract contract ProxyFacetedController is ProxyFacetedModel, ProxyController {
    using AddressUtils for address;

    function implementation_() internal view virtual override returns (address) {
        return implementation_(msg.sig);
    }

    function implementation_(bytes4 selector)
        internal
        view
        virtual
        returns (address implementation)
    {
        implementation = _implementation(selector);
        implementation.enforceIsNotZeroAddress();
    }

    function addFunctions_(
        bytes4[] memory selectors,
        address implementation,
        bool isUpgradable
    ) internal virtual {
        _enforceCanAddFunctions(implementation);

        unchecked {
            for (uint256 i; i < selectors.length; i++) {
                bytes4 selector = selectors[i];
                _enforceCanAddFunction(selector, implementation);
                _addFunction_(selector, implementation, isUpgradable);
            }
        }
    }

    function addFunction_(
        bytes4 selector,
        address implementation,
        bool isUpgradable
    ) internal virtual {
        _enforceCanAddFunctions(implementation);
        _enforceCanAddFunction(selector, implementation);
        _addFunction_(selector, implementation, isUpgradable);
    }

    function replaceFunctions_(bytes4[] memory selectors, address implementation)
        internal
        virtual
    {
        _enforceCanAddFunctions(implementation);

        unchecked {
            for (uint256 i; i < selectors.length; i++) {
                bytes4 selector = selectors[i];
                _enforceCanReplaceFunction(selector, implementation);
                _replaceFunction_(selector, implementation);
            }
        }
    }

    function replaceFunction_(bytes4 selector, address implementation) internal virtual {
        _enforceCanAddFunctions(implementation);
        _enforceCanReplaceFunction(selector, implementation);
        _replaceFunction_(selector, implementation);
    }

    function removeFunctions_(bytes4[] memory selectors) internal virtual {
        unchecked {
            for (uint256 i; i < selectors.length; i++) {
                removeFunction_(selectors[i]);
            }
        }
    }

    function removeFunction_(bytes4 selector) internal virtual {
        address implementation = _implementation(selector);
        _enforceCanRemoveFunction(selector, implementation);
        _removeFunction_(selector, implementation);
    }

    function setUpgradableFunctions_(bytes4[] memory selectors, bool isUpgradable)
        internal
        virtual
    {
        unchecked {
            for (uint256 i; i < selectors.length; i++) {
                setUpgradableFunction_(selectors[i], isUpgradable);
            }
        }
    }

    function setUpgradableFunction_(bytes4 selector, bool isUpgradable) internal virtual {
        _implementation(selector).enforceIsNotZeroAddress();
        _setUpgradableFunction(selector, isUpgradable);
    }

    function _addFunction_(
        bytes4 selector,
        address implementation,
        bool isUpgradable
    ) internal virtual {
        _addFunction(selector, implementation, isUpgradable);
        _afterAddFunction(implementation);
    }

    function _replaceFunction_(bytes4 selector, address implementation) internal virtual {
        address oldImplementation = _implementation(selector);
        _replaceFunction(selector, implementation);
        _afterRemoveFunction(oldImplementation);
        _afterAddFunction(implementation);
    }

    function _removeFunction_(bytes4 selector, address implementation) internal virtual {
        _removeFunction(selector);
        _afterRemoveFunction(implementation);
    }

    function _enforceCanAddFunctions(address implementation) internal view virtual {
        if (implementation != address(this)) {
            implementation.enforceIsContract();
        }
    }

    function _enforceCanAddFunction(bytes4 selector, address) internal view virtual {
        _implementation(selector).enforceIsZeroAddress();
    }

    function _enforceCanReplaceFunction(bytes4 selector, address implementation)
        internal
        view
        virtual
    {
        address oldImplementation = _implementation(selector);
        oldImplementation.enforceNotEquals(implementation);
        _enforceCanRemoveFunction(selector, oldImplementation);
    }

    function _enforceCanRemoveFunction(bytes4 selector, address implementation)
        internal
        view
        virtual
    {
        implementation.enforceIsNotZeroAddress();

        if (!_isUpgradable(selector)) {
            implementation.enforceNotEquals(address(this));
        }
    }
}

File 5 of 79 : Proxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ProxyController } from "./ProxyController.sol";

/**
 * @title Proxy delegatecall fallback implementation
 */
abstract contract Proxy is ProxyController {
    fallback() external payable virtual {
        fallback_();
    }

    receive() external payable virtual {
        fallback_();
    }
}

File 6 of 79 : IMutytesToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC165 } from "../../core/introspection/IERC165.sol";
import { IERC721 } from "../../core/token/ERC721/IERC721.sol";
import { IERC721Metadata } from "../../core/token/ERC721/metadata/IERC721Metadata.sol";
import { IERC721Enumerable } from "../../core/token/ERC721/enumerable/IERC721Enumerable.sol";
import { IERC721Mintable } from "../../core/token/ERC721/mintable/IERC721Mintable.sol";
import { IERC721Burnable } from "../../core/token/ERC721/burnable/IERC721Burnable.sol";

/**
 * @title Mutytes token interface
 */
interface IMutytesToken is
    IERC721Burnable,
    IERC721Mintable,
    IERC721Enumerable,
    IERC721Metadata,
    IERC721,
    IERC165
{
    /**
     * @notice Get the available supply
     * @return supply The available supply amount
     */
    function availableSupply() external returns (uint256);

    /**
     * @notice Get the amount of tokens minted by an owner
     * @param owner The owner's address
     * @return balance The balance amount
     */
    function mintBalanceOf(address owner) external returns (uint256);
}

File 7 of 79 : MutytesTokenController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ERC721MetadataController } from "../../core/token/ERC721/metadata/ERC721MetadataController.sol";
import { ERC721MintableController } from "../../core/token/ERC721/mintable/ERC721MintableController.sol";
import { ERC721BurnableController } from "../../core/token/ERC721/burnable/ERC721BurnableController.sol";
import { IntegerUtils } from "../../core/utils/IntegerUtils.sol";

abstract contract MutytesTokenController is
    ERC721BurnableController,
    ERC721MintableController,
    ERC721MetadataController
{
    using IntegerUtils for uint256;

    function MutytesToken_() internal virtual {
        ERC721Metadata_("Mutytes", "TYTE");
    }

    function _burn_(address owner, uint256 tokenId) internal virtual override {
        if (_tokenURIProvider(tokenId) != 0) {
            _setTokenURIProvider(tokenId, 0);
        }

        super._burn_(owner, tokenId);
    }

    function _maxMintBalance() internal pure virtual override returns (uint256) {
        return 10;
    }
}

File 8 of 79 : ERC165Proxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC165 } from "./IERC165.sol";
import { ERC165Controller } from "./ERC165Controller.sol";
import { ProxyUpgradableController } from "../proxy/upgradable/ProxyUpgradableController.sol";

/**
 * @title ERC165 implementation
 * @dev Note: Upgradable implementation
 */
abstract contract ERC165Proxy is IERC165, ERC165Controller, ProxyUpgradableController {
    /**
     * @inheritdoc IERC165
     */
    function supportsInterface(bytes4 interfaceId)
        external
        virtual
        upgradable
        returns (bool)
    {
        return supportsInterface_(interfaceId);
    }
}

File 9 of 79 : ERC721Proxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721 } from "./IERC721.sol";
import { ERC721Controller } from "./ERC721Controller.sol";
import { ProxyUpgradableController } from "../../proxy/upgradable/ProxyUpgradableController.sol";

/**
 * @title ERC721 implementation, excluding optional extensions
 * @dev Note: Upgradable implementation
 */
abstract contract ERC721Proxy is IERC721, ERC721Controller, ProxyUpgradableController {
    /**
     * @inheritdoc IERC721
     */
    function balanceOf(address owner) external virtual upgradable returns (uint256) {
        return balanceOf_(owner);
    }

    /**
     * @inheritdoc IERC721
     */
    function ownerOf(uint256 tokenId) external virtual upgradable returns (address) {
        return ownerOf_(tokenId);
    }

    /**
     * @inheritdoc IERC721
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external virtual upgradable {
        safeTransferFrom_(from, to, tokenId, data);
    }

    /**
     * @inheritdoc IERC721
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external virtual upgradable {
        safeTransferFrom_(from, to, tokenId, "");
    }

    /**
     * @inheritdoc IERC721
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external virtual upgradable {
        transferFrom_(from, to, tokenId);
    }

    /**
     * @inheritdoc IERC721
     */
    function approve(address to, uint256 tokenId) external virtual upgradable {
        approve_(to, tokenId);
    }

    /**
     * @inheritdoc IERC721
     */
    function setApprovalForAll(address operator, bool approved)
        external
        virtual
        upgradable
    {
        setApprovalForAll_(operator, approved);
    }

    /**
     * @inheritdoc IERC721
     */
    function getApproved(uint256 tokenId) external virtual upgradable returns (address) {
        return getApproved_(tokenId);
    }

    /**
     * @inheritdoc IERC721
     */
    function isApprovedForAll(address owner, address operator)
        external
        virtual
        upgradable
        returns (bool)
    {
        return isApprovedForAll_(owner, operator);
    }
}

File 10 of 79 : ERC721MetadataProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721Metadata } from "./IERC721Metadata.sol";
import { ERC721MetadataController } from "./ERC721MetadataController.sol";
import { ERC721TokenURIProxyController } from "../tokenURI/ERC721TokenURIProxyController.sol";
import { ProxyUpgradableController } from "../../../proxy/upgradable/ProxyUpgradableController.sol";

/**
 * @title ERC721 metadata extension implementation
 * @dev Note: Upgradable implementation
 */
abstract contract ERC721MetadataProxy is
    IERC721Metadata,
    ERC721MetadataController,
    ERC721TokenURIProxyController,
    ProxyUpgradableController
{
    /**
     * @inheritdoc IERC721Metadata
     */
    function name() external virtual upgradable returns (string memory) {
        return name_();
    }

    /**
     * @inheritdoc IERC721Metadata
     */
    function symbol() external virtual upgradable returns (string memory) {
        return symbol_();
    }

    /**
     * @inheritdoc IERC721Metadata
     */
    function tokenURI(uint256 tokenId)
        external
        virtual
        upgradable
        returns (string memory)
    {
        return tokenURIProxyable_(tokenId);
    }
}

File 11 of 79 : ERC721EnumerableProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721Enumerable } from "./IERC721Enumerable.sol";
import { ERC721EnumerableController } from "./ERC721EnumerableController.sol";
import { ProxyUpgradableController } from "../../../proxy/upgradable/ProxyUpgradableController.sol";

/**
 * @title ERC721 enumerable extension implementation
 * @dev Note: Upgradable implementation
 */
abstract contract ERC721EnumerableProxy is
    IERC721Enumerable,
    ERC721EnumerableController,
    ProxyUpgradableController
{
    /**
     * @inheritdoc IERC721Enumerable
     */
    function totalSupply() external virtual upgradable returns (uint256) {
        return totalSupply_();
    }

    /**
     * @inheritdoc IERC721Enumerable
     */
    function tokenByIndex(uint256 index) external virtual upgradable returns (uint256) {
        return tokenByIndex_(index);
    }

    /**
     * @inheritdoc IERC721Enumerable
     */
    function tokenOfOwnerByIndex(address owner, uint256 index)
        external
        virtual
        upgradable
        returns (uint256)
    {
        return tokenOfOwnerByIndex_(owner, index);
    }
}

File 12 of 79 : ERC721MintableProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721Mintable } from "./IERC721Mintable.sol";
import { ERC721MintableController } from "./ERC721MintableController.sol";
import { ProxyUpgradableController } from "../../../proxy/upgradable/ProxyUpgradableController.sol";

/**
 * @title ERC721 token minting extension implementation
 * @dev Note: Upgradable implementation
 */
abstract contract ERC721MintableProxy is
    IERC721Mintable,
    ERC721MintableController,
    ProxyUpgradableController
{
    /**
     * @inheritdoc IERC721Mintable
     */
    function mint(uint256 amount) external payable virtual override upgradable {
        mint_(amount);
    }
}

File 13 of 79 : ERC721MintableController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721MintableController } from "./IERC721MintableController.sol";
import { ERC721MintableModel } from "./ERC721MintableModel.sol";
import { ERC721SupplyController } from "../supply/ERC721SupplyController.sol";
import { ERC721TokenUtils } from "../utils/ERC721TokenUtils.sol";
import { AddressUtils } from "../../../utils/AddressUtils.sol";
import { IntegerUtils } from "../../../utils/IntegerUtils.sol";

abstract contract ERC721MintableController is
    IERC721MintableController,
    ERC721MintableModel,
    ERC721SupplyController
{
    using ERC721TokenUtils for address;
    using AddressUtils for address;
    using IntegerUtils for uint256;

    function mintBalanceOf_(address owner) internal view virtual returns (uint256) {
        owner.enforceIsNotZeroAddress();
        return _mintBalanceOf(owner);
    }

    function mint_(uint256 amount) internal virtual {
        _enforceCanMint(amount);
        (uint256 tokenId, uint256 maxTokenId) = _mint_(msg.sender, amount);

        unchecked {
            while (tokenId < maxTokenId) {
                emit Transfer(address(0), msg.sender, tokenId++);
            }
        }
    }

    function _mint_(address to, uint256 amount)
        internal
        virtual
        returns (uint256 tokenId, uint256 maxTokenId)
    {
        tokenId = to.toTokenId() | _mintBalanceOf(to);
        maxTokenId = tokenId + amount;
        _mint(to, amount);
        _updateAvailableSupply(amount);
    }

    function _mintValue() internal view virtual returns (uint256) {
        return 0 ether;
    }

    function _mintedSupply() internal view virtual returns (uint256) {
        return _initialSupply() - _availableSupply();
    }

    function _enforceCanMint(uint256 amount) internal view virtual {
        amount.enforceIsNotZero();
        amount.enforceNotGreaterThan(_availableSupply());
        msg.value.enforceEquals(amount * _mintValue());
        (_mintBalanceOf(msg.sender) + amount).enforceNotGreaterThan(_maxMintBalance());
    }
}

File 14 of 79 : ERC721BurnableProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721Burnable } from "./IERC721Burnable.sol";
import { ERC721BurnableController } from "./ERC721BurnableController.sol";
import { ProxyUpgradableController } from "../../../proxy/upgradable/ProxyUpgradableController.sol";

/**
 * @title ERC721 token burning extension implementation
 * @dev Note: Upgradable implementation
 */
abstract contract ERC721BurnableProxy is
    IERC721Burnable,
    ERC721BurnableController,
    ProxyUpgradableController
{
    /**
     * @inheritdoc IERC721Burnable
     */
    function burn(uint256 tokenId) external virtual override upgradable {
        burn_(tokenId);
    }
}

File 15 of 79 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC165 interface
 * @dev See https://eips.ethereum.org/EIPS/eip-165
 */
interface IERC165 {
    /**
     * @notice Query whether contract supports an interface
     * @param interfaceId The interface id
     * @return isSupported Whether the interface is supported
     */
    function supportsInterface(bytes4 interfaceId) external returns (bool);
}

File 16 of 79 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721Controller } from "./IERC721Controller.sol";

/**
 * @title ERC721 interface
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721 is IERC721Controller {
    /**
     * @notice Get the balance of an owner
     * @param owner The owner's address
     * @return balance The balance amount
     */
    function balanceOf(address owner) external returns (uint256);

    /**
     * @notice Get the owner a token
     * @param tokenId The token id
     * @return owner The owner's address
     */
    function ownerOf(uint256 tokenId) external returns (address);

    /**
     * @notice Transfer a token between addresses
     * @dev Preforms ERC721Receiver check if applicable
     * @param from The token's owner address
     * @param to The recipient address
     * @param tokenId The token id
     * @param data Additional data
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @notice Transfer a token between addresses
     * @dev Preforms ERC721Receiver check if applicable
     * @param from The token's owner address
     * @param to The recipient address
     * @param tokenId The token id
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @notice Transfer a token between addresses
     * @param from The token's owner address
     * @param to The recipient address
     * @param tokenId The token id
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @notice Grant approval to a token
     * @param approved The address to approve
     * @param tokenId The token id
     */
    function approve(address approved, uint256 tokenId) external;

    /**
     * @notice Set operator approval
     * @param operator The operator's address
     * @param approved Whether to grant approval
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @notice Get the approved address of a token
     * @param tokenId The token id
     * @return approved The approved address
     */
    function getApproved(uint256 tokenId) external returns (address);

    /**
     * @notice Query whether the operator is approved for an address
     * @param owner The address to query
     * @param operator The operator's address
     * @return isApproved Whether the operator is approved
     */
    function isApprovedForAll(address owner, address operator) external returns (bool);
}

File 17 of 79 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721 metadata extension interface
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata {
    /**
     * @notice Get the token name
     * @return name The token name
     */
    function name() external returns (string memory);

    /**
     * @notice Get the token symbol
     * @return symbol The token symbol
     */
    function symbol() external returns (string memory);

    /**
     * @notice Get the URI of a token
     * @param tokenId The token id
     * @return tokenURI The token URI
     */
    function tokenURI(uint256 tokenId) external returns (string memory);
}

File 18 of 79 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721 enumerable extension interface
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable {
    /**
     * @notice Get the total token supply
     * @return supply The total supply amount
     */
    function totalSupply() external returns (uint256);

    /**
     * @notice Get a token by global enumeration index
     * @param index The token position
     * @return tokenId The token id
     */
    function tokenByIndex(uint256 index) external returns (uint256);

    /**
     * @notice Get an owner's token by enumeration index
     * @param owner The owner's address
     * @param index The token position
     * @return tokenId The token id
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external returns (uint256);
}

File 19 of 79 : IERC721Mintable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721MintableController } from "./IERC721MintableController.sol";

/**
 * @title ERC721 token minting extension interface
 */
interface IERC721Mintable is IERC721MintableController {
    /**
     * @notice Mint new tokens
     * @param amount The amount to mint
     */
    function mint(uint256 amount) external payable;
}

File 20 of 79 : IERC721Burnable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721BurnableController } from "./IERC721BurnableController.sol";

/**
 * @title ERC721 token burning extension interface
 */
interface IERC721Burnable is IERC721BurnableController {
    /**
     * @notice Burn a token
     * @param tokenId The token id
     */
    function burn(uint256 tokenId) external;
}

File 21 of 79 : IERC721Controller.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721BaseController } from "./base/IERC721BaseController.sol";
import { IERC721ApprovableController } from "./approvable/IERC721ApprovableController.sol";
import { IERC721TransferableController } from "./transferable/IERC721TransferableController.sol";

/**
 * @title Partial ERC721 interface required by controller functions
 */
interface IERC721Controller is
    IERC721TransferableController,
    IERC721ApprovableController,
    IERC721BaseController
{}

File 22 of 79 : IERC721BaseController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Partial ERC721 interface required by controller functions
 */
interface IERC721BaseController {
    error NonExistentToken(uint256 tokenId);
}

File 23 of 79 : IERC721ApprovableController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Partial ERC721 interface required by controller functions
 */
interface IERC721ApprovableController {
    error UnapprovedTokenAction(uint256 tokenId);
    
    error UnapprovedOperatorAction();

    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

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

File 24 of 79 : IERC721TransferableController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Partial ERC721 interface required by controller functions
 */
interface IERC721TransferableController {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
}

File 25 of 79 : IERC721MintableController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721TransferableController } from "../transferable/IERC721TransferableController.sol";

/**
 * @title Partial ERC721 interface required by controller functions
 */
interface IERC721MintableController is IERC721TransferableController {}

File 26 of 79 : IERC721BurnableController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721TransferableController } from "../transferable/IERC721TransferableController.sol";

/**
 * @title Partial ERC721 interface required by controller functions
 */
interface IERC721BurnableController is IERC721TransferableController {}

File 27 of 79 : ERC721MetadataController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ERC721MetadataModel } from "./ERC721MetadataModel.sol";
import { ERC721TokenURIController } from "../tokenURI/ERC721TokenURIController.sol";

abstract contract ERC721MetadataController is
    ERC721MetadataModel,
    ERC721TokenURIController
{
    function ERC721Metadata_(string memory name, string memory symbol) internal virtual {
        _setName(name);
        _setSymbol(symbol);
    }

    function name_() internal view virtual returns (string memory) {
        return _name();
    }

    function symbol_() internal view virtual returns (string memory) {
        return _symbol();
    }
}

File 28 of 79 : ERC721BurnableController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721BurnableController } from "./IERC721BurnableController.sol";
import { ERC721BurnableModel } from "./ERC721BurnableModel.sol";
import { ERC721SupplyController } from "../supply/ERC721SupplyController.sol";
import { ERC721ApprovableController } from "../approvable/ERC721ApprovableController.sol";

abstract contract ERC721BurnableController is
    IERC721BurnableController,
    ERC721BurnableModel,
    ERC721SupplyController,
    ERC721ApprovableController
{
    function burn_(uint256 tokenId) internal virtual {
        address owner = _ownerOf(tokenId);
        _enforceIsApproved(owner, msg.sender, tokenId);
        _burn_(owner, tokenId);
    }

    function _burn_(address owner, uint256 tokenId) internal virtual {
        if (_getApproved(tokenId) != address(0)) {
            _approve_(owner, address(0), tokenId);
        }

        _burn(owner, tokenId);
        _updateMaxSupply(1);

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

    function _burnedSupply() internal view virtual returns (uint256) {
        return _initialSupply() - _maxSupply();
    }
}

File 29 of 79 : IntegerUtils.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Integer utilities
 */
library IntegerUtils {
    error UnexpectedZeroValue();
    error UnexpectedNonZeroValue();
    error OutOfBoundsValue(uint256 value, uint256 length);
    error UnexpectedValue();

    function enforceIsZero(uint256 i) internal pure {
        if (i == 0) {
            return;
        }

        revert UnexpectedNonZeroValue();
    }

    function enforceIsNotZero(uint256 i) internal pure {
        if (i == 0) {
            revert UnexpectedZeroValue();
        }
    }

    function enforceLessThan(uint256 a, uint256 b) internal pure {
        if (a < b) {
            return;
        }

        revert OutOfBoundsValue(a, b);
    }

    function enforceNotLessThan(uint256 a, uint256 b) internal pure {
        if (a < b) {
            revert OutOfBoundsValue(b, a);
        }
    }

    function enforceGreaterThan(uint256 a, uint256 b) internal pure {
        if (a > b) {
            return;
        }

        revert OutOfBoundsValue(b, a);
    }

    function enforceNotGreaterThan(uint256 a, uint256 b) internal pure {
        if (a > b) {
            revert OutOfBoundsValue(a, b);
        }
    }
    
    function enforceEquals(uint256 a, uint256 b) internal pure {
        if (a == b) {
            return;
        }

        revert UnexpectedValue();
    }

    function enforceNotEquals(uint256 a, uint256 b) internal pure {
        if (a == b) {
            revert UnexpectedValue();
        }
    }
}

File 30 of 79 : ERC721MetadataModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { erc721MetadataStorage as es } from "./ERC721MetadataStorage.sol";

abstract contract ERC721MetadataModel {
    function _setName(string memory name) internal virtual {
        es().name = name;
    }

    function _setSymbol(string memory symbol) internal virtual {
        es().symbol = symbol;
    }

    function _name() internal view virtual returns (string memory) {
        return es().name;
    }

    function _symbol() internal view virtual returns (string memory) {
        return es().symbol;
    }
}

File 31 of 79 : ERC721TokenURIController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721TokenURIController } from "./IERC721TokenURIController.sol";
import { ERC721TokenURIModel } from "./ERC721TokenURIModel.sol";
import { ERC721BaseController } from "../base/ERC721BaseController.sol";
import { AddressUtils } from "../../../utils/AddressUtils.sol";

abstract contract ERC721TokenURIController is
    IERC721TokenURIController,
    ERC721TokenURIModel,
    ERC721BaseController
{
    using AddressUtils for address;

    function ERC721TokenURI_(
        uint256 id,
        address provider,
        bool isProxyable
    ) internal virtual {
        _setTokenURIProviderInfo(id, provider, isProxyable);
        _setDefaultTokenURIProvider(id);
    }

    function tokenURI_(uint256 tokenId) internal view virtual returns (string memory) {
        uint256 providerId = tokenURIProvider_(tokenId);
        (address provider, bool isProxyable) = _tokenURIProviderInfo(providerId);

        if (isProxyable) {
            revert UnexpectedTokenURIProvider(providerId);
        }

        return _tokenURI(tokenId, provider);
    }

    function tokenURIProvider_(uint256 tokenId)
        internal
        view
        virtual
        returns (uint256 providerId)
    {
        _enforceTokenExists(tokenId);
        providerId = _tokenURIProvider_(tokenId);
        (address provider, ) = _tokenURIProviderInfo(providerId);
        provider.enforceIsNotZeroAddress();
    }

    function tokenURIProviderInfo_(uint256 providerId)
        internal
        view
        virtual
        returns (address provider, bool isProxyable)
    {
        (provider, isProxyable) = _tokenURIProviderInfo_(providerId);
        provider.enforceIsNotZeroAddress();
    }

    function _tokenURIProvider_(uint256 tokenId)
        internal
        view
        virtual
        returns (uint256 providerId)
    {
        providerId = _tokenURIProvider(tokenId);
        (address provider, ) = _tokenURIProviderInfo(providerId);

        if (provider == address(0)) {
            providerId = _defaultTokenURIProvider();
        }
    }

    function _tokenURIProviderInfo_(uint256 providerId)
        internal
        view
        virtual
        returns (address provider, bool isProxyable)
    {
        (provider, isProxyable) = _tokenURIProviderInfo(providerId);

        if (provider == address(0)) {
            (provider, isProxyable) = _tokenURIProviderInfo(_defaultTokenURIProvider());
        }
    }
}

File 32 of 79 : ERC721MetadataStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

bytes32 constant ERC721_METADATA_STORAGE_SLOT = keccak256("core.token.erc721.metadata.storage");

struct ERC721MetadataStorage {
    string name;
    string symbol;
}

function erc721MetadataStorage() pure returns (ERC721MetadataStorage storage es) {
    bytes32 slot = ERC721_METADATA_STORAGE_SLOT;
    assembly {
        es.slot := slot
    }
}

File 33 of 79 : IERC721TokenURIController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Partial ERC721 interface required by controller functions
 */
interface IERC721TokenURIController {
    error UnexpectedTokenURIProvider(uint256 providerId);
}

File 34 of 79 : ERC721TokenURIModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721TokenURIProvider } from "./IERC721TokenURIProvider.sol";
import { erc721TokenURIStorage as es, ProviderInfo } from "./ERC721TokenURIStorage.sol";

abstract contract ERC721TokenURIModel {
    function _ERC721TokenURI(
        uint256 id,
        address provider,
        bool isProxyable
    ) internal virtual {
        _setTokenURIProviderInfo(id, provider, isProxyable);
        _setDefaultTokenURIProvider(id);
    }

    function _tokenURI(uint256 tokenId, address provider)
        internal
        view
        virtual
        returns (string memory)
    {
        return IERC721TokenURIProvider(provider).tokenURI(tokenId);
    }

    function _setTokenURIProvider(uint256 tokenId, uint256 providerId) internal virtual {
        es().tokenURIProviders[tokenId] = providerId;
    }

    function _setTokenURIProviderInfo(
        uint256 providerId,
        address providerAddress,
        bool isProxyable
    ) internal virtual {
        es().providerInfo[providerId] = ProviderInfo(isProxyable, providerAddress);
    }

    function _setDefaultTokenURIProvider(uint256 providerId) internal virtual {
        es().defaultProvider = providerId;
    }

    function _tokenURIProvider(uint256 tokenId) internal view virtual returns (uint256) {
        return es().tokenURIProviders[tokenId];
    }

    function _tokenURIProviderInfo(uint256 providerId)
        internal
        view
        virtual
        returns (address, bool)
    {
        ProviderInfo memory providerInfo = es().providerInfo[providerId];
        return (providerInfo.providerAddress, providerInfo.isProxyable);
    }

    function _defaultTokenURIProvider() internal view virtual returns (uint256) {
        return es().defaultProvider;
    }
}

File 35 of 79 : ERC721BaseController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721BaseController } from "./IERC721BaseController.sol";
import { ERC721BaseModel } from "./ERC721BaseModel.sol";
import { AddressUtils } from "../../../utils/AddressUtils.sol";

abstract contract ERC721BaseController is IERC721BaseController, ERC721BaseModel {
    using AddressUtils for address;

    function balanceOf_(address owner) internal view virtual returns (uint256) {
        owner.enforceIsNotZeroAddress();
        return _balanceOf(owner);
    }

    function ownerOf_(uint256 tokenId) internal view virtual returns (address owner) {
        owner = _ownerOf(tokenId);
        owner.enforceIsNotZeroAddress();
    }

    function _enforceTokenExists(uint256 tokenId) internal view virtual {
        if (!_tokenExists(tokenId)) {
            revert NonExistentToken(tokenId);
        }
    }
}

File 36 of 79 : AddressUtils.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Address utilities
 */
library AddressUtils {
    error UnexpectedContractAddress();
    error UnexpectedNonContractAddress();
    error UnexpectedZeroAddress();
    error UnexpectedNonZeroAddress();
    error UnexpectedAddress();

    function isContract(address account) internal view returns (bool) {
        return account.code.length > 0;
    }

    function enforceIsContract(address account) internal view {
        if (isContract(account)) {
            return;
        }

        revert UnexpectedNonContractAddress();
    }

    function enforceIsNotContract(address account) internal view {
        if (isContract(account)) {
            revert UnexpectedContractAddress();
        }
    }

    function enforceIsZeroAddress(address account) internal pure {
        if (account == address(0)) {
            return;
        }

        revert UnexpectedNonZeroAddress();
    }

    function enforceIsNotZeroAddress(address account) internal pure {
        if (account == address(0)) {
            revert UnexpectedZeroAddress();
        }
    }

    function enforceEquals(address a, address b) internal pure {
        if (a == b) {
            return;
        }

        revert UnexpectedAddress();
    }

    function enforceNotEquals(address a, address b) internal pure {
        if (a == b) {
            revert UnexpectedAddress();
        }
    }
}

File 37 of 79 : IERC721TokenURIProvider.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721 token URI provider interface
 */
interface IERC721TokenURIProvider {
    /**
     * @notice Get the URI of a token
     * @param tokenId The token id
     * @return tokenURI The token URI
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 38 of 79 : ERC721TokenURIStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

bytes32 constant ERC721_TOKEN_URI_STORAGE_SLOT = keccak256("core.token.erc721.tokenURI.storage");

struct ProviderInfo {
    bool isProxyable;
    address providerAddress;
}

struct ERC721TokenURIStorage {
    uint256 defaultProvider;
    mapping(uint256 => uint256) tokenURIProviders;
    mapping(uint256 => ProviderInfo) providerInfo;
}

function erc721TokenURIStorage() pure returns (ERC721TokenURIStorage storage es) {
    bytes32 slot = ERC721_TOKEN_URI_STORAGE_SLOT;
    assembly {
        es.slot := slot
    }
}

File 39 of 79 : ERC721BaseModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { erc721BaseStorage, ERC721BaseStorage } from "./ERC721BaseStorage.sol";
import { ERC721TokenUtils } from "../utils/ERC721TokenUtils.sol";
import { ERC721InventoryUtils } from "../utils/ERC721InventoryUtils.sol";

abstract contract ERC721BaseModel {
    using ERC721TokenUtils for uint256;
    using ERC721InventoryUtils for uint256;
    
    function _balanceOf(address owner) internal view virtual returns (uint256) {
        return erc721BaseStorage().inventories[owner].balance();
    }
    
    function _ownerOf(uint256 tokenId) internal view virtual returns (address owner) {
        ERC721BaseStorage storage es = erc721BaseStorage();
        owner = es.owners[tokenId];

        if (owner == address(0)) {
            address holder = tokenId.holder();
            if (es.inventories[holder].has(tokenId.index())) {
                owner = holder;
            }
        }
    }

    function _tokenExists(uint256 tokenId) internal view virtual returns (bool) {
        ERC721BaseStorage storage es = erc721BaseStorage();

        if (es.owners[tokenId] == address(0)) {
            return es.inventories[tokenId.holder()].has(tokenId.index());
        }
        
        return true;
    }
}

File 40 of 79 : ERC721BaseStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

bytes32 constant ERC721_BASE_STORAGE_SLOT = keccak256("core.token.erc721.base.storage");

struct ERC721BaseStorage {
    mapping(uint256 => address) owners;
    mapping(address => uint256) inventories;
}

function erc721BaseStorage() pure returns (ERC721BaseStorage storage es) {
    bytes32 slot = ERC721_BASE_STORAGE_SLOT;
    assembly {
        es.slot := slot
    }
}

File 41 of 79 : ERC721TokenUtils.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721 token utilities
 */
library ERC721TokenUtils {
    uint256 constant HOLDER_OFFSET = 8;
    uint256 constant INDEX_BITMASK = (1 << HOLDER_OFFSET) - 1; // = 0xFF

    function toTokenId(address owner) internal pure returns (uint256) {
        return uint256(uint160(owner)) << HOLDER_OFFSET;
    }

    function index(uint256 tokenId) internal pure returns (uint256) {
        return tokenId & INDEX_BITMASK;
    }

    function holder(uint256 tokenId) internal pure returns (address) {
        return address(uint160(tokenId >> HOLDER_OFFSET));
    }
}

File 42 of 79 : ERC721InventoryUtils.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { BitmapUtils } from "../../../utils/BitmapUtils.sol";

/**
 * @title ERC721 token inventory utilities
 */
library ERC721InventoryUtils {
    using BitmapUtils for uint256;

    uint256 constant BALANCE_BITSIZE = 16;
    uint256 constant BALANCE_BITMASK = (1 << BALANCE_BITSIZE) - 1;              // = 0xFFFF;
    uint256 constant CURRENT_SLOT_BITSIZE = 8;
    uint256 constant CURRENT_SLOT_BITMASK = (1 << CURRENT_SLOT_BITSIZE) - 1;    // = 0xFF;
    uint256 constant BITMAP_OFFSET = BALANCE_BITSIZE + CURRENT_SLOT_BITSIZE;    // = 24
    uint256 constant SLOTS_PER_INVENTORY = 256 - BITMAP_OFFSET;                 // = 232

    function balance(uint256 inventory) internal pure returns (uint256) {
        return inventory & BALANCE_BITMASK;
    }

    function current(uint256 inventory) internal pure returns (uint256) {
        return (inventory >> BALANCE_BITSIZE) & CURRENT_SLOT_BITMASK;
    }

    function has(uint256 inventory, uint256 index) internal pure returns (bool) {
        return inventory.isSet(BITMAP_OFFSET + index);
    }

    function add(uint256 inventory, uint256 amount) internal pure returns (uint256) {
        return
            inventory.setRange(BITMAP_OFFSET + current(inventory), amount) +
            (amount << BALANCE_BITSIZE) +
            amount;
    }

    function remove(uint256 inventory, uint256 index) internal pure returns (uint256) {
        return inventory.unset(BITMAP_OFFSET + index) - 1;
    }
}

File 43 of 79 : BitmapUtils.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Bitmap utilities
 */
library BitmapUtils {
    function get(uint256 bitmap, uint256 index) internal pure returns (uint256) {
        return (bitmap >> index) & 1;
    }

    function isSet(uint256 bitmap, uint256 index) internal pure returns (bool) {
        return get(bitmap, index) == 1;
    }

    function set(uint256 bitmap, uint256 index) internal pure returns (uint256) {
        return bitmap | (1 << index);
    }

    function setRange(uint256 bitmap, uint256 offset, uint256 amount) internal pure returns (uint256) {
        return bitmap | (((1 << amount) - 1) << offset);
    }

    function unset(uint256 bitmap, uint256 index) internal pure returns (uint256) {
        return bitmap & toggle(type(uint256).max, index);
    }
    
    function unsetRange(uint256 bitmap, uint256 offset, uint256 amount) internal pure returns (uint256) {
        return bitmap & toggleRange(type(uint256).max, offset, amount);
    }

    function toggle(uint256 bitmap, uint256 index) internal pure returns (uint256) {
        return bitmap ^ (1 << index);
    }

    function toggleRange(uint256 bitmap, uint256 offset, uint256 amount) internal pure returns (uint256) {
        return bitmap ^ (((1 << amount) - 1) << offset);
    }
}

File 44 of 79 : ERC721MintableModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { erc721BaseStorage, ERC721BaseStorage } from "../base/ERC721BaseStorage.sol";
import { ERC721InventoryUtils } from "../utils/ERC721InventoryUtils.sol";

abstract contract ERC721MintableModel {
    using ERC721InventoryUtils for uint256;

    function _maxMintBalance() internal view virtual returns (uint256) {
        return ERC721InventoryUtils.SLOTS_PER_INVENTORY;
    }

    function _mintBalanceOf(address owner) internal view virtual returns (uint256) {
        return erc721BaseStorage().inventories[owner].current();
    }

    function _mint(address to, uint256 amount) internal virtual {
        ERC721BaseStorage storage es = erc721BaseStorage();
        es.inventories[to] = es.inventories[to].add(amount);
    }
}

File 45 of 79 : ERC721SupplyController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ERC721SupplyModel } from "./ERC721SupplyModel.sol";

abstract contract ERC721SupplyController is ERC721SupplyModel {
    function ERC721Supply_(uint256 supply) internal virtual {
        _setInitialSupply(supply);
        _setMaxSupply(supply);
        _setAvailableSupply(supply);
    }

    function _updateSupply(uint256 supply) internal virtual {
        _setInitialSupply(_initialSupply() + supply);
        _setMaxSupply(_maxSupply() + supply);
        _setAvailableSupply(_availableSupply() + supply);
    }
}

File 46 of 79 : ERC721SupplyModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { erc721SupplyStorage as es } from "./ERC721SupplyStorage.sol";

abstract contract ERC721SupplyModel {
    function _initialSupply() internal view virtual returns (uint256) {
        return es().initialSupply;
    }

    function _maxSupply() internal view virtual returns (uint256) {
        return es().maxSupply;
    }

    function _availableSupply() internal view virtual returns (uint256) {
        return es().availableSupply;
    }

    function _setInitialSupply(uint256 supply) internal virtual {
        es().initialSupply = supply;
    }

    function _setMaxSupply(uint256 supply) internal virtual {
        es().maxSupply = supply;
    }

    function _setAvailableSupply(uint256 supply) internal virtual {
        es().availableSupply = supply;
    }

    function _updateInitialSupply(uint256 amount) internal virtual {
        es().initialSupply -= amount;
    }

    function _updateMaxSupply(uint256 amount) internal virtual {
        es().maxSupply -= amount;
    }

    function _updateAvailableSupply(uint256 amount) internal virtual {
        es().availableSupply -= amount;
    }
}

File 47 of 79 : ERC721SupplyStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

bytes32 constant ERC721_SUPPLY_STORAGE_SLOT = keccak256(
    "core.token.erc721.supply.storage"
);

struct ERC721SupplyStorage {
    uint256 initialSupply;
    uint256 maxSupply;
    uint256 availableSupply;
}

function erc721SupplyStorage() pure returns (ERC721SupplyStorage storage es) {
    bytes32 slot = ERC721_SUPPLY_STORAGE_SLOT;
    assembly {
        es.slot := slot
    }
}

File 48 of 79 : ERC721BurnableModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { erc721BaseStorage, ERC721BaseStorage } from "../base/ERC721BaseStorage.sol";
import { ERC721TokenUtils } from "../utils/ERC721TokenUtils.sol";
import { ERC721InventoryUtils } from "../utils/ERC721InventoryUtils.sol";

abstract contract ERC721BurnableModel {
    using ERC721TokenUtils for uint256;
    using ERC721InventoryUtils for uint256;

    function _burn(address owner, uint256 tokenId) internal virtual {
        ERC721BaseStorage storage es = erc721BaseStorage();

        if (es.owners[tokenId] == owner) {
            delete es.owners[tokenId];
            es.inventories[owner]--;
        } else {
            es.inventories[owner] = es.inventories[owner].remove(
                tokenId.index()
            );
        }
    }
}

File 49 of 79 : ERC721ApprovableController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721ApprovableController } from "./IERC721ApprovableController.sol";
import { ERC721ApprovableModel } from "./ERC721ApprovableModel.sol";
import { ERC721BaseController } from "../base/ERC721BaseController.sol";
import { AddressUtils } from "../../../utils/AddressUtils.sol";

abstract contract ERC721ApprovableController is
    IERC721ApprovableController,
    ERC721ApprovableModel,
    ERC721BaseController
{
    using AddressUtils for address;

    function approve_(address approved, uint256 tokenId) internal virtual {
        address owner = _ownerOf(tokenId);
        owner.enforceNotEquals(approved);
        _enforceIsApproved(owner, msg.sender);
        _approve_(owner, approved, tokenId);
    }

    function setApprovalForAll_(address operator, bool approved) internal virtual {
        operator.enforceIsNotZeroAddress();
        operator.enforceNotEquals(msg.sender);
        _setApprovalForAll_(msg.sender, operator, approved);
    }

    function getApproved_(uint256 tokenId) internal view virtual returns (address) {
        _enforceTokenExists(tokenId);
        return _getApproved(tokenId);
    }

    function isApprovedForAll_(address owner, address operator)
        internal
        view
        virtual
        returns (bool)
    {
        return _isApprovedForAll(owner, operator);
    }

    function _approve_(
        address owner,
        address approved,
        uint256 tokenId
    ) internal virtual {
        _approve(approved, tokenId);
        emit Approval(owner, approved, tokenId);
    }

    function _setApprovalForAll_(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        _setApprovalForAll(owner, operator, approved);
        emit ApprovalForAll(owner, operator, approved);
    }

    function _isApproved(address owner, address operator)
        internal
        view
        virtual
        returns (bool)
    {
        return owner == operator || _isApprovedForAll(owner, operator);
    }

    function _isApproved(
        address owner,
        address operator,
        uint256 tokenId
    ) internal view virtual returns (bool) {
        return _isApproved(owner, operator) || _getApproved(tokenId) == operator;
    }

    function _enforceIsApproved(address owner, address operator) internal view virtual {
        if (!_isApproved(owner, operator)) {
            revert UnapprovedOperatorAction();
        }
    }

    function _enforceIsApproved(
        address owner,
        address operator,
        uint256 tokenId
    ) internal view virtual {
        if (!_isApproved(owner, operator, tokenId)) {
            revert UnapprovedTokenAction(tokenId);
        }
    }
}

File 50 of 79 : ERC721ApprovableModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { erc721ApprovableStorage as es } from "./ERC721ApprovableStorage.sol";

abstract contract ERC721ApprovableModel {
    function _approve(address approved, uint256 tokenId) internal virtual {
        es().tokenApprovals[tokenId] = approved;
    }

    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        es().operatorApprovals[owner][operator] = approved;
    }

    function _getApproved(uint256 tokenId) internal view virtual returns (address) {
        return es().tokenApprovals[tokenId];
    }

    function _isApprovedForAll(address owner, address operator)
        internal
        view
        virtual
        returns (bool)
    {
        return es().operatorApprovals[owner][operator];
    }
}

File 51 of 79 : ERC721ApprovableStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

bytes32 constant ERC721_APPROVABLE_STORAGE_SLOT = keccak256("core.token.erc721.approvable.storage");

struct ERC721ApprovableStorage {
    mapping(uint256 => address) tokenApprovals;
    mapping(address => mapping(address => bool)) operatorApprovals;
}

function erc721ApprovableStorage() pure returns (ERC721ApprovableStorage storage es) {
    bytes32 slot = ERC721_APPROVABLE_STORAGE_SLOT;
    assembly {
        es.slot := slot
    }
}

File 52 of 79 : ERC165Controller.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ERC165Model } from "./ERC165Model.sol";

abstract contract ERC165Controller is ERC165Model {
    function supportsInterface_(bytes4 interfaceId) internal view virtual returns (bool) {
        return _supportsInterface(interfaceId);
    }

    function _setSupportedInterfaces(bytes4[] memory interfaceIds, bool isSupported)
        internal
        virtual
    {
        unchecked {
            for (uint256 i; i < interfaceIds.length; i++) {
                _setSupportedInterface(interfaceIds[i], isSupported);
            }
        }
    }
}

File 53 of 79 : ProxyUpgradableController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ProxyController } from "../ProxyController.sol";

abstract contract ProxyUpgradableController is ProxyController {
    modifier upgradable() {
        address implementation = implementation_();
        
         if (implementation == address(this)) {
            _;
        } else {
            _delegate(implementation);
        }
    }
}

File 54 of 79 : ERC165Model.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { erc165Storage as es } from "./ERC165Storage.sol";

abstract contract ERC165Model {
    function _supportsInterface(bytes4 interfaceId) internal view virtual returns (bool) {
        return es().supportedInterfaces[interfaceId];
    }

    function _setSupportedInterface(bytes4 interfaceId, bool isSupported)
        internal
        virtual
    {
        es().supportedInterfaces[interfaceId] = isSupported;
    }
}

File 55 of 79 : ERC165Storage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

bytes32 constant ERC165_STORAGE_SLOT = keccak256("core.introspection.erc165.storage");

struct ERC165Storage {
    mapping(bytes4 => bool) supportedInterfaces;
}

function erc165Storage() pure returns (ERC165Storage storage es) {
    bytes32 slot = ERC165_STORAGE_SLOT;
    assembly {
        es.slot := slot
    }
}

File 56 of 79 : ProxyController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ProxyModel } from "./ProxyModel.sol";
import { AddressUtils } from "../utils/AddressUtils.sol";
import { IntegerUtils } from "../utils/IntegerUtils.sol";

abstract contract ProxyController is ProxyModel {
    using AddressUtils for address;
    using IntegerUtils for uint256;

    function Proxy_(address init, bytes memory data) internal virtual {
        data.length.enforceIsNotZero();
        init.enforceIsContract();
        _Proxy(init, data);
    }

    function fallback_() internal virtual {
        _delegate(implementation_());
    }

    function implementation_() internal view virtual returns (address);
}

File 57 of 79 : ProxyModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

abstract contract ProxyModel {
    function _Proxy(address init, bytes memory data) internal virtual {
        (bool success, bytes memory reason) = init.delegatecall(data);

        if (!success) {
            assembly {
                revert(add(reason, 0x20), mload(reason))
            }
        }
    }

    function _delegate(address implementation) internal virtual {
        assembly {
            calldatacopy(0, 0, calldatasize())

            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            returndatacopy(0, 0, returndatasize())

            switch result
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }
}

File 58 of 79 : ERC721Controller.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721Controller } from "./IERC721Controller.sol";
import { ERC721BaseController } from "./base/ERC721BaseController.sol";
import { ERC721ApprovableController } from "./approvable/ERC721ApprovableController.sol";
import { ERC721TransferableController } from "./transferable/ERC721TransferableController.sol";

abstract contract ERC721Controller is
    IERC721Controller,
    ERC721BaseController,
    ERC721ApprovableController,
    ERC721TransferableController
{}

File 59 of 79 : ERC721TransferableController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721TransferableController } from "./IERC721TransferableController.sol";
import { ERC721TransferableModel } from "./ERC721TransferableModel.sol";
import { ERC721ApprovableController } from "../approvable/ERC721ApprovableController.sol";
import { ERC721ReceiverUtils } from "../utils/ERC721ReceiverUtils.sol";
import { AddressUtils } from "../../../utils/AddressUtils.sol";

abstract contract ERC721TransferableController is
    IERC721TransferableController,
    ERC721TransferableModel,
    ERC721ApprovableController
{
    using ERC721ReceiverUtils for address;
    using AddressUtils for address;

    function safeTransferFrom_(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        if (to.isContract()) {
            to.enforceNotEquals(from);
            _enforceCanTransferFrom(from, to, tokenId);
            _transferFrom_(from, to, tokenId);
            to.enforceOnReceived(msg.sender, from, tokenId, data);
        } else {
            transferFrom_(from, to, tokenId);
        }
    }

    function transferFrom_(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        to.enforceIsNotZeroAddress();
        to.enforceNotEquals(from);
        _enforceCanTransferFrom(from, to, tokenId);
        _transferFrom_(from, to, tokenId);
    }

    function _transferFrom_(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        if (_getApproved(tokenId) != address(0)) {
            _approve_(from, address(0), tokenId);
        }

        _transferFrom(from, to, tokenId);
        emit Transfer(from, to, tokenId);
    }

    function _enforceCanTransferFrom(
        address from,
        address,
        uint256 tokenId
    ) internal view virtual {
        from.enforceEquals(_ownerOf(tokenId));
        _enforceIsApproved(from, msg.sender, tokenId);
    }
}

File 60 of 79 : ERC721TransferableModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { erc721BaseStorage, ERC721BaseStorage } from "../base/ERC721BaseStorage.sol";
import { ERC721TokenUtils } from "../utils/ERC721TokenUtils.sol";
import { ERC721InventoryUtils } from "../utils/ERC721InventoryUtils.sol";

abstract contract ERC721TransferableModel {
    using ERC721TokenUtils for uint256;
    using ERC721InventoryUtils for uint256;

    function _transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        ERC721BaseStorage storage es = erc721BaseStorage();

        if (es.owners[tokenId] == from) {
            es.inventories[from]--;
        } else {
            es.inventories[from] = es.inventories[from].remove(tokenId.index());
        }

        es.owners[tokenId] = to;
        es.inventories[to]++;
    }
}

File 61 of 79 : ERC721ReceiverUtils.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721Receiver } from "../IERC721Receiver.sol";

/**
 * @title ERC721 token receiver utilities
 */
library ERC721ReceiverUtils {
    error UnexpectedNonERC721Receiver(address receiver);

    function enforceOnReceived(
        address to,
        address operator,
        address from,
        uint256 tokenId,
        bytes memory data
    ) internal {
        if (checkOnERC721Received(to, operator, from, tokenId, data)) {
            return;
        }

        revert UnexpectedNonERC721Receiver(to);
    }
    
    function checkOnERC721Received(
        address to,
        address operator,
        address from,
        uint256 tokenId,
        bytes memory data
    ) internal returns (bool) {
        try
            IERC721Receiver(to).onERC721Received(operator, from, tokenId, data)
        returns (bytes4 retval) {
            return retval == IERC721Receiver.onERC721Received.selector;
        } catch (bytes memory) {
            return false;
        }
    }
}

File 62 of 79 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Receiver {
    /**
     * @notice Handle the receipt of a token
     * @param operator The operator's address
     * @param from The previous owner's address
     * @param tokenId The token id
     * @param data Additional data
     * @return selector The function selector
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 63 of 79 : ERC721TokenURIProxyController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ERC721TokenURIController } from "./ERC721TokenURIController.sol";
import { ProxyController } from "../../../proxy/ProxyController.sol";

abstract contract ERC721TokenURIProxyController is
    ERC721TokenURIController,
    ProxyController
{
    function tokenURIProxyable_(uint256 tokenId)
        internal
        virtual
        returns (string memory)
    {
        uint256 providerId = tokenURIProvider_(tokenId);
        (address provider, bool isProxyable) = _tokenURIProviderInfo(providerId);

        if (isProxyable) {
            _delegate(provider);
        } else {
            return _tokenURI(tokenId, provider);
        }
    }
}

File 64 of 79 : ERC721EnumerableController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ERC721EnumerableModel } from "./ERC721EnumerableModel.sol";
import { ERC721SupplyController } from "../supply/ERC721SupplyController.sol";
import { ERC721BaseController } from "../base/ERC721BaseController.sol";
import { IntegerUtils } from "../../../utils/IntegerUtils.sol";

abstract contract ERC721EnumerableController is
    ERC721EnumerableModel,
    ERC721SupplyController,
    ERC721BaseController
{
    using IntegerUtils for uint256;

    function totalSupply_() internal view virtual returns (uint256) {
        return _maxSupply() - _availableSupply();
    }

    function tokenByIndex_(uint256 index) internal view virtual returns (uint256) {
        index.enforceLessThan(totalSupply_());
        return _tokenByIndex_(index);
    }

    function tokenOfOwnerByIndex_(address owner, uint256 index)
        internal
        view
        virtual
        returns (uint256)
    {
        index.enforceLessThan(_balanceOf(owner));
        return _tokenOfOwnerByIndex_(owner, index);
    }

    function _tokenOfOwnerByIndex_(address owner, uint256 index)
        internal
        view
        virtual
        returns (uint256 tokenId)
    {
        unchecked {
            index++;
            for (uint256 i; index > 0; i++) {
                if (_ownerOf(tokenId = _tokenByIndex(i)) == owner) {
                    index--;
                }
            }
        }
    }

    function _tokenByIndex_(uint256 index) internal view returns (uint256 tokenId) {
        unchecked {
            index++;
            for (uint256 i; index > 0; i++) {
                if (_tokenExists(tokenId = _tokenByIndex(i))) {
                    index--;
                }
            }
        }
    }
}

File 65 of 79 : ERC721EnumerableModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC721EnumerablePage } from "./IERC721EnumerablePage.sol";
import { erc721EnumerableStorage, ERC721EnumerableStorage, PageInfo } from "./ERC721EnumerableStorage.sol";

abstract contract ERC721EnumerableModel {
    function _ERC721Enumerable(PageInfo[] memory pages) internal virtual {
        erc721EnumerableStorage().pages = pages;
    }

    function _tokenByIndex(uint256 index)
        internal
        view
        virtual
        returns (uint256 tokenId)
    {
        ERC721EnumerableStorage storage es = erc721EnumerableStorage();

        unchecked {
            for (uint256 i; i < es.pages.length; i++) {
                PageInfo memory page = es.pages[i];

                if (index < page.length) {
                    return IERC721EnumerablePage(page.pageAddress).tokenByIndex(index);
                }
                
                index -= page.length;
            }
        }
    }
}

File 66 of 79 : IERC721EnumerablePage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721 enumerable page interface
 */
interface IERC721EnumerablePage {
    /**
     * @notice Get a token by enumeration index
     * @param index The token position
     * @return tokenId The token id
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

File 67 of 79 : ERC721EnumerableStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

bytes32 constant ERC721_ENUMERABLE_STORAGE_SLOT = keccak256("core.token.erc721.enumerable.storage");

struct PageInfo {
    uint16 length;
    address pageAddress;
}

struct ERC721EnumerableStorage {
    PageInfo[] pages;
}

function erc721EnumerableStorage() pure returns (ERC721EnumerableStorage storage es) {
    bytes32 slot = ERC721_ENUMERABLE_STORAGE_SLOT;
    assembly {
        es.slot := slot
    }
}

File 68 of 79 : ISafeOwnable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC173 } from "../../IERC173.sol";

/**
 * @title ERC173 safe ownership access control interface
 */
interface ISafeOwnable is IERC173 {
    /**
     * @notice Get the nominated owner
     * @return nomineeOwner The nominated owner's address
     */
    function nomineeOwner() external returns (address);

    /**
     * @notice Accept contract ownership
     */
    function acceptOwnership() external;
}

File 69 of 79 : SafeOwnableController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { SafeOwnableModel } from "./SafeOwnableModel.sol";
import { OwnableController } from "../OwnableController.sol";
import { AddressUtils } from "../../../utils/AddressUtils.sol";

abstract contract SafeOwnableController is SafeOwnableModel, OwnableController {
    using AddressUtils for address;

    modifier onlyNomineeOwner() {
        _enforceOnlyNomineeOwner();
        _;
    }

    function nomineeOwner_() internal view virtual returns (address) {
        return _nomineeOwner();
    }

    function acceptOwnership_() internal virtual {
        transferOwnership_(_nomineeOwner());
        _setNomineeOwner(address(0));
    }

    function _enforceOnlyNomineeOwner() internal view virtual {
        msg.sender.enforceEquals(_nomineeOwner());
    }
}

File 70 of 79 : OwnableProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC173 } from "../IERC173.sol";
import { OwnableController } from "./OwnableController.sol";
import { ProxyUpgradableController } from "../../proxy/upgradable/ProxyUpgradableController.sol";

/**
 * @title ERC173 ownership access control implementation
 * @dev Note: Upgradable implementation
 */
abstract contract OwnableProxy is IERC173, OwnableController, ProxyUpgradableController {
    /**
     * @inheritdoc IERC173
     */
    function owner() external virtual upgradable returns (address) {
        return owner_();
    }

    /**
     * @inheritdoc IERC173
     */
    function transferOwnership(address newOwner) external virtual upgradable onlyOwner {
        transferOwnership_(newOwner);
    }
}

File 71 of 79 : IERC173.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC173Controller } from "./IERC173Controller.sol";

/**
 * @title ERC173 interface
 * @dev See https://eips.ethereum.org/EIPS/eip-173
 */
interface IERC173 is IERC173Controller {
    /**
     * @notice Get the contract owner
     * @return owner The owner's address
     */
    function owner() external returns (address);

    /**
     * @notice Transfer ownership to new owner
     * @param newOwner The new owner's address
     */
    function transferOwnership(address newOwner) external;
}

File 72 of 79 : IERC173Controller.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Partial ERC173 interface required by controller functions
 */
interface IERC173Controller {
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
}

File 73 of 79 : SafeOwnableModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { safeOwnableStorage as os } from "./SafeOwnableStorage.sol";

abstract contract SafeOwnableModel {
    function _nomineeOwner() internal view virtual returns (address) {
        return os().nomineeOwner;
    }

    function _setNomineeOwner(address nomineeOwner) internal virtual {
        os().nomineeOwner = nomineeOwner;
    }
}

File 74 of 79 : OwnableController.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC173Controller } from "../IERC173Controller.sol";
import { OwnableModel } from "./OwnableModel.sol";
import { AddressUtils } from "../../utils/AddressUtils.sol";

abstract contract OwnableController is IERC173Controller, OwnableModel {
    using AddressUtils for address;

    modifier onlyOwner() {
        _enforceOnlyOwner();
        _;
    }

    function Ownable_() internal virtual {
        Ownable_(msg.sender);
    }

    function Ownable_(address owner) internal virtual {
        transferOwnership_(owner);
    }

    function owner_() internal view virtual returns (address) {
        return _owner();
    }

    function transferOwnership_(address newOwner) internal virtual {
        _transferOwnership(newOwner);
        emit OwnershipTransferred(_owner(), newOwner);
    }

    function _enforceOnlyOwner() internal view virtual {
        msg.sender.enforceEquals(_owner());
    }
}

File 75 of 79 : SafeOwnableStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

bytes32 constant SAFE_OWNABLE_STORAGE_SLOT = keccak256("core.access.ownable.safe.storage");

struct SafeOwnableStorage {
    address nomineeOwner;
}

function safeOwnableStorage() pure returns (SafeOwnableStorage storage os) {
    bytes32 slot = SAFE_OWNABLE_STORAGE_SLOT;
    assembly {
        os.slot := slot
    }
}

File 76 of 79 : OwnableModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ownableStorage as os } from "./OwnableStorage.sol";

abstract contract OwnableModel {
    function _owner() internal view virtual returns (address) {
        return os().owner;
    }

    function _transferOwnership(address newOwner) internal virtual {
        os().owner = newOwner;
    }
}

File 77 of 79 : OwnableStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

bytes32 constant OWNABLE_STORAGE_SLOT = keccak256("core.access.ownable.storage");

struct OwnableStorage {
    address owner;
}

function ownableStorage() pure returns (OwnableStorage storage os) {
    bytes32 slot = OWNABLE_STORAGE_SLOT;
    assembly {
        os.slot := slot
    }
}

File 78 of 79 : ProxyFacetedModel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { proxyFacetedStorage, ProxyFacetedStorage, SelectorInfo, ImplementationInfo } from "./ProxyFacetedStorage.sol";

abstract contract ProxyFacetedModel {
    function _implementation(bytes4 selector) internal view virtual returns (address) {
        return proxyFacetedStorage().selectorInfo[selector].implementation;
    }

    function _addFunction(
        bytes4 selector,
        address implementation,
        bool isUpgradable
    ) internal virtual {
        ProxyFacetedStorage storage ps = proxyFacetedStorage();
        ps.selectorInfo[selector] = SelectorInfo(
            isUpgradable,
            uint16(ps.selectors.length),
            implementation
        );
        ps.selectors.push(selector);
    }

    function _replaceFunction(bytes4 selector, address implementation) internal virtual {
        proxyFacetedStorage().selectorInfo[selector].implementation = implementation;
    }

    function _removeFunction(bytes4 selector) internal virtual {
        ProxyFacetedStorage storage ps = proxyFacetedStorage();
        uint16 position = ps.selectorInfo[selector].position;
        uint256 lastPosition = ps.selectors.length - 1;

        if (position != lastPosition) {
            bytes4 lastSelector = ps.selectors[lastPosition];
            ps.selectors[position] = lastSelector;
            ps.selectorInfo[lastSelector].position = position;
        }

        ps.selectors.pop();
        delete ps.selectorInfo[selector];
    }

    function _afterAddFunction(address implementation) internal virtual {
        ProxyFacetedStorage storage ps = proxyFacetedStorage();
        ImplementationInfo memory info = ps.implementationInfo[implementation];

        if (++info.selectorCount == 1) {
            info.position = uint16(ps.implementations.length);
            ps.implementations.push(implementation);
        }

        ps.implementationInfo[implementation] = info;
    }

    function _afterRemoveFunction(address implementation) internal virtual {
        ProxyFacetedStorage storage ps = proxyFacetedStorage();
        ImplementationInfo memory info = ps.implementationInfo[implementation];

        if (--info.selectorCount == 0) {
            uint16 position = info.position;
            uint256 lastPosition = ps.implementations.length - 1;

            if (position != lastPosition) {
                address lastImplementation = ps.implementations[lastPosition];
                ps.implementations[position] = lastImplementation;
                ps.implementationInfo[lastImplementation].position = position;
            }

            ps.implementations.pop();
            delete ps.implementationInfo[implementation];
        } else {
            ps.implementationInfo[implementation] = info;
        }
    }

    function _setUpgradableFunction(bytes4 selector, bool isUpgradable) internal virtual {
        proxyFacetedStorage().selectorInfo[selector].isUpgradable = isUpgradable;
    }

    function _isUpgradable(bytes4 selector) internal view virtual returns (bool) {
        return proxyFacetedStorage().selectorInfo[selector].isUpgradable;
    }
}

File 79 of 79 : ProxyFacetedStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

bytes32 constant FACETED_PROXY_STORAGE_SLOT = keccak256("core.proxy.faceted.storage");

struct SelectorInfo {
    bool isUpgradable;
    uint16 position;
    address implementation;
}

struct ImplementationInfo {
    uint16 position;
    uint16 selectorCount;
}

struct ProxyFacetedStorage {
    mapping(bytes4 => SelectorInfo) selectorInfo;
    bytes4[] selectors;
    mapping(address => ImplementationInfo) implementationInfo;
    address[] implementations;
}

function proxyFacetedStorage() pure returns (ProxyFacetedStorage storage ps) {
    bytes32 slot = FACETED_PROXY_STORAGE_SLOT;
    assembly {
        ps.slot := slot
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"init","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NonExistentToken","type":"error"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"length","type":"uint256"}],"name":"OutOfBoundsValue","type":"error"},{"inputs":[],"name":"UnapprovedOperatorAction","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"UnapprovedTokenAction","type":"error"},{"inputs":[],"name":"UnexpectedAddress","type":"error"},{"inputs":[],"name":"UnexpectedNonContractAddress","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"UnexpectedNonERC721Receiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"providerId","type":"uint256"}],"name":"UnexpectedTokenURIProvider","type":"error"},{"inputs":[],"name":"UnexpectedValue","type":"error"},{"inputs":[],"name":"UnexpectedZeroAddress","type":"error"},{"inputs":[],"name":"UnexpectedZeroValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","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":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"availableSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"mintBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nomineeOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","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":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234620000e357620026fd803803806200001d816200012e565b9283398101604082820312620000e35781516001600160a01b0381168103620000e35760208381015190936001600160401b038211620000e3570182601f82011215620000e3578051906200007c620000768362000154565b6200012e565b93828552858383010111620000e357936000945b828610620000cd575081620000ae9511620000be575b505062000182565b60405161209d9081620006208239f35b600091840101523880620000a6565b8581018201518587018301529481019462000090565b600080fd5b50634e487b7160e01b600052604160045260246000fd5b60408051919082016001600160401b038111838210176200011f57604052565b62000129620000e8565b604052565b6040519190601f01601f191682016001600160401b038111838210176200011f57604052565b6020906001600160401b03811162000172575b601f01601f19160190565b6200017c620000e8565b62000167565b91906200018e620000ff565b9260078452602093664d75747974657360c81b85820152620001af620000ff565b60048152635459544560e01b86820152815190956001600160401b038211620002fe575b600080516020620026bd83398151915292620001fb83620001f58654620003f2565b6200042f565b81601f841160011462000259575091806200023b94926200024b9899946000926200024d575b50508160011b916000199060031b1c1916179055620004fd565b620002456200030e565b62000369565b565b01519050388062000221565b600080516020620026bd8339815191526000529190601f1984167fa4b58ba3ac2b3947060498ebdbcff1d26efc6a4642c1d6ae2206de97a9be5491936000905b828210620002e55750509260019285926200024b9a9b966200023b989610620002cb575b505050811b019055620004fd565b015160001960f88460031b161c19169055388080620002bd565b8060018697829497870151815501960194019062000299565b62000308620000e8565b620001d3565b7f311bbfc7ad6a9098c3613fdc40ca4709ae1e5cdd3ef27b14dc8d504b8a91a55c3360018060a01b031982541617905533337f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e06000604051a3565b815115620003c85760009181620003818493620003da565b602082519201905af43d15620003bf573d90620003a2620000768362000154565b9182523d6000602084013e5b15620003b75750565b602081519101fd5b606090620003ae565b6040516375a0be4160e01b8152600490fd5b3b6200024b576040516314b1fc2360e31b8152600490fd5b90600182811c9216801562000424575b60208310146200040e57565b634e487b7160e01b600052602260045260246000fd5b91607f169162000402565b601f81116200043c575050565b600090600080516020620026bd833981519152825260208220906020601f850160051c830194106200048b575b601f0160051c01915b8281106200047f57505050565b81815560010162000472565b909250829062000469565b601f8111620004a3575050565b600090600080516020620026dd833981519152825260208220906020601f850160051c83019410620004f2575b601f0160051c01915b828110620004e657505050565b818155600101620004d9565b9092508290620004d0565b80519091906001600160401b0381116200060f575b600080516020620026dd833981519152906200053a81620005348454620003f2565b62000496565b602080601f8311600114620005795750819293946000926200056d575b50508160011b916000199060031b1c1916179055565b01519050388062000557565b600080516020620026dd833981519152600052601f198316959091907fca2c8f0030a855398300b0e4b8dd828e333842258e8e6ae862e623c794c647e0926000905b888210620005f657505083600195969710620005dc575b505050811b019055565b015160001960f88460031b161c19169055388080620005d2565b80600185968294968601518155019501930190620005bb565b62000619620000e8565b6200051256fe6080604052600436101561002c575b361561001f575b61001d6112a4565b005b6100276112a4565b610015565b60003560e01c806301ffc9a71461020c57806306fdde0314610203578063081812fc146101fa578063095ea7b3146101f157806318160ddd146101e857806323b872dd146101df5780632f745c59146101d657806342842e0e146101cd57806342966c68146101c45780634f6ccce7146101bb578063630a3d26146101b25780636352211e146101a957806370a08231146101a057806379ba5097146101975780637ecc2b561461018e5780638ab5150a146101855780638da5cb5b1461017c57806395d89b4114610173578063a0712d681461016a578063a22cb46514610161578063b88d4fde14610158578063c87b56dd1461014f578063e985e9c5146101465763f2fde38b0361000e576101416111ee565b61000e565b50610141611179565b5061014161110a565b5061014161109e565b50610141610fd9565b50610141610ef9565b50610141610dca565b50610141610d60565b50610141610cf6565b50610141610ca1565b50610141610bc2565b50610141610b64565b50610141610b08565b50610141610a98565b506101416109f2565b50610141610879565b50610141610807565b5061014161072b565b506101416106df565b5061014161064d565b50610141610564565b506101416104b9565b5061014161032e565b5061014161022c565b6001600160e01b031981160361022757565b600080fd5b503461022757602036600319011261022757602060043561024c81610215565b6000906001600160e01b031990610265833583166112e4565b6001600160a01b03811630036102af57501681527f16b23ef5cc9bddbf2e21b60afc4b56245b80d8dbeaaa1fc3455c33a00202d4ce8252604090205460ff165b6040519015158152f35b90506102bb91506112c3565b6102a5565b918091926000905b8282106102e05750116102d9575050565b6000910152565b915080602091830151818601520182916102c8565b9060209161030e815180928185528580860191016102c0565b601f01601f1916010190565b90602061032b9281815201906102f5565b90565b5034610227576000806003193601126104b657606061035782356001600160e01b0319166112e4565b6001600160a01b03811630036104a357505060405190807f3ebca56210b6e5e0b046fdfff7679f9cfd6394a3a3037061a1730d9945fa27ef549060019180831c92808216928315610499575b602092838610851461048557858852602088019490811561046457506001146103ec575b5050505050906103dc816103e89303826113bb565b6040519182918261031a565b0390f35b7f3ebca56210b6e5e0b046fdfff7679f9cfd6394a3a3037061a1730d9945fa27ef60005294509192917fa4b58ba3ac2b3947060498ebdbcff1d26efc6a4642c1d6ae2206de97a9be54915b83861061045357505050910190506103dc826103e838806103c7565b805485870152948201948101610437565b60ff191685525050505090151560051b0190506103dc826103e838806103c7565b634e487b7160e01b82526022600452602482fd5b93607f16936103a3565b6103e892506104b1906112c3565b6103dc565b80fd5b503461022757602036600319011261022757602060006004356104e682356001600160e01b0319166112e4565b6001600160a01b03919082811630036105295750819281610508604093611517565b81526000805160206120088339815191528552205416905b60405191168152f35b61053391506112c3565b610520565b600435906001600160a01b038216820361022757565b602435906001600160a01b038216820361022757565b50346102275760403660031901126102275761057e610538565b602435906105976000356001600160e01b0319166112e4565b6001600160a01b0390808216300361064057506105b383611540565b916105be8184611f01565b6105c83384611473565b1561062e5760008481526000805160206120088339815191526020526040902080546001600160a01b0319166001600160a01b038316179055811691167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9256000604051a4005b60405163983c62ff60e01b8152600490fd5b91505061001d91506112c3565b503461022757600036600319011261022757600061067581356001600160e01b0319166112e4565b906001600160a01b038216300361069a5750506020610692611670565b604051908152f35b6106a56020926112c3565b610692565b6060906003190112610227576001600160a01b0390600435828116810361022757916024359081168103610227579060443590565b5034610227576106ee366106aa565b906107046000356001600160e01b0319166112e4565b926001600160a01b038416300361071f5761001d9350611bdb565b50505061001d906112c3565b503461022757604036600319011261022757610745610538565b6024359060009061076082356001600160e01b0319166112e4565b6001600160a01b039080821630036107f1575061079061078a610782846114a5565b5461ffff1690565b85611f27565b828160018096019283929416915b6107bc57505050506103e891505b6040519081529081906020820190565b8394506107c98694611789565b9482826107d588611540565b16146107e6575b938394019361079e565b9260001901926107dc565b90506103e8935061080291506112c3565b6107ac565b503461022757610816366106aa565b90919061082e6000356001600160e01b0319166112e4565b926001600160a01b038416300361071f5761001d9350604051926020840184811067ffffffffffffffff82111761086c575b60405260008452611b8b565b6108746113a4565b610860565b5034610227576020366003190112610227576000600435816108a581356001600160e01b0319166112e4565b6001600160a01b039080821630036109e057507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef826108e385611540565b6108ee8633836115f4565b8582527fa28c56c3394ff00fe0713c07d98dd5d22cffe16416b26e65d6d6526b89d56800602052604090818320546109d6575b6000805160206120088339815191526020528482842054166109c7575b868352600080516020612048833981519152602081905282842054828716961686036109a05787845260205281832080546001600160a01b0319169055610984906114a5565b61098e8154611d34565b90555b610999611fc6565b51a4604051f35b506109c16109bb6109b0836114a5565b5460ff8a1690611d5f565b916114a5565b55610991565b6109d18782611415565b61093e565b8282812055610921565b9150506109ed91506112c3565b604051f35b5034610227576020366003190112610227576004356000610a1d81356001600160e01b0319166112e4565b6001600160a01b0381163003610a8a5750610a3f610a39611670565b83611f27565b806001809301805b610a5957505060405190815260209150f35b819250610a668492611789565b92610a70846115a3565b610a7f575b9181920191610a47565b906000190190610a75565b6103e89250610802906112c3565b5034610227576020366003190112610227576020610ab4610538565b6000610aca81356001600160e01b0319166112e4565b6001600160a01b0381163003610afd575050610af081610aeb60ff93611ebb565b6114a5565b5460101c16604051908152f35b6106a59192506112c3565b50346102275760203660031901126102275760206000610b3281356001600160e01b0319166112e4565b6001600160a01b03908082163003610b5b57509050610b52600435611540565b61052081611ebb565b610533906112c3565b5034610227576020366003190112610227576020610b80610538565b6000610b9681356001600160e01b0319166112e4565b6001600160a01b0381163003610afd575050610bb881610aeb61ffff93611ebb565b5416604051908152f35b5034610227576000806003193601126104b657610be981356001600160e01b0319166112e4565b6001600160a01b03908082163003610c9757507feaea6f5f17cefda44d7cbdfd7396ad4fbb4c0428e2e403ce46705b682833f39390815490811690610c2e8233611edd565b6bffffffffffffffffffffffff60a01b917f311bbfc7ad6a9098c3613fdc40ca4709ae1e5cdd3ef27b14dc8d504b8a91a55c8184825416179055807f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e086604051a3169055604051f35b6109ed91506112c3565b5034610227576000366003190112610227576000610cc981356001600160e01b0319166112e4565b906001600160a01b038216300361069a575050602060008051602061202883398151915254604051908152f35b50346102275760003660031901126102275760206000610d2081356001600160e01b0319166112e4565b6001600160a01b03908082163003610b5b57507feaea6f5f17cefda44d7cbdfd7396ad4fbb4c0428e2e403ce46705b682833f39354604051911681529050f35b50346102275760003660031901126102275760206000610d8a81356001600160e01b0319166112e4565b6001600160a01b03908082163003610b5b57507f311bbfc7ad6a9098c3613fdc40ca4709ae1e5cdd3ef27b14dc8d504b8a91a55c54604051911681529050f35b5034610227576000806003193601126104b6576060610df382356001600160e01b0319166112e4565b6001600160a01b03811630036104a357505060405190807f3ebca56210b6e5e0b046fdfff7679f9cfd6394a3a3037061a1730d9945fa27f0549060019180831c92808216928315610eef575b60209283861085146104855785885260208801949081156104645750600114610e77575050505050906103dc816103e89303826113bb565b7f3ebca56210b6e5e0b046fdfff7679f9cfd6394a3a3037061a1730d9945fa27f060005294509192917fca2c8f0030a855398300b0e4b8dd828e333842258e8e6ae862e623c794c647e05b838610610ede57505050910190506103dc826103e838806103c7565b805485870152948201948101610ec2565b93607f1693610e3f565b506020366003190112610227576000600435610f1f82356001600160e01b0319166112e4565b6001600160a01b0381163003610c9757508015610fc757610f8390610f536000805160206120288339815191525482611f82565b610f5c34611faf565b610f7d610f788260ff610f6e336114a5565b5460101c166118c6565b611f58565b336118de565b604051905b808310610f9757505050604051f35b600183019233857fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8186a4610f88565b6040516375a0be4160e01b8152600490fd5b503461022757604036600319011261022757610ff3610538565b60243590811515809203610227576110166000356001600160e01b0319166112e4565b6001600160a01b0391908281163003610640575061103381611ebb565b61103d3382611f01565b6110618161104a336114de565b9060018060a01b0316600052602052604060002090565b60ff1981541660ff851617905560405192835216907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b5034610227576080366003190112610227576110b8610538565b6110c061054e565b906064359167ffffffffffffffff91828411610227573660238501121561022757836004013592831161022757366024848601011161022757602461001d94019160443591611332565b50346102275760203660031901126102275760606111336000356001600160e01b0319166112e4565b906001600160a01b03821630036111685750506103e861115460043561199e565b6040519182916020835260208301906102f5565b6111746103e8926112c3565b611154565b5034610227576040366003190112610227576020611195610538565b61119d61054e565b9060006111b481356001600160e01b0319166112e4565b6001600160a01b03811630036111e157505060ff9161104a6111d5926114de565b54166040519015158152f35b9092506102bb91506112c3565b503461022757602036600319011261022757611208610538565b61121d6000356001600160e01b0319166112e4565b6001600160a01b03908082163003611298575061125d817f311bbfc7ad6a9098c3613fdc40ca4709ae1e5cdd3ef27b14dc8d504b8a91a55c541633611edd565b7feaea6f5f17cefda44d7cbdfd7396ad4fbb4c0428e2e403ce46705b682833f39391166bffffffffffffffffffffffff60a01b825416179055005b905061001d91506112c3565b6112c16112bc6000356001600160e01b0319166112e4565b6112c3565b565b90506000808092368280378136915af43d82803e156112e0573d90f35b3d90fd5b6001600160e01b03191660009081527f53c8d2cb336b1b5589c5d84db92eab23bfad9284648b13ccf94e058d0787dadf602052604090205460181c6001600160a01b0316906112c182611ebb565b92939261134a6000356001600160e01b0319166112e4565b6001600160a01b03811630036113955750611364846113ea565b9361137260405195866113bb565b8085523681870111610227576020816000926112c1988389013786010152611b8b565b93505050506112c191506112c3565b50634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176113dd57604052565b6113e56113a4565b604052565b60209067ffffffffffffffff8111611408575b601f01601f19160190565b6114106113a4565b6113fd565b6000828152600080516020612008833981519152602052604080822080546001600160a01b03191690555190916001600160a01b0316907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925908390a4565b6001600160a01b03808216908316149190821561148f57505090565b60ff92509061104a6114a0926114de565b541690565b6001600160a01b031660009081527f5c6880c19ffa4067385c27452342a7cf11f424ec075a22a885d3c7a424d781826020526040902090565b6001600160a01b031660009081527ff210ad279556cbff7ee6fbccf2b1dd313f889b411182c3db318a3b962a3578516020526040902090565b611520816115a3565b156115285750565b602490604051906338077a2b60e01b82526004820152fd5b600081815260008051602061204883398151915260205260409020546001600160a01b039081169291908315611574575050565b600180918360081c169261159460ff61158c866114a5565b5492166118a9565b1c161461159f575b50565b9150565b600081815260008051602061204883398151915260205260409020546001600160a01b03908116156115d6575050600190565b816115ee60ff61158c60019594869560081c166114a5565b1c161490565b816115fe91611473565b908115611627575b501561160f5750565b602490604051906320c3f59160e21b82526004820152fd5b600083815260008051602061200883398151915260205260409020546001600160a01b03918216911614905038611606565b50634e487b7160e01b600052601160045260246000fd5b7f423f283a7f0d4ed37463f55a0d558a9e3c0dcbfd800ee0233490b750779602565460008051602061202883398151915254908181106116ae570390565b6116b6611659565b0390565b7f9a6b4e94c3f039ddbf6f40d22f091fd200dcfe12af49dd13dc1a8d370400b000805482101561170f576000527f5144465d69f64229d7547ef0eaad0358793b1e7d6a9c2fb772300cbf1134a4690190600090565b634e487b7160e01b600052603260045260246000fd5b906040516040810181811067ffffffffffffffff821117611760575b604052915461ffff8116835260101c6001600160a01b03166020830152565b6117686113a4565b611741565b90816020910312610227575190565b506040513d6000823e3d90fd5b90600091600090817f9a6b4e94c3f039ddbf6f40d22f091fd200dcfe12af49dd13dc1a8d370400b00054915b8282106117c25750505050565b6117d46117ce836116ba565b50611725565b6117ea6117e3825161ffff1690565b61ffff1690565b821061180c57906118026117e36001935161ffff1690565b90039101906117b5565b602090810151959650939461186094935083925061184090611834906001600160a01b031681565b6001600160a01b031690565b6040518080968194634f6ccce760e01b8352600483019190602083019252565b03915afa92831561189c575b9261187657505090565b61032b9250803d10611895575b61188d81836113bb565b81019061176d565b503d611883565b6118a461177c565b61186c565b80196018116118b9575b60180190565b6118c1611659565b6118b3565b811981116118d2570190565b6118da611659565b0190565b909160ff6118eb836114a5565b5460101c16610100600160a81b038360081b16179261190a81856118c6565b926119586109bb8361195361191e856114a5565b5460ff8160101c16908119601811611991575b6001841b9160018310611984575b8460101b9260001901906018011b176118c6565b6118c6565b5560008051602061202883398151915290815481811061197757039055565b61197f611659565b039055565b61198c611659565b61193f565b611999611659565b611931565b906060916119ab81611517565b604060008281527fa28c56c3394ff00fe0713c07d98dd5d22cffe16416b26e65d6d6526b89d5680060205220546119e181611b0c565b506001600160a01b039190821615611ae4575b80611a0a611a04611a0f93611b0c565b50611ebb565b611b0c565b90929015611a225750506112c1906112c3565b60405163c87b56dd60e01b8152600481019190915292935060009183916024918391165afa908115611ad7575b600091611a5a575090565b903d8082843e611a6a81846113bb565b820191602081840312611acf5780519067ffffffffffffffff8211611ad3570182601f82011215611acf57805191611aa1836113ea565b93611aaf60405195866113bb565b838552602084840101116104b657509061032b91602080850191016102c0565b5080fd5b8280fd5b611adf61177c565b611a4f565b507fa28c56c3394ff00fe0713c07d98dd5d22cffe16416b26e65d6d6526b89d567ff546119f4565b6000527fa28c56c3394ff00fe0713c07d98dd5d22cffe16416b26e65d6d6526b89d568016020526040600020906020604051926040840184811067ffffffffffffffff821117611b7e575b6040525460ff8116151580855260089190911c6001600160a01b0316919093018190529190565b611b866113a4565b611b57565b90929190833b15611bd35783611ba4826112c196611f01565b611bb6611bb084611540565b83611edd565b611bc18333846115f4565b611bcc838284611c11565b3390611d8f565b6112c1939192505b906112c19291611bea82611ebb565b611bf48183611f01565b611c06611c0084611540565b82611edd565b611c118333836115f4565b6000838152600080516020612008833981519152602052604090205490916001600160a01b03918216611d25575b83600052600080516020612048833981519152602052816040600020541692828116809414600014611d0557611c74906114a5565b611c7e8154611d34565b90555b611cc581611ca686600052600080516020612048833981519152602052604060002090565b80546001600160a01b0319166001600160a01b03909216919091179055565b611cce816114a5565b611cd88154611d4f565b905516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6000604051a4565b611d1f6109bb611d14836114a5565b5460ff881690611d5f565b55611c81565b611d2f8484611415565b611c3f565b8015611d42575b6000190190565b611d4a611659565b611d3b565b60019060001981146118d2570190565b8119601811611d82575b6001600019926018011b821816600181106118d2570190565b611d8a611659565b611d69565b9391611d9c939185611e07565b61159c57604051634b42d1cd60e11b81526001600160a01b039091166004820152602490fd5b90816020910312610227575161032b81610215565b3d15611e02573d90611de8826113ea565b91611df660405193846113bb565b82523d6000602084013e565b606090565b604051630a85bd0160e11b8082526001600160a01b039384166004830152938316602482015260448101949094526080606485015291936020928492909183916000918390611e5a9060848301906102f5565b0393165af160009181611e8b575b50611e7d575050611e77611dd7565b50600090565b6001600160e01b0319161490565b611ead91925060203d8111611eb4575b611ea581836113bb565b810190611dc2565b9038611e68565b503d611e9b565b6001600160a01b031615611ecb57565b60405163f5bf603960e01b8152600490fd5b6001600160a01b039081169116146112c15760405163801b255b60e01b8152600490fd5b6001600160a01b03908116911614611f1557565b60405163801b255b60e01b8152600490fd5b9091828210611f5357506040516337532da760e21b815260048101919091526024810191909152604490fd5b915050565b600a8111611f635750565b604490604051906337532da760e21b82526004820152600a6024820152fd5b818111611f8d575050565b6040516337532da760e21b815260048101919091526024810191909152604490fd5b156112c157604051630918a35360e11b8152600490fd5b7f423f283a7f0d4ed37463f55a0d558a9e3c0dcbfd800ee0233490b75077960256805460018110611ffa575b600019019055565b612002611659565b611ff256fef210ad279556cbff7ee6fbccf2b1dd313f889b411182c3db318a3b962a357850423f283a7f0d4ed37463f55a0d558a9e3c0dcbfd800ee0233490b750779602575c6880c19ffa4067385c27452342a7cf11f424ec075a22a885d3c7a424d78181a264697066735822122031bd0dcaf7ac98ca52f5df084e990925427939ae6cf386ac2a5b85c08018033364736f6c634300080f00333ebca56210b6e5e0b046fdfff7679f9cfd6394a3a3037061a1730d9945fa27ef3ebca56210b6e5e0b046fdfff7679f9cfd6394a3a3037061a1730d9945fa27f0000000000000000000000000558195b6dc0e06b69f1a87505f3b49a9a3e40c810000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002419ab453c000000000000000000000000558195b6dc0e06b69f1a87505f3b49a9a3e40c8100000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436101561002c575b361561001f575b61001d6112a4565b005b6100276112a4565b610015565b60003560e01c806301ffc9a71461020c57806306fdde0314610203578063081812fc146101fa578063095ea7b3146101f157806318160ddd146101e857806323b872dd146101df5780632f745c59146101d657806342842e0e146101cd57806342966c68146101c45780634f6ccce7146101bb578063630a3d26146101b25780636352211e146101a957806370a08231146101a057806379ba5097146101975780637ecc2b561461018e5780638ab5150a146101855780638da5cb5b1461017c57806395d89b4114610173578063a0712d681461016a578063a22cb46514610161578063b88d4fde14610158578063c87b56dd1461014f578063e985e9c5146101465763f2fde38b0361000e576101416111ee565b61000e565b50610141611179565b5061014161110a565b5061014161109e565b50610141610fd9565b50610141610ef9565b50610141610dca565b50610141610d60565b50610141610cf6565b50610141610ca1565b50610141610bc2565b50610141610b64565b50610141610b08565b50610141610a98565b506101416109f2565b50610141610879565b50610141610807565b5061014161072b565b506101416106df565b5061014161064d565b50610141610564565b506101416104b9565b5061014161032e565b5061014161022c565b6001600160e01b031981160361022757565b600080fd5b503461022757602036600319011261022757602060043561024c81610215565b6000906001600160e01b031990610265833583166112e4565b6001600160a01b03811630036102af57501681527f16b23ef5cc9bddbf2e21b60afc4b56245b80d8dbeaaa1fc3455c33a00202d4ce8252604090205460ff165b6040519015158152f35b90506102bb91506112c3565b6102a5565b918091926000905b8282106102e05750116102d9575050565b6000910152565b915080602091830151818601520182916102c8565b9060209161030e815180928185528580860191016102c0565b601f01601f1916010190565b90602061032b9281815201906102f5565b90565b5034610227576000806003193601126104b657606061035782356001600160e01b0319166112e4565b6001600160a01b03811630036104a357505060405190807f3ebca56210b6e5e0b046fdfff7679f9cfd6394a3a3037061a1730d9945fa27ef549060019180831c92808216928315610499575b602092838610851461048557858852602088019490811561046457506001146103ec575b5050505050906103dc816103e89303826113bb565b6040519182918261031a565b0390f35b7f3ebca56210b6e5e0b046fdfff7679f9cfd6394a3a3037061a1730d9945fa27ef60005294509192917fa4b58ba3ac2b3947060498ebdbcff1d26efc6a4642c1d6ae2206de97a9be54915b83861061045357505050910190506103dc826103e838806103c7565b805485870152948201948101610437565b60ff191685525050505090151560051b0190506103dc826103e838806103c7565b634e487b7160e01b82526022600452602482fd5b93607f16936103a3565b6103e892506104b1906112c3565b6103dc565b80fd5b503461022757602036600319011261022757602060006004356104e682356001600160e01b0319166112e4565b6001600160a01b03919082811630036105295750819281610508604093611517565b81526000805160206120088339815191528552205416905b60405191168152f35b61053391506112c3565b610520565b600435906001600160a01b038216820361022757565b602435906001600160a01b038216820361022757565b50346102275760403660031901126102275761057e610538565b602435906105976000356001600160e01b0319166112e4565b6001600160a01b0390808216300361064057506105b383611540565b916105be8184611f01565b6105c83384611473565b1561062e5760008481526000805160206120088339815191526020526040902080546001600160a01b0319166001600160a01b038316179055811691167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9256000604051a4005b60405163983c62ff60e01b8152600490fd5b91505061001d91506112c3565b503461022757600036600319011261022757600061067581356001600160e01b0319166112e4565b906001600160a01b038216300361069a5750506020610692611670565b604051908152f35b6106a56020926112c3565b610692565b6060906003190112610227576001600160a01b0390600435828116810361022757916024359081168103610227579060443590565b5034610227576106ee366106aa565b906107046000356001600160e01b0319166112e4565b926001600160a01b038416300361071f5761001d9350611bdb565b50505061001d906112c3565b503461022757604036600319011261022757610745610538565b6024359060009061076082356001600160e01b0319166112e4565b6001600160a01b039080821630036107f1575061079061078a610782846114a5565b5461ffff1690565b85611f27565b828160018096019283929416915b6107bc57505050506103e891505b6040519081529081906020820190565b8394506107c98694611789565b9482826107d588611540565b16146107e6575b938394019361079e565b9260001901926107dc565b90506103e8935061080291506112c3565b6107ac565b503461022757610816366106aa565b90919061082e6000356001600160e01b0319166112e4565b926001600160a01b038416300361071f5761001d9350604051926020840184811067ffffffffffffffff82111761086c575b60405260008452611b8b565b6108746113a4565b610860565b5034610227576020366003190112610227576000600435816108a581356001600160e01b0319166112e4565b6001600160a01b039080821630036109e057507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef826108e385611540565b6108ee8633836115f4565b8582527fa28c56c3394ff00fe0713c07d98dd5d22cffe16416b26e65d6d6526b89d56800602052604090818320546109d6575b6000805160206120088339815191526020528482842054166109c7575b868352600080516020612048833981519152602081905282842054828716961686036109a05787845260205281832080546001600160a01b0319169055610984906114a5565b61098e8154611d34565b90555b610999611fc6565b51a4604051f35b506109c16109bb6109b0836114a5565b5460ff8a1690611d5f565b916114a5565b55610991565b6109d18782611415565b61093e565b8282812055610921565b9150506109ed91506112c3565b604051f35b5034610227576020366003190112610227576004356000610a1d81356001600160e01b0319166112e4565b6001600160a01b0381163003610a8a5750610a3f610a39611670565b83611f27565b806001809301805b610a5957505060405190815260209150f35b819250610a668492611789565b92610a70846115a3565b610a7f575b9181920191610a47565b906000190190610a75565b6103e89250610802906112c3565b5034610227576020366003190112610227576020610ab4610538565b6000610aca81356001600160e01b0319166112e4565b6001600160a01b0381163003610afd575050610af081610aeb60ff93611ebb565b6114a5565b5460101c16604051908152f35b6106a59192506112c3565b50346102275760203660031901126102275760206000610b3281356001600160e01b0319166112e4565b6001600160a01b03908082163003610b5b57509050610b52600435611540565b61052081611ebb565b610533906112c3565b5034610227576020366003190112610227576020610b80610538565b6000610b9681356001600160e01b0319166112e4565b6001600160a01b0381163003610afd575050610bb881610aeb61ffff93611ebb565b5416604051908152f35b5034610227576000806003193601126104b657610be981356001600160e01b0319166112e4565b6001600160a01b03908082163003610c9757507feaea6f5f17cefda44d7cbdfd7396ad4fbb4c0428e2e403ce46705b682833f39390815490811690610c2e8233611edd565b6bffffffffffffffffffffffff60a01b917f311bbfc7ad6a9098c3613fdc40ca4709ae1e5cdd3ef27b14dc8d504b8a91a55c8184825416179055807f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e086604051a3169055604051f35b6109ed91506112c3565b5034610227576000366003190112610227576000610cc981356001600160e01b0319166112e4565b906001600160a01b038216300361069a575050602060008051602061202883398151915254604051908152f35b50346102275760003660031901126102275760206000610d2081356001600160e01b0319166112e4565b6001600160a01b03908082163003610b5b57507feaea6f5f17cefda44d7cbdfd7396ad4fbb4c0428e2e403ce46705b682833f39354604051911681529050f35b50346102275760003660031901126102275760206000610d8a81356001600160e01b0319166112e4565b6001600160a01b03908082163003610b5b57507f311bbfc7ad6a9098c3613fdc40ca4709ae1e5cdd3ef27b14dc8d504b8a91a55c54604051911681529050f35b5034610227576000806003193601126104b6576060610df382356001600160e01b0319166112e4565b6001600160a01b03811630036104a357505060405190807f3ebca56210b6e5e0b046fdfff7679f9cfd6394a3a3037061a1730d9945fa27f0549060019180831c92808216928315610eef575b60209283861085146104855785885260208801949081156104645750600114610e77575050505050906103dc816103e89303826113bb565b7f3ebca56210b6e5e0b046fdfff7679f9cfd6394a3a3037061a1730d9945fa27f060005294509192917fca2c8f0030a855398300b0e4b8dd828e333842258e8e6ae862e623c794c647e05b838610610ede57505050910190506103dc826103e838806103c7565b805485870152948201948101610ec2565b93607f1693610e3f565b506020366003190112610227576000600435610f1f82356001600160e01b0319166112e4565b6001600160a01b0381163003610c9757508015610fc757610f8390610f536000805160206120288339815191525482611f82565b610f5c34611faf565b610f7d610f788260ff610f6e336114a5565b5460101c166118c6565b611f58565b336118de565b604051905b808310610f9757505050604051f35b600183019233857fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8186a4610f88565b6040516375a0be4160e01b8152600490fd5b503461022757604036600319011261022757610ff3610538565b60243590811515809203610227576110166000356001600160e01b0319166112e4565b6001600160a01b0391908281163003610640575061103381611ebb565b61103d3382611f01565b6110618161104a336114de565b9060018060a01b0316600052602052604060002090565b60ff1981541660ff851617905560405192835216907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b5034610227576080366003190112610227576110b8610538565b6110c061054e565b906064359167ffffffffffffffff91828411610227573660238501121561022757836004013592831161022757366024848601011161022757602461001d94019160443591611332565b50346102275760203660031901126102275760606111336000356001600160e01b0319166112e4565b906001600160a01b03821630036111685750506103e861115460043561199e565b6040519182916020835260208301906102f5565b6111746103e8926112c3565b611154565b5034610227576040366003190112610227576020611195610538565b61119d61054e565b9060006111b481356001600160e01b0319166112e4565b6001600160a01b03811630036111e157505060ff9161104a6111d5926114de565b54166040519015158152f35b9092506102bb91506112c3565b503461022757602036600319011261022757611208610538565b61121d6000356001600160e01b0319166112e4565b6001600160a01b03908082163003611298575061125d817f311bbfc7ad6a9098c3613fdc40ca4709ae1e5cdd3ef27b14dc8d504b8a91a55c541633611edd565b7feaea6f5f17cefda44d7cbdfd7396ad4fbb4c0428e2e403ce46705b682833f39391166bffffffffffffffffffffffff60a01b825416179055005b905061001d91506112c3565b6112c16112bc6000356001600160e01b0319166112e4565b6112c3565b565b90506000808092368280378136915af43d82803e156112e0573d90f35b3d90fd5b6001600160e01b03191660009081527f53c8d2cb336b1b5589c5d84db92eab23bfad9284648b13ccf94e058d0787dadf602052604090205460181c6001600160a01b0316906112c182611ebb565b92939261134a6000356001600160e01b0319166112e4565b6001600160a01b03811630036113955750611364846113ea565b9361137260405195866113bb565b8085523681870111610227576020816000926112c1988389013786010152611b8b565b93505050506112c191506112c3565b50634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176113dd57604052565b6113e56113a4565b604052565b60209067ffffffffffffffff8111611408575b601f01601f19160190565b6114106113a4565b6113fd565b6000828152600080516020612008833981519152602052604080822080546001600160a01b03191690555190916001600160a01b0316907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925908390a4565b6001600160a01b03808216908316149190821561148f57505090565b60ff92509061104a6114a0926114de565b541690565b6001600160a01b031660009081527f5c6880c19ffa4067385c27452342a7cf11f424ec075a22a885d3c7a424d781826020526040902090565b6001600160a01b031660009081527ff210ad279556cbff7ee6fbccf2b1dd313f889b411182c3db318a3b962a3578516020526040902090565b611520816115a3565b156115285750565b602490604051906338077a2b60e01b82526004820152fd5b600081815260008051602061204883398151915260205260409020546001600160a01b039081169291908315611574575050565b600180918360081c169261159460ff61158c866114a5565b5492166118a9565b1c161461159f575b50565b9150565b600081815260008051602061204883398151915260205260409020546001600160a01b03908116156115d6575050600190565b816115ee60ff61158c60019594869560081c166114a5565b1c161490565b816115fe91611473565b908115611627575b501561160f5750565b602490604051906320c3f59160e21b82526004820152fd5b600083815260008051602061200883398151915260205260409020546001600160a01b03918216911614905038611606565b50634e487b7160e01b600052601160045260246000fd5b7f423f283a7f0d4ed37463f55a0d558a9e3c0dcbfd800ee0233490b750779602565460008051602061202883398151915254908181106116ae570390565b6116b6611659565b0390565b7f9a6b4e94c3f039ddbf6f40d22f091fd200dcfe12af49dd13dc1a8d370400b000805482101561170f576000527f5144465d69f64229d7547ef0eaad0358793b1e7d6a9c2fb772300cbf1134a4690190600090565b634e487b7160e01b600052603260045260246000fd5b906040516040810181811067ffffffffffffffff821117611760575b604052915461ffff8116835260101c6001600160a01b03166020830152565b6117686113a4565b611741565b90816020910312610227575190565b506040513d6000823e3d90fd5b90600091600090817f9a6b4e94c3f039ddbf6f40d22f091fd200dcfe12af49dd13dc1a8d370400b00054915b8282106117c25750505050565b6117d46117ce836116ba565b50611725565b6117ea6117e3825161ffff1690565b61ffff1690565b821061180c57906118026117e36001935161ffff1690565b90039101906117b5565b602090810151959650939461186094935083925061184090611834906001600160a01b031681565b6001600160a01b031690565b6040518080968194634f6ccce760e01b8352600483019190602083019252565b03915afa92831561189c575b9261187657505090565b61032b9250803d10611895575b61188d81836113bb565b81019061176d565b503d611883565b6118a461177c565b61186c565b80196018116118b9575b60180190565b6118c1611659565b6118b3565b811981116118d2570190565b6118da611659565b0190565b909160ff6118eb836114a5565b5460101c16610100600160a81b038360081b16179261190a81856118c6565b926119586109bb8361195361191e856114a5565b5460ff8160101c16908119601811611991575b6001841b9160018310611984575b8460101b9260001901906018011b176118c6565b6118c6565b5560008051602061202883398151915290815481811061197757039055565b61197f611659565b039055565b61198c611659565b61193f565b611999611659565b611931565b906060916119ab81611517565b604060008281527fa28c56c3394ff00fe0713c07d98dd5d22cffe16416b26e65d6d6526b89d5680060205220546119e181611b0c565b506001600160a01b039190821615611ae4575b80611a0a611a04611a0f93611b0c565b50611ebb565b611b0c565b90929015611a225750506112c1906112c3565b60405163c87b56dd60e01b8152600481019190915292935060009183916024918391165afa908115611ad7575b600091611a5a575090565b903d8082843e611a6a81846113bb565b820191602081840312611acf5780519067ffffffffffffffff8211611ad3570182601f82011215611acf57805191611aa1836113ea565b93611aaf60405195866113bb565b838552602084840101116104b657509061032b91602080850191016102c0565b5080fd5b8280fd5b611adf61177c565b611a4f565b507fa28c56c3394ff00fe0713c07d98dd5d22cffe16416b26e65d6d6526b89d567ff546119f4565b6000527fa28c56c3394ff00fe0713c07d98dd5d22cffe16416b26e65d6d6526b89d568016020526040600020906020604051926040840184811067ffffffffffffffff821117611b7e575b6040525460ff8116151580855260089190911c6001600160a01b0316919093018190529190565b611b866113a4565b611b57565b90929190833b15611bd35783611ba4826112c196611f01565b611bb6611bb084611540565b83611edd565b611bc18333846115f4565b611bcc838284611c11565b3390611d8f565b6112c1939192505b906112c19291611bea82611ebb565b611bf48183611f01565b611c06611c0084611540565b82611edd565b611c118333836115f4565b6000838152600080516020612008833981519152602052604090205490916001600160a01b03918216611d25575b83600052600080516020612048833981519152602052816040600020541692828116809414600014611d0557611c74906114a5565b611c7e8154611d34565b90555b611cc581611ca686600052600080516020612048833981519152602052604060002090565b80546001600160a01b0319166001600160a01b03909216919091179055565b611cce816114a5565b611cd88154611d4f565b905516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6000604051a4565b611d1f6109bb611d14836114a5565b5460ff881690611d5f565b55611c81565b611d2f8484611415565b611c3f565b8015611d42575b6000190190565b611d4a611659565b611d3b565b60019060001981146118d2570190565b8119601811611d82575b6001600019926018011b821816600181106118d2570190565b611d8a611659565b611d69565b9391611d9c939185611e07565b61159c57604051634b42d1cd60e11b81526001600160a01b039091166004820152602490fd5b90816020910312610227575161032b81610215565b3d15611e02573d90611de8826113ea565b91611df660405193846113bb565b82523d6000602084013e565b606090565b604051630a85bd0160e11b8082526001600160a01b039384166004830152938316602482015260448101949094526080606485015291936020928492909183916000918390611e5a9060848301906102f5565b0393165af160009181611e8b575b50611e7d575050611e77611dd7565b50600090565b6001600160e01b0319161490565b611ead91925060203d8111611eb4575b611ea581836113bb565b810190611dc2565b9038611e68565b503d611e9b565b6001600160a01b031615611ecb57565b60405163f5bf603960e01b8152600490fd5b6001600160a01b039081169116146112c15760405163801b255b60e01b8152600490fd5b6001600160a01b03908116911614611f1557565b60405163801b255b60e01b8152600490fd5b9091828210611f5357506040516337532da760e21b815260048101919091526024810191909152604490fd5b915050565b600a8111611f635750565b604490604051906337532da760e21b82526004820152600a6024820152fd5b818111611f8d575050565b6040516337532da760e21b815260048101919091526024810191909152604490fd5b156112c157604051630918a35360e11b8152600490fd5b7f423f283a7f0d4ed37463f55a0d558a9e3c0dcbfd800ee0233490b75077960256805460018110611ffa575b600019019055565b612002611659565b611ff256fef210ad279556cbff7ee6fbccf2b1dd313f889b411182c3db318a3b962a357850423f283a7f0d4ed37463f55a0d558a9e3c0dcbfd800ee0233490b750779602575c6880c19ffa4067385c27452342a7cf11f424ec075a22a885d3c7a424d78181a264697066735822122031bd0dcaf7ac98ca52f5df084e990925427939ae6cf386ac2a5b85c08018033364736f6c634300080f0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000558195b6dc0e06b69f1a87505f3b49a9a3e40c810000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002419ab453c000000000000000000000000558195b6dc0e06b69f1a87505f3b49a9a3e40c8100000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : init (address): 0x558195B6Dc0e06B69f1a87505F3B49A9A3E40c81
Arg [1] : data (bytes): 0x19ab453c000000000000000000000000558195b6dc0e06b69f1a87505f3b49a9a3e40c81

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000558195b6dc0e06b69f1a87505f3b49a9a3e40c81
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000024
Arg [3] : 19ab453c000000000000000000000000558195b6dc0e06b69f1a87505f3b49a9
Arg [4] : a3e40c8100000000000000000000000000000000000000000000000000000000


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.