creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/diamond/BaseStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport {INiftyKitAppRegistry} from \"../interfaces/INiftyKitAppRegistry.sol\";\nimport {INiftyKitV3} from \"../interfaces/INiftyKitV3.sol\";\n\nlibrary BaseStorage {\n    enum Transfer {\n        AllowAll,\n        AllowedOperatorsOnly,\n        BlockAll\n    }\n\n    struct URIEntry {\n        bool isValue;\n        string tokenURI;\n    }\n\n    bytes32 private constant STORAGE_SLOT = keccak256(\"niftykit.base.storage\");\n\n    uint256 public constant ADMIN_ROLE = 1 << 0;\n    uint256 public constant MANAGER_ROLE = 1 << 1;\n    uint256 public constant API_ROLE = 1 << 2;\n\n    struct Layout {\n        mapping(bytes32 => INiftyKitAppRegistry.App) _apps;\n        mapping(address => bool) _allowedOperators;\n        mapping(uint256 => bool) _blockedTokenIds;\n        mapping(uint256 => URIEntry) _tokenURIs;\n        bool _operatorFilteringEnabled;\n        Transfer _transferStatus;\n        INiftyKitV3 _niftyKit;\n        uint8 _baseVersion;\n        address _treasury;\n        string _baseURI;\n        address _mintSigner;\n        address _trustedForwarder;\n    }\n\n    function layout() internal pure returns (Layout storage ds) {\n        bytes32 position = STORAGE_SLOT;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            ds.slot := position\n        }\n    }\n}\n"
      },
      "contracts/diamond/DiamondCollection.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport {INiftyKitAppRegistry} from \"../interfaces/INiftyKitAppRegistry.sol\";\nimport {INiftyKitV3} from \"../interfaces/INiftyKitV3.sol\";\nimport {IDiamondCut} from \"../interfaces/IDiamondCut.sol\";\nimport {LibDiamond} from \"../libraries/LibDiamond.sol\";\nimport {BaseStorage} from \"./BaseStorage.sol\";\n\ncontract DiamondCollection {\n    constructor(INiftyKitV3.DiamondArgs memory args) {\n        BaseStorage.Layout storage layout = BaseStorage.layout();\n        layout._niftyKit = INiftyKitV3(msg.sender);\n        INiftyKitAppRegistry registry = INiftyKitAppRegistry(\n            layout._niftyKit.appRegistry()\n        );\n        INiftyKitAppRegistry.Base memory base = registry.getBase();\n        IDiamondCut.FacetCut[] memory facetCuts = new IDiamondCut.FacetCut[](\n            args.apps.length + 1\n        );\n\n        layout._treasury = args.treasury;\n        layout._baseVersion = base.version;\n        layout._baseURI = args.baseURI;\n        layout._trustedForwarder = args.trustedForwarder;\n        facetCuts = _appFacets(facetCuts, layout, registry, args.apps);\n        facetCuts = _baseFacet(facetCuts, base);\n\n        LibDiamond.diamondCut(\n            facetCuts,\n            base.implementation,\n            abi.encodeWithSignature(\n                \"_initialize(address,address,string,string,address,uint16)\",\n                args.owner,\n                args.admin,\n                args.name,\n                args.symbol,\n                args.royalty,\n                args.royaltyBps\n            )\n        );\n    }\n\n    function _appFacets(\n        IDiamondCut.FacetCut[] memory facetCuts,\n        BaseStorage.Layout storage layout,\n        INiftyKitAppRegistry registry,\n        bytes32[] memory apps\n    ) internal returns (IDiamondCut.FacetCut[] memory) {\n        LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n        uint256 appsLength = apps.length;\n        for (uint256 i = 0; i < appsLength; ) {\n            INiftyKitAppRegistry.App memory app = registry.getApp(apps[i]);\n            if (app.version == 0) revert(\"App does not exist\");\n\n            facetCuts[i] = IDiamondCut.FacetCut({\n                facetAddress: app.implementation,\n                action: IDiamondCut.FacetCutAction.Add,\n                functionSelectors: app.selectors\n            });\n\n            ds.supportedInterfaces[app.interfaceId] = true;\n            layout._apps[apps[i]] = app;\n\n            unchecked {\n                i++;\n            }\n        }\n\n        return facetCuts;\n    }\n\n    function _baseFacet(\n        IDiamondCut.FacetCut[] memory facetCuts,\n        INiftyKitAppRegistry.Base memory base\n    ) internal returns (IDiamondCut.FacetCut[] memory) {\n        LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n        facetCuts[facetCuts.length - 1] = IDiamondCut.FacetCut({\n            facetAddress: base.implementation,\n            action: IDiamondCut.FacetCutAction.Add,\n            functionSelectors: base.selectors\n        });\n\n        uint256 idsLength = base.interfaceIds.length;\n        for (uint256 i = 0; i < idsLength; ) {\n            ds.supportedInterfaces[base.interfaceIds[i]] = true;\n\n            unchecked {\n                i++;\n            }\n        }\n\n        return facetCuts;\n    }\n\n    // Find facet for function that is called and execute the\n    // function if a facet is found and return any value.\n    fallback() external payable {\n        LibDiamond.DiamondStorage storage ds;\n        bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION;\n        // get diamond storage\n        assembly {\n            ds.slot := position\n        }\n        // get facet from function selector\n        address facet = address(bytes20(ds.facets[msg.sig]));\n        require(facet != address(0), \"Diamond: Function does not exist\");\n        // Execute external function from facet using delegatecall and return any value.\n        assembly {\n            // copy function selector and any arguments\n            calldatacopy(0, 0, calldatasize())\n            // execute function call using the facet\n            let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)\n            // get any return value\n            returndatacopy(0, 0, returndatasize())\n            // return any return value or error back to the caller\n            switch result\n            case 0 {\n                revert(0, returndatasize())\n            }\n            default {\n                return(0, returndatasize())\n            }\n        }\n    }\n\n    receive() external payable {}\n}\n"
      },
      "contracts/interfaces/IDiamondCut.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/******************************************************************************\\\n* Author: Nick Mudge <nick@perfectabstractions.com> (https://twitter.com/mudgen)\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\n/******************************************************************************/\n\ninterface IDiamondCut {\n    enum FacetCutAction {Add, Replace, Remove}\n    // Add=0, Replace=1, Remove=2\n\n    struct FacetCut {\n        address facetAddress;\n        FacetCutAction action;\n        bytes4[] functionSelectors;\n    }\n\n    /// @notice Add/replace/remove any number of functions and optionally execute\n    ///         a function with delegatecall\n    /// @param _diamondCut Contains the facet addresses and function selectors\n    /// @param _init The address of the contract or facet to execute _calldata\n    /// @param _calldata A function call, including function selector and arguments\n    ///                  _calldata is executed with delegatecall on _init\n    function diamondCut(\n        FacetCut[] calldata _diamondCut,\n        address _init,\n        bytes calldata _calldata\n    ) external;\n\n    event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n"
      },
      "contracts/interfaces/INiftyKitAppRegistry.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface INiftyKitAppRegistry {\n    struct App {\n        address implementation;\n        bytes4 interfaceId;\n        bytes4[] selectors;\n        uint8 version;\n    }\n\n    struct Base {\n        address implementation;\n        bytes4[] interfaceIds;\n        bytes4[] selectors;\n        uint8 version;\n    }\n\n    /**\n     * Get App Facet by app name\n     * @param name app name\n     */\n    function getApp(bytes32 name) external view returns (App memory);\n\n    /**\n     * Get base Facet\n     */\n    function getBase() external view returns (Base memory);\n}\n"
      },
      "contracts/interfaces/INiftyKitV3.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface INiftyKitV3 {\n    struct DiamondArgs {\n        address owner;\n        address admin;\n        address treasury;\n        address royalty;\n        address trustedForwarder;\n        uint16 royaltyBps;\n        string name;\n        string symbol;\n        string baseURI;\n        bytes32[] apps;\n    }\n\n    /**\n     * @dev Returns app registry address.\n     */\n    function appRegistry() external returns (address);\n\n    /**\n     * @dev Returns the commission amount (sellerFee, buyerFee).\n     * @dev Deprecated: use commissionByQuantity instead.\n     */\n    function commission(\n        address collection,\n        uint256 amount\n    ) external view returns (uint256, uint256);\n\n    /**\n     * @dev Returns the commission amount (mintFee, ownerPerks).\n     */\n    function commissionByQuantity(\n        address collection,\n        uint256 quantity\n    ) external view returns (uint256, uint256);\n\n    /**\n     * @dev Get fees by amount (called from collection)\n     * @dev Deprecated: use getFeesByQuantity instead.\n     */\n    function getFees(uint256 amount) external view returns (uint256, uint256);\n\n    /**\n     * @dev Get fees by quantity (called from collection)\n     */\n    function getFeesByQuantity(\n        uint256 quantity\n    ) external view returns (uint256, uint256);\n\n    /**\n     * @dev Returns the perks rate for a given owner.\n     */\n    function getOwnerPerksRate(address owner) external view returns (uint96);\n}\n"
      },
      "contracts/libraries/LibDiamond.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/******************************************************************************\\\n* Author: Nick Mudge <nick@perfectabstractions.com> (https://twitter.com/mudgen)\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\n/******************************************************************************/\nimport { IDiamondCut } from \"../interfaces/IDiamondCut.sol\";\n\n// Remember to add the loupe functions from DiamondLoupeFacet to the diamond.\n// The loupe functions are required by the EIP2535 Diamonds standard\n\nerror InitializationFunctionReverted(address _initializationContractAddress, bytes _calldata);\n\nlibrary LibDiamond {\n    bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\"diamond.standard.diamond.storage\");\n\n    struct DiamondStorage {\n        // maps function selectors to the facets that execute the functions.\n        // and maps the selectors to their position in the selectorSlots array.\n        // func selector => address facet, selector position\n        mapping(bytes4 => bytes32) facets;\n        // array of slots of function selectors.\n        // each slot holds 8 function selectors.\n        mapping(uint256 => bytes32) selectorSlots;\n        // The number of function selectors in selectorSlots\n        uint16 selectorCount;\n        // Used to query if a contract implements an interface.\n        // Used to implement ERC-165.\n        mapping(bytes4 => bool) supportedInterfaces;\n        // owner of the contract\n        address contractOwner;\n    }\n\n    function diamondStorage() internal pure returns (DiamondStorage storage ds) {\n        bytes32 position = DIAMOND_STORAGE_POSITION;\n        assembly {\n            ds.slot := position\n        }\n    }\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    function setContractOwner(address _newOwner) internal {\n        DiamondStorage storage ds = diamondStorage();\n        address previousOwner = ds.contractOwner;\n        ds.contractOwner = _newOwner;\n        emit OwnershipTransferred(previousOwner, _newOwner);\n    }\n\n    function contractOwner() internal view returns (address contractOwner_) {\n        contractOwner_ = diamondStorage().contractOwner;\n    }\n\n    function enforceIsContractOwner() internal view {\n        require(msg.sender == diamondStorage().contractOwner, \"LibDiamond: Must be contract owner\");\n    }\n\n    event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\n\n    bytes32 constant CLEAR_ADDRESS_MASK = bytes32(uint256(0xffffffffffffffffffffffff));\n    bytes32 constant CLEAR_SELECTOR_MASK = bytes32(uint256(0xffffffff << 224));\n\n    // Internal function version of diamondCut\n    // This code is almost the same as the external diamondCut,\n    // except it is using 'Facet[] memory _diamondCut' instead of\n    // 'Facet[] calldata _diamondCut'.\n    // The code is duplicated to prevent copying calldata to memory which\n    // causes an error for a two dimensional array.\n    function diamondCut(\n        IDiamondCut.FacetCut[] memory _diamondCut,\n        address _init,\n        bytes memory _calldata\n    ) internal {\n        DiamondStorage storage ds = diamondStorage();\n        uint256 originalSelectorCount = ds.selectorCount;\n        uint256 selectorCount = originalSelectorCount;\n        bytes32 selectorSlot;\n        // Check if last selector slot is not full\n        // \"selectorCount & 7\" is a gas efficient modulo by eight \"selectorCount % 8\" \n        if (selectorCount & 7 > 0) {\n            // get last selectorSlot\n            // \"selectorSlot >> 3\" is a gas efficient division by 8 \"selectorSlot / 8\"\n            selectorSlot = ds.selectorSlots[selectorCount >> 3];\n        }\n        // loop through diamond cut\n        for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n            (selectorCount, selectorSlot) = addReplaceRemoveFacetSelectors(\n                selectorCount,\n                selectorSlot,\n                _diamondCut[facetIndex].facetAddress,\n                _diamondCut[facetIndex].action,\n                _diamondCut[facetIndex].functionSelectors\n            );\n\n            unchecked {\n                facetIndex++;\n            }\n        }\n        if (selectorCount != originalSelectorCount) {\n            ds.selectorCount = uint16(selectorCount);\n        }\n        // If last selector slot is not full\n        // \"selectorCount & 7\" is a gas efficient modulo by eight \"selectorCount % 8\" \n        if (selectorCount & 7 > 0) {\n            // \"selectorSlot >> 3\" is a gas efficient division by 8 \"selectorSlot / 8\"\n            ds.selectorSlots[selectorCount >> 3] = selectorSlot;\n        }\n        emit DiamondCut(_diamondCut, _init, _calldata);\n        initializeDiamondCut(_init, _calldata);\n    }\n\n    function addReplaceRemoveFacetSelectors(\n        uint256 _selectorCount,\n        bytes32 _selectorSlot,\n        address _newFacetAddress,\n        IDiamondCut.FacetCutAction _action,\n        bytes4[] memory _selectors\n    ) internal returns (uint256, bytes32) {\n        DiamondStorage storage ds = diamondStorage();\n        require(_selectors.length > 0, \"LibDiamondCut: No selectors in facet to cut\");\n        if (_action == IDiamondCut.FacetCutAction.Add) {\n            enforceHasContractCode(_newFacetAddress, \"LibDiamondCut: Add facet has no code\");\n            for (uint256 selectorIndex; selectorIndex < _selectors.length; ) {\n                bytes4 selector = _selectors[selectorIndex];\n                bytes32 oldFacet = ds.facets[selector];\n                require(address(bytes20(oldFacet)) == address(0), \"LibDiamondCut: Can't add function that already exists\");\n                // add facet for selector\n                ds.facets[selector] = bytes20(_newFacetAddress) | bytes32(_selectorCount);\n                // \"_selectorCount & 7\" is a gas efficient modulo by eight \"_selectorCount % 8\" \n                // \" << 5 is the same as multiplying by 32 ( * 32)\n                uint256 selectorInSlotPosition = (_selectorCount & 7) << 5;\n                // clear selector position in slot and add selector\n                _selectorSlot = (_selectorSlot & ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) | (bytes32(selector) >> selectorInSlotPosition);\n                // if slot is full then write it to storage\n                if (selectorInSlotPosition == 224) {\n                    // \"_selectorSlot >> 3\" is a gas efficient division by 8 \"_selectorSlot / 8\"\n                    ds.selectorSlots[_selectorCount >> 3] = _selectorSlot;\n                    _selectorSlot = 0;\n                }\n                _selectorCount++;\n\n                unchecked {\n                    selectorIndex++;\n                }\n            }\n        } else if (_action == IDiamondCut.FacetCutAction.Replace) {\n            enforceHasContractCode(_newFacetAddress, \"LibDiamondCut: Replace facet has no code\");\n            for (uint256 selectorIndex; selectorIndex < _selectors.length; ) {\n                bytes4 selector = _selectors[selectorIndex];\n                bytes32 oldFacet = ds.facets[selector];\n                address oldFacetAddress = address(bytes20(oldFacet));\n                // only useful if immutable functions exist\n                require(oldFacetAddress != address(this), \"LibDiamondCut: Can't replace immutable function\");\n                require(oldFacetAddress != _newFacetAddress, \"LibDiamondCut: Can't replace function with same function\");\n                require(oldFacetAddress != address(0), \"LibDiamondCut: Can't replace function that doesn't exist\");\n                // replace old facet address\n                ds.facets[selector] = (oldFacet & CLEAR_ADDRESS_MASK) | bytes20(_newFacetAddress);\n\n                unchecked {\n                    selectorIndex++;\n                }\n            }\n        } else if (_action == IDiamondCut.FacetCutAction.Remove) {\n            require(_newFacetAddress == address(0), \"LibDiamondCut: Remove facet address must be address(0)\");\n            // \"_selectorCount >> 3\" is a gas efficient division by 8 \"_selectorCount / 8\"\n            uint256 selectorSlotCount = _selectorCount >> 3;\n            // \"_selectorCount & 7\" is a gas efficient modulo by eight \"_selectorCount % 8\" \n            uint256 selectorInSlotIndex = _selectorCount & 7;\n            for (uint256 selectorIndex; selectorIndex < _selectors.length; ) {\n                if (_selectorSlot == 0) {\n                    // get last selectorSlot\n                    selectorSlotCount--;\n                    _selectorSlot = ds.selectorSlots[selectorSlotCount];\n                    selectorInSlotIndex = 7;\n                } else {\n                    selectorInSlotIndex--;\n                }\n                bytes4 lastSelector;\n                uint256 oldSelectorsSlotCount;\n                uint256 oldSelectorInSlotPosition;\n                // adding a block here prevents stack too deep error\n                {\n                    bytes4 selector = _selectors[selectorIndex];\n                    bytes32 oldFacet = ds.facets[selector];\n                    require(address(bytes20(oldFacet)) != address(0), \"LibDiamondCut: Can't remove function that doesn't exist\");\n                    // only useful if immutable functions exist\n                    require(address(bytes20(oldFacet)) != address(this), \"LibDiamondCut: Can't remove immutable function\");\n                    // replace selector with last selector in ds.facets\n                    // gets the last selector\n                    // \" << 5 is the same as multiplying by 32 ( * 32)\n                    lastSelector = bytes4(_selectorSlot << (selectorInSlotIndex << 5));\n                    if (lastSelector != selector) {\n                        // update last selector slot position info\n                        ds.facets[lastSelector] = (oldFacet & CLEAR_ADDRESS_MASK) | bytes20(ds.facets[lastSelector]);\n                    }\n                    delete ds.facets[selector];\n                    uint256 oldSelectorCount = uint16(uint256(oldFacet));\n                    // \"oldSelectorCount >> 3\" is a gas efficient division by 8 \"oldSelectorCount / 8\"\n                    oldSelectorsSlotCount = oldSelectorCount >> 3;\n                    // \"oldSelectorCount & 7\" is a gas efficient modulo by eight \"oldSelectorCount % 8\" \n                    // \" << 5 is the same as multiplying by 32 ( * 32)\n                    oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;\n                }\n                if (oldSelectorsSlotCount != selectorSlotCount) {\n                    bytes32 oldSelectorSlot = ds.selectorSlots[oldSelectorsSlotCount];\n                    // clears the selector we are deleting and puts the last selector in its place.\n                    oldSelectorSlot =\n                        (oldSelectorSlot & ~(CLEAR_SELECTOR_MASK >> oldSelectorInSlotPosition)) |\n                        (bytes32(lastSelector) >> oldSelectorInSlotPosition);\n                    // update storage with the modified slot\n                    ds.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;\n                } else {\n                    // clears the selector we are deleting and puts the last selector in its place.\n                    _selectorSlot =\n                        (_selectorSlot & ~(CLEAR_SELECTOR_MASK >> oldSelectorInSlotPosition)) |\n                        (bytes32(lastSelector) >> oldSelectorInSlotPosition);\n                }\n                if (selectorInSlotIndex == 0) {\n                    delete ds.selectorSlots[selectorSlotCount];\n                    _selectorSlot = 0;\n                }\n\n                unchecked {\n                    selectorIndex++;\n                }\n            }\n            _selectorCount = selectorSlotCount * 8 + selectorInSlotIndex;\n        } else {\n            revert(\"LibDiamondCut: Incorrect FacetCutAction\");\n        }\n        return (_selectorCount, _selectorSlot);\n    }\n\n    function initializeDiamondCut(address _init, bytes memory _calldata) internal {\n        if (_init == address(0)) {\n            return;\n        }\n        enforceHasContractCode(_init, \"LibDiamondCut: _init address has no code\");        \n        (bool success, bytes memory error) = _init.delegatecall(_calldata);\n        if (!success) {\n            if (error.length > 0) {\n                // bubble up error\n                /// @solidity memory-safe-assembly\n                assembly {\n                    let returndata_size := mload(error)\n                    revert(add(32, error), returndata_size)\n                }\n            } else {\n                revert InitializationFunctionReverted(_init, _calldata);\n            }\n        }\n    }\n\n    function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\n        uint256 contractSize;\n        assembly {\n            contractSize := extcodesize(_contract)\n        }\n        require(contractSize > 0, _errorMessage);\n    }\n}"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}