ETH Price: $2,513.97 (-1.79%)

Transaction Decoder

Block:
17278131 at May-17-2023 08:19:23 AM +UTC
Transaction Fee:
0.025338578870111874 ETH $63.70
Gas Used:
582,591 Gas / 43.492911614 Gwei

Emitted Events:

161 Zora1155.Upgraded( implementation=ZoraCreator1155Impl )
162 Zora1155Factory.0xa45800684f65ae010ceb4385eceaed88dec7f6a6bcbe11f7ffd8bd24dd2653f4( 0xa45800684f65ae010ceb4385eceaed88dec7f6a6bcbe11f7ffd8bd24dd2653f4, 0x000000000000000000000000ac59216e41ad9e611ba30aa6eefea87085524cde, 0x00000000000000000000000027b4a2eb472c280b17b79c315f79c522b038afcf, 0x00000000000000000000000027b4a2eb472c280b17b79c315f79c522b038afcf, 00000000000000000000000000000000000000000000000000000000000000a0, 0000000000000000000000000000000000000000000000000000000000000120, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b726569686d336e6175727a3272366d75676a343676, 716d3571757033326b7236766b6d68706e32347a377235727561726b76616877, 7171000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000007, 4149204b61796100000000000000000000000000000000000000000000000000 )
163 Zora1155.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x00000000000000000000000027b4a2eb472c280b17b79c315f79c522b038afcf, 0x0000000000000000000000000000000000000000000000000000000000000002 )
164 Zora1155.0x5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe( 0x5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000060, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b726569686d336e6175727a3272366d75676a343676, 716d3571757033326b7236766b6d68706e32347a377235727561726b76616877, 7171000000000000000000000000000000000000000000000000000000000000 )
165 Zora1155.0x5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d( 0x5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
166 Zora1155.0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0( 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0, 0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000027b4a2eb472c280b17b79c315f79c522b038afcf )
167 Zora1155.0x3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f( 0x3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000027b4a2eb472c280b17b79c315f79c522b038afcf, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
168 Zora1155.0x3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f( 0x3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000001, 00000000000000000000000027b4a2eb472c280b17b79c315f79c522b038afcf, 0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000027b4a2eb472c280b17b79c315f79c522b038afcf, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
169 Zora1155.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000002 )
170 Zora1155.0x5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe( 0x5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000060, 000000000000000000000000000000000000000000000000ffffffffffffffff, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b72656967716736373774356766626977727166626a, 65347a6d336f766f726265647663367564686333376c32376573357468707574, 3779000000000000000000000000000000000000000000000000000000000000 )
171 Zora1155.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000002 )
172 Zora1155.0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b( 0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b, 0x0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b72656967716736373774356766626977727166626a, 65347a6d336f766f726265647663367564686333376c32376573357468707574, 3779000000000000000000000000000000000000000000000000000000000000 )
173 Zora1155.0x1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc068( 0x1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc068, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0000000000000000000000000000000000000000000000000000000000000040, 000000000000000000000000000000000000000000000000ffffffffffffffff, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b72656967716736373774356766626977727166626a, 65347a6d336f766f726265647663367564686333376c32376573357468707574, 3779000000000000000000000000000000000000000000000000000000000000 )
174 Zora1155.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000000 )
175 Zora1155.0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498, 0000000000000000000000000000000000000000000000000000000000000001 )

Account State Difference:

  Address   Before After State Difference Code
0x27B4a2eB...2B038aFCF
0.108624287333871039 Eth
Nonce: 53
0.083285708463759165 Eth
Nonce: 54
0.025338578870111874
(beaverbuild)
92.429359489267050199 Eth92.429417748367050199 Eth0.0000582591
0xA6C5f2DE...91748cb85
0xAC59216e...085524Cde
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 7580990366191477516319551431636853775417539837550867334602508048238757929087879027900449337487518794946950352205601743281030887287489436310908839699191659809388444823355674645354979357162961249134900110529687881663019692932138136169432064773836259952710621644470898343405927174133984597236657651087359028670195474342013788531238380808257890765480551801068149982708333191330653462914990335414292036779052701522397263760767722087683826927505529058253836023112924693032821268011500407724974790870433127585371125309201813375400424860628391336808226709444821043

Execution Trace

Zora1155Factory.0582823a( )
  • ZoraCreator1155FactoryImpl.createContract( newContractURI=ipfs://bafkreihm3naurz2r6mugj46vqm5qup32kr6vkmhpn24z7r5ruarkvahwqq, name=AI Kaya, defaultRoyaltyConfiguration=[{name:royaltyMintSchedule, type:uint32, order:1, indexed:false, value:0, valueString:0}, {name:royaltyBPS, type:uint32, order:2, indexed:false, value:0, valueString:0}, {name:royaltyRecipient, type:address, order:3, indexed:false, value:0x0000000000000000000000000000000000000000, valueString:0x0000000000000000000000000000000000000000}], defaultAdmin=0x27B4a2eB472C280b17B79c315F79C522B038aFCF, setupActions=[5yh4tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, 0lhgmgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQmlwZnM6Ly9iYWZrcmVpZ3FnNjc3dDVnZmJpd3JxZmJqZTR6bTNvdm9yYmVkdmM2dWRoYzM3bDI3ZXM1dGhwdXQ3eQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==] ) => ( 0xAC59216e41aD9E611BA30aa6EEFea87085524Cde )
    • Zora1155.60406080( )
    • Zora1155.8a08eb4c( )
      • ZoraCreator1155Impl.initialize( contractName=AI Kaya, newContractURI=ipfs://bafkreihm3naurz2r6mugj46vqm5qup32kr6vkmhpn24z7r5ruarkvahwqq, defaultRoyaltyConfiguration=[{name:royaltyMintSchedule, type:uint32, order:1, indexed:false, value:0, valueString:0}, {name:royaltyBPS, type:uint32, order:2, indexed:false, value:0, valueString:0}, {name:royaltyRecipient, type:address, order:3, indexed:false, value:0x0000000000000000000000000000000000000000, valueString:0x0000000000000000000000000000000000000000}], defaultAdmin=0x27B4a2eB472C280b17B79c315F79C522B038aFCF, setupActions=[5yh4tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, 0lhgmgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQmlwZnM6Ly9iYWZrcmVpZ3FnNjc3dDVnZmJpd3JxZmJqZTR6bTNvdm9yYmVkdmM2dWRoYzM3bDI3ZXM1dGhwdXQ3eQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==] )
        • Zora1155.e72878b4( )
        • Zora1155.d258609a( )
          • ZoraCreator1155Impl.setupNewToken( newURI=ipfs://bafkreigqg677t5gfbiwrqfbje4zm3ovorbedvc6udhc37l27es5thput7y, maxSupply=18446744073709551615 ) => ( 1 )
            File 1 of 4: Zora1155Factory
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            /*
                         ░░░░░░░░░░░░░░              
                    ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                  ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
               ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
              ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
              ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
               ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                  ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                      ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                           OURS TRULY,
             */
            interface Enjoy {
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
             * proxy whose upgrades are fully controlled by the current implementation.
             */
            interface IERC1822Proxiable {
                /**
                 * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
                 * address.
                 *
                 * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
                 * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
                 * function revert if invoked through a proxy.
                 */
                function proxiableUUID() external view returns (bytes32);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)
            pragma solidity ^0.8.0;
            import "../Proxy.sol";
            import "./ERC1967Upgrade.sol";
            /**
             * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
             * implementation address that can be changed. This address is stored in storage in the location specified by
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
             * implementation behind the proxy.
             */
            contract ERC1967Proxy is Proxy, ERC1967Upgrade {
                /**
                 * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
                 *
                 * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
                 * function call, and allows initializing the storage of the proxy like a Solidity constructor.
                 */
                constructor(address _logic, bytes memory _data) payable {
                    _upgradeToAndCall(_logic, _data, false);
                }
                /**
                 * @dev Returns the current implementation address.
                 */
                function _implementation() internal view virtual override returns (address impl) {
                    return ERC1967Upgrade._getImplementation();
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
            pragma solidity ^0.8.2;
            import "../beacon/IBeacon.sol";
            import "../../interfaces/draft-IERC1822.sol";
            import "../../utils/Address.sol";
            import "../../utils/StorageSlot.sol";
            /**
             * @dev This abstract contract provides getters and event emitting update functions for
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
             *
             * _Available since v4.1._
             *
             * @custom:oz-upgrades-unsafe-allow delegatecall
             */
            abstract contract ERC1967Upgrade {
                // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
                bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
                /**
                 * @dev Storage slot with the address of the current implementation.
                 * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                /**
                 * @dev Emitted when the implementation is upgraded.
                 */
                event Upgraded(address indexed implementation);
                /**
                 * @dev Returns the current implementation address.
                 */
                function _getImplementation() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 implementation slot.
                 */
                function _setImplementation(address newImplementation) private {
                    require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                    StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                }
                /**
                 * @dev Perform implementation upgrade
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeTo(address newImplementation) internal {
                    _setImplementation(newImplementation);
                    emit Upgraded(newImplementation);
                }
                /**
                 * @dev Perform implementation upgrade with additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCall(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _upgradeTo(newImplementation);
                    if (data.length > 0 || forceCall) {
                        Address.functionDelegateCall(newImplementation, data);
                    }
                }
                /**
                 * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCallUUPS(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    // Upgrades from old implementations will perform a rollback test. This test requires the new
                    // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
                    // this special case will break upgrade paths from old UUPS implementation to new ones.
                    if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
                        _setImplementation(newImplementation);
                    } else {
                        try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                            require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
                        } catch {
                            revert("ERC1967Upgrade: new implementation is not UUPS");
                        }
                        _upgradeToAndCall(newImplementation, data, forceCall);
                    }
                }
                /**
                 * @dev Storage slot with the admin of the contract.
                 * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                /**
                 * @dev Emitted when the admin account has changed.
                 */
                event AdminChanged(address previousAdmin, address newAdmin);
                /**
                 * @dev Returns the current admin.
                 */
                function _getAdmin() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 admin slot.
                 */
                function _setAdmin(address newAdmin) private {
                    require(newAdmin != address(0), "ERC1967: new admin is the zero address");
                    StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
                }
                /**
                 * @dev Changes the admin of the proxy.
                 *
                 * Emits an {AdminChanged} event.
                 */
                function _changeAdmin(address newAdmin) internal {
                    emit AdminChanged(_getAdmin(), newAdmin);
                    _setAdmin(newAdmin);
                }
                /**
                 * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
                 * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
                 */
                bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
                /**
                 * @dev Emitted when the beacon is upgraded.
                 */
                event BeaconUpgraded(address indexed beacon);
                /**
                 * @dev Returns the current beacon.
                 */
                function _getBeacon() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
                }
                /**
                 * @dev Stores a new beacon in the EIP1967 beacon slot.
                 */
                function _setBeacon(address newBeacon) private {
                    require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
                    require(
                        Address.isContract(IBeacon(newBeacon).implementation()),
                        "ERC1967: beacon implementation is not a contract"
                    );
                    StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
                }
                /**
                 * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
                 * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
                 *
                 * Emits a {BeaconUpgraded} event.
                 */
                function _upgradeBeaconToAndCall(
                    address newBeacon,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _setBeacon(newBeacon);
                    emit BeaconUpgraded(newBeacon);
                    if (data.length > 0 || forceCall) {
                        Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
             * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
             * be specified by overriding the virtual {_implementation} function.
             *
             * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
             * different contract through the {_delegate} function.
             *
             * The success and return data of the delegated call will be returned back to the caller of the proxy.
             */
            abstract contract Proxy {
                /**
                 * @dev Delegates the current call to `implementation`.
                 *
                 * This function does not return to its internal call site, it will return directly to the external caller.
                 */
                function _delegate(address implementation) internal virtual {
                    assembly {
                        // Copy msg.data. We take full control of memory in this inline assembly
                        // block because it will not return to Solidity code. We overwrite the
                        // Solidity scratch pad at memory position 0.
                        calldatacopy(0, 0, calldatasize())
                        // Call the implementation.
                        // out and outsize are 0 because we don't know the size yet.
                        let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                        // Copy the returned data.
                        returndatacopy(0, 0, returndatasize())
                        switch result
                        // delegatecall returns 0 on error.
                        case 0 {
                            revert(0, returndatasize())
                        }
                        default {
                            return(0, returndatasize())
                        }
                    }
                }
                /**
                 * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
                 * and {_fallback} should delegate.
                 */
                function _implementation() internal view virtual returns (address);
                /**
                 * @dev Delegates the current call to the address returned by `_implementation()`.
                 *
                 * This function does not return to its internal call site, it will return directly to the external caller.
                 */
                function _fallback() internal virtual {
                    _beforeFallback();
                    _delegate(_implementation());
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                 * function in the contract matches the call data.
                 */
                fallback() external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
                 * is empty.
                 */
                receive() external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
                 * call, or as part of the Solidity `fallback` or `receive` functions.
                 *
                 * If overridden should call `super._beforeFallback()`.
                 */
                function _beforeFallback() internal virtual {}
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev This is the interface that {BeaconProxy} expects of its beacon.
             */
            interface IBeacon {
                /**
                 * @dev Must return an address that can be used as a delegate call target.
                 *
                 * {BeaconProxy} will check that this address is a contract.
                 */
                function implementation() external view returns (address);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
            pragma solidity ^0.8.1;
            /**
             * @dev Collection of functions related to the address type
             */
            library Address {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 *
                 * [IMPORTANT]
                 * ====
                 * You shouldn't rely on `isContract` to protect against flash loan attacks!
                 *
                 * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                 * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                 * constructor.
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize/address.code.length, which returns 0
                    // for contracts in construction, since the code is only stored at the end
                    // of the constructor execution.
                    return account.code.length > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    (bool success, ) = recipient.call{value: amount}("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain `call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    (bool success, bytes memory returndata) = target.call{value: value}(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                 * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                 *
                 * _Available since v4.8._
                 */
                function verifyCallResultFromTarget(
                    address target,
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    if (success) {
                        if (returndata.length == 0) {
                            // only check isContract if the call was successful and the return data is empty
                            // otherwise we already know that it was a contract
                            require(isContract(target), "Address: call to non-contract");
                        }
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                /**
                 * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                 * revert reason or using the provided one.
                 *
                 * _Available since v4.3._
                 */
                function verifyCallResult(
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal pure returns (bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                function _revert(bytes memory returndata, string memory errorMessage) private pure {
                    // Look for revert reason and bubble it up if present
                    if (returndata.length > 0) {
                        // The easiest way to bubble the revert reason is using memory via assembly
                        /// @solidity memory-safe-assembly
                        assembly {
                            let returndata_size := mload(returndata)
                            revert(add(32, returndata), returndata_size)
                        }
                    } else {
                        revert(errorMessage);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Library for reading and writing primitive types to specific storage slots.
             *
             * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
             * This library helps with reading and writing to such slots without the need for inline assembly.
             *
             * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
             *
             * Example usage to set ERC1967 implementation slot:
             * ```
             * contract ERC1967 {
             *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
             *
             *     function _getImplementation() internal view returns (address) {
             *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
             *     }
             *
             *     function _setImplementation(address newImplementation) internal {
             *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
             *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
             *     }
             * }
             * ```
             *
             * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
             */
            library StorageSlot {
                struct AddressSlot {
                    address value;
                }
                struct BooleanSlot {
                    bool value;
                }
                struct Bytes32Slot {
                    bytes32 value;
                }
                struct Uint256Slot {
                    uint256 value;
                }
                /**
                 * @dev Returns an `AddressSlot` with member `value` located at `slot`.
                 */
                function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
                 */
                function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
                 */
                function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
                 */
                function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {Enjoy} from "_imagine/mint/Enjoy.sol";
            import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
            /*
                         ░░░░░░░░░░░░░░              
                    ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                  ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
               ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
              ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
              ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
               ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                  ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                      ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                           OURS TRULY,
             */
            /// Imagine. Mint. Enjoy.
            /// @notice Imagine. Mint. Enjoy.
            /// @author @iainnash / @tbtstl
            contract Zora1155Factory is Enjoy, ERC1967Proxy {
                constructor(address _logic, bytes memory _data) ERC1967Proxy(_logic, _data) {}
            }
            

            File 2 of 4: Zora1155
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            /*
                         ░░░░░░░░░░░░░░              
                    ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                  ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
               ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
              ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
              ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
               ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                  ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                      ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                           OURS TRULY,
             */
            interface Enjoy {
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
             * proxy whose upgrades are fully controlled by the current implementation.
             */
            interface IERC1822Proxiable {
                /**
                 * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
                 * address.
                 *
                 * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
                 * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
                 * function revert if invoked through a proxy.
                 */
                function proxiableUUID() external view returns (bytes32);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)
            pragma solidity ^0.8.0;
            import "../Proxy.sol";
            import "./ERC1967Upgrade.sol";
            /**
             * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
             * implementation address that can be changed. This address is stored in storage in the location specified by
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
             * implementation behind the proxy.
             */
            contract ERC1967Proxy is Proxy, ERC1967Upgrade {
                /**
                 * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
                 *
                 * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
                 * function call, and allows initializing the storage of the proxy like a Solidity constructor.
                 */
                constructor(address _logic, bytes memory _data) payable {
                    _upgradeToAndCall(_logic, _data, false);
                }
                /**
                 * @dev Returns the current implementation address.
                 */
                function _implementation() internal view virtual override returns (address impl) {
                    return ERC1967Upgrade._getImplementation();
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
            pragma solidity ^0.8.2;
            import "../beacon/IBeacon.sol";
            import "../../interfaces/draft-IERC1822.sol";
            import "../../utils/Address.sol";
            import "../../utils/StorageSlot.sol";
            /**
             * @dev This abstract contract provides getters and event emitting update functions for
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
             *
             * _Available since v4.1._
             *
             * @custom:oz-upgrades-unsafe-allow delegatecall
             */
            abstract contract ERC1967Upgrade {
                // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
                bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
                /**
                 * @dev Storage slot with the address of the current implementation.
                 * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                /**
                 * @dev Emitted when the implementation is upgraded.
                 */
                event Upgraded(address indexed implementation);
                /**
                 * @dev Returns the current implementation address.
                 */
                function _getImplementation() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 implementation slot.
                 */
                function _setImplementation(address newImplementation) private {
                    require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                    StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                }
                /**
                 * @dev Perform implementation upgrade
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeTo(address newImplementation) internal {
                    _setImplementation(newImplementation);
                    emit Upgraded(newImplementation);
                }
                /**
                 * @dev Perform implementation upgrade with additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCall(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _upgradeTo(newImplementation);
                    if (data.length > 0 || forceCall) {
                        Address.functionDelegateCall(newImplementation, data);
                    }
                }
                /**
                 * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCallUUPS(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    // Upgrades from old implementations will perform a rollback test. This test requires the new
                    // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
                    // this special case will break upgrade paths from old UUPS implementation to new ones.
                    if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
                        _setImplementation(newImplementation);
                    } else {
                        try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                            require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
                        } catch {
                            revert("ERC1967Upgrade: new implementation is not UUPS");
                        }
                        _upgradeToAndCall(newImplementation, data, forceCall);
                    }
                }
                /**
                 * @dev Storage slot with the admin of the contract.
                 * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                /**
                 * @dev Emitted when the admin account has changed.
                 */
                event AdminChanged(address previousAdmin, address newAdmin);
                /**
                 * @dev Returns the current admin.
                 */
                function _getAdmin() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 admin slot.
                 */
                function _setAdmin(address newAdmin) private {
                    require(newAdmin != address(0), "ERC1967: new admin is the zero address");
                    StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
                }
                /**
                 * @dev Changes the admin of the proxy.
                 *
                 * Emits an {AdminChanged} event.
                 */
                function _changeAdmin(address newAdmin) internal {
                    emit AdminChanged(_getAdmin(), newAdmin);
                    _setAdmin(newAdmin);
                }
                /**
                 * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
                 * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
                 */
                bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
                /**
                 * @dev Emitted when the beacon is upgraded.
                 */
                event BeaconUpgraded(address indexed beacon);
                /**
                 * @dev Returns the current beacon.
                 */
                function _getBeacon() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
                }
                /**
                 * @dev Stores a new beacon in the EIP1967 beacon slot.
                 */
                function _setBeacon(address newBeacon) private {
                    require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
                    require(
                        Address.isContract(IBeacon(newBeacon).implementation()),
                        "ERC1967: beacon implementation is not a contract"
                    );
                    StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
                }
                /**
                 * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
                 * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
                 *
                 * Emits a {BeaconUpgraded} event.
                 */
                function _upgradeBeaconToAndCall(
                    address newBeacon,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _setBeacon(newBeacon);
                    emit BeaconUpgraded(newBeacon);
                    if (data.length > 0 || forceCall) {
                        Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
             * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
             * be specified by overriding the virtual {_implementation} function.
             *
             * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
             * different contract through the {_delegate} function.
             *
             * The success and return data of the delegated call will be returned back to the caller of the proxy.
             */
            abstract contract Proxy {
                /**
                 * @dev Delegates the current call to `implementation`.
                 *
                 * This function does not return to its internal call site, it will return directly to the external caller.
                 */
                function _delegate(address implementation) internal virtual {
                    assembly {
                        // Copy msg.data. We take full control of memory in this inline assembly
                        // block because it will not return to Solidity code. We overwrite the
                        // Solidity scratch pad at memory position 0.
                        calldatacopy(0, 0, calldatasize())
                        // Call the implementation.
                        // out and outsize are 0 because we don't know the size yet.
                        let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                        // Copy the returned data.
                        returndatacopy(0, 0, returndatasize())
                        switch result
                        // delegatecall returns 0 on error.
                        case 0 {
                            revert(0, returndatasize())
                        }
                        default {
                            return(0, returndatasize())
                        }
                    }
                }
                /**
                 * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
                 * and {_fallback} should delegate.
                 */
                function _implementation() internal view virtual returns (address);
                /**
                 * @dev Delegates the current call to the address returned by `_implementation()`.
                 *
                 * This function does not return to its internal call site, it will return directly to the external caller.
                 */
                function _fallback() internal virtual {
                    _beforeFallback();
                    _delegate(_implementation());
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                 * function in the contract matches the call data.
                 */
                fallback() external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
                 * is empty.
                 */
                receive() external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
                 * call, or as part of the Solidity `fallback` or `receive` functions.
                 *
                 * If overridden should call `super._beforeFallback()`.
                 */
                function _beforeFallback() internal virtual {}
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev This is the interface that {BeaconProxy} expects of its beacon.
             */
            interface IBeacon {
                /**
                 * @dev Must return an address that can be used as a delegate call target.
                 *
                 * {BeaconProxy} will check that this address is a contract.
                 */
                function implementation() external view returns (address);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
            pragma solidity ^0.8.1;
            /**
             * @dev Collection of functions related to the address type
             */
            library Address {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 *
                 * [IMPORTANT]
                 * ====
                 * You shouldn't rely on `isContract` to protect against flash loan attacks!
                 *
                 * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                 * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                 * constructor.
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize/address.code.length, which returns 0
                    // for contracts in construction, since the code is only stored at the end
                    // of the constructor execution.
                    return account.code.length > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    (bool success, ) = recipient.call{value: amount}("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain `call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    (bool success, bytes memory returndata) = target.call{value: value}(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                 * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                 *
                 * _Available since v4.8._
                 */
                function verifyCallResultFromTarget(
                    address target,
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    if (success) {
                        if (returndata.length == 0) {
                            // only check isContract if the call was successful and the return data is empty
                            // otherwise we already know that it was a contract
                            require(isContract(target), "Address: call to non-contract");
                        }
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                /**
                 * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                 * revert reason or using the provided one.
                 *
                 * _Available since v4.3._
                 */
                function verifyCallResult(
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal pure returns (bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                function _revert(bytes memory returndata, string memory errorMessage) private pure {
                    // Look for revert reason and bubble it up if present
                    if (returndata.length > 0) {
                        // The easiest way to bubble the revert reason is using memory via assembly
                        /// @solidity memory-safe-assembly
                        assembly {
                            let returndata_size := mload(returndata)
                            revert(add(32, returndata), returndata_size)
                        }
                    } else {
                        revert(errorMessage);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Library for reading and writing primitive types to specific storage slots.
             *
             * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
             * This library helps with reading and writing to such slots without the need for inline assembly.
             *
             * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
             *
             * Example usage to set ERC1967 implementation slot:
             * ```
             * contract ERC1967 {
             *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
             *
             *     function _getImplementation() internal view returns (address) {
             *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
             *     }
             *
             *     function _setImplementation(address newImplementation) internal {
             *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
             *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
             *     }
             * }
             * ```
             *
             * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
             */
            library StorageSlot {
                struct AddressSlot {
                    address value;
                }
                struct BooleanSlot {
                    bool value;
                }
                struct Bytes32Slot {
                    bytes32 value;
                }
                struct Uint256Slot {
                    uint256 value;
                }
                /**
                 * @dev Returns an `AddressSlot` with member `value` located at `slot`.
                 */
                function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
                 */
                function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
                 */
                function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
                 */
                function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {Enjoy} from "_imagine/mint/Enjoy.sol";
            import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
            /*
                         ░░░░░░░░░░░░░░              
                    ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                  ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
               ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
              ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
              ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
               ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                  ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                      ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                           OURS TRULY,
             */
            /// Imagine. Mint. Enjoy.
            /// @notice Imagine. Mint. Enjoy.
            /// @author ZORA @iainnash / @tbtstl
            contract Zora1155 is Enjoy, ERC1967Proxy {
                constructor(address _logic) ERC1967Proxy(_logic, "") {}
            }
            

            File 3 of 4: ZoraCreator1155FactoryImpl
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
            import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
            import {IZoraCreator1155Factory} from "../interfaces/IZoraCreator1155Factory.sol";
            import {IZoraCreator1155Initializer} from "../interfaces/IZoraCreator1155Initializer.sol";
            import {IZoraCreator1155} from "../interfaces/IZoraCreator1155.sol";
            import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol";
            import {IMinter1155} from "../interfaces/IMinter1155.sol";
            import {IContractMetadata} from "../interfaces/IContractMetadata.sol";
            import {Ownable2StepUpgradeable} from "../utils/ownable/Ownable2StepUpgradeable.sol";
            import {FactoryManagedUpgradeGate} from "../upgrades/FactoryManagedUpgradeGate.sol";
            import {Zora1155} from "../proxies/Zora1155.sol";
            import {ContractVersionBase} from "../version/ContractVersionBase.sol";
            /// @title ZoraCreator1155FactoryImpl
            /// @notice Factory contract for creating new ZoraCreator1155 contracts
            contract ZoraCreator1155FactoryImpl is IZoraCreator1155Factory, ContractVersionBase, FactoryManagedUpgradeGate, UUPSUpgradeable, IContractMetadata {
                IZoraCreator1155 public immutable implementation;
                IMinter1155 public immutable merkleMinter;
                IMinter1155 public immutable fixedPriceMinter;
                IMinter1155 public immutable redeemMinterFactory;
                constructor(IZoraCreator1155 _implementation, IMinter1155 _merkleMinter, IMinter1155 _fixedPriceMinter, IMinter1155 _redeemMinterFactory) initializer {
                    implementation = _implementation;
                    if (address(implementation) == address(0)) {
                        revert Constructor_ImplCannotBeZero();
                    }
                    merkleMinter = _merkleMinter;
                    fixedPriceMinter = _fixedPriceMinter;
                    redeemMinterFactory = _redeemMinterFactory;
                }
                /// @notice ContractURI for contract information with the strategy
                function contractURI() external pure returns (string memory) {
                    return "https://github.com/ourzora/zora-1155-contracts/";
                }
                /// @notice The name of the sale strategy
                function contractName() external pure returns (string memory) {
                    return "ZORA 1155 Contract Factory";
                }
                /// @notice The default minters for new 1155 contracts
                function defaultMinters() external view returns (IMinter1155[] memory minters) {
                    minters = new IMinter1155[](3);
                    minters[0] = fixedPriceMinter;
                    minters[1] = merkleMinter;
                    minters[2] = redeemMinterFactory;
                }
                function initialize(address _initialOwner) public initializer {
                    __Ownable_init(_initialOwner);
                    __UUPSUpgradeable_init();
                    emit FactorySetup();
                }
                /// @notice Creates a new ZoraCreator1155 contract
                /// @param newContractURI The URI for the contract metadata
                /// @param name The name of the contract
                /// @param defaultRoyaltyConfiguration The default royalty configuration for the contract
                /// @param defaultAdmin The default admin for the contract
                /// @param setupActions The actions to perform on the new contract upon initialization
                function createContract(
                    string memory newContractURI,
                    string calldata name,
                    ICreatorRoyaltiesControl.RoyaltyConfiguration memory defaultRoyaltyConfiguration,
                    address payable defaultAdmin,
                    bytes[] calldata setupActions
                ) external returns (address) {
                    address newContract = address(new Zora1155(address(implementation)));
                    emit SetupNewContract({
                        newContract: address(newContract),
                        creator: msg.sender,
                        defaultAdmin: defaultAdmin,
                        contractURI: newContractURI,
                        name: name,
                        defaultRoyaltyConfiguration: defaultRoyaltyConfiguration
                    });
                    IZoraCreator1155Initializer(newContract).initialize(name, newContractURI, defaultRoyaltyConfiguration, defaultAdmin, setupActions);
                    return address(newContract);
                }
                ///                                                          ///
                ///                         MANAGER UPGRADE                  ///
                ///                                                          ///
                /// @notice Ensures the caller is authorized to upgrade the contract
                /// @dev This function is called in `upgradeTo` & `upgradeToAndCall`
                /// @param _newImpl The new implementation address
                function _authorizeUpgrade(address _newImpl) internal override onlyOwner {}
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)
            pragma solidity ^0.8.2;
            import "../../utils/AddressUpgradeable.sol";
            /**
             * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
             * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
             * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
             * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
             *
             * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
             * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
             * case an upgrade adds a module that needs to be initialized.
             *
             * For example:
             *
             * [.hljs-theme-light.nopadding]
             * ```
             * contract MyToken is ERC20Upgradeable {
             *     function initialize() initializer public {
             *         __ERC20_init("MyToken", "MTK");
             *     }
             * }
             * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
             *     function initializeV2() reinitializer(2) public {
             *         __ERC20Permit_init("MyToken");
             *     }
             * }
             * ```
             *
             * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
             * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
             *
             * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
             * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
             *
             * [CAUTION]
             * ====
             * Avoid leaving a contract uninitialized.
             *
             * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
             * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
             * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
             *
             * [.hljs-theme-light.nopadding]
             * ```
             * /// @custom:oz-upgrades-unsafe-allow constructor
             * constructor() {
             *     _disableInitializers();
             * }
             * ```
             * ====
             */
            abstract contract Initializable {
                /**
                 * @dev Indicates that the contract has been initialized.
                 * @custom:oz-retyped-from bool
                 */
                uint8 private _initialized;
                /**
                 * @dev Indicates that the contract is in the process of being initialized.
                 */
                bool private _initializing;
                /**
                 * @dev Triggered when the contract has been initialized or reinitialized.
                 */
                event Initialized(uint8 version);
                /**
                 * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
                 * `onlyInitializing` functions can be used to initialize parent contracts.
                 *
                 * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
                 * constructor.
                 *
                 * Emits an {Initialized} event.
                 */
                modifier initializer() {
                    bool isTopLevelCall = !_initializing;
                    require(
                        (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
                        "Initializable: contract is already initialized"
                    );
                    _initialized = 1;
                    if (isTopLevelCall) {
                        _initializing = true;
                    }
                    _;
                    if (isTopLevelCall) {
                        _initializing = false;
                        emit Initialized(1);
                    }
                }
                /**
                 * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
                 * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
                 * used to initialize parent contracts.
                 *
                 * A reinitializer may be used after the original initialization step. This is essential to configure modules that
                 * are added through upgrades and that require initialization.
                 *
                 * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
                 * cannot be nested. If one is invoked in the context of another, execution will revert.
                 *
                 * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
                 * a contract, executing them in the right order is up to the developer or operator.
                 *
                 * WARNING: setting the version to 255 will prevent any future reinitialization.
                 *
                 * Emits an {Initialized} event.
                 */
                modifier reinitializer(uint8 version) {
                    require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
                    _initialized = version;
                    _initializing = true;
                    _;
                    _initializing = false;
                    emit Initialized(version);
                }
                /**
                 * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
                 * {initializer} and {reinitializer} modifiers, directly or indirectly.
                 */
                modifier onlyInitializing() {
                    require(_initializing, "Initializable: contract is not initializing");
                    _;
                }
                /**
                 * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
                 * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
                 * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
                 * through proxies.
                 *
                 * Emits an {Initialized} event the first time it is successfully executed.
                 */
                function _disableInitializers() internal virtual {
                    require(!_initializing, "Initializable: contract is initializing");
                    if (_initialized < type(uint8).max) {
                        _initialized = type(uint8).max;
                        emit Initialized(type(uint8).max);
                    }
                }
                /**
                 * @dev Returns the highest version that has been initialized. See {reinitializer}.
                 */
                function _getInitializedVersion() internal view returns (uint8) {
                    return _initialized;
                }
                /**
                 * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
                 */
                function _isInitializing() internal view returns (bool) {
                    return _initializing;
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol)
            pragma solidity ^0.8.0;
            import "../../interfaces/draft-IERC1822Upgradeable.sol";
            import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
            import "./Initializable.sol";
            /**
             * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
             * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
             *
             * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
             * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
             * `UUPSUpgradeable` with a custom implementation of upgrades.
             *
             * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
             *
             * _Available since v4.1._
             */
            abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
                function __UUPSUpgradeable_init() internal onlyInitializing {
                }
                function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
                }
                /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
                address private immutable __self = address(this);
                /**
                 * @dev Check that the execution is being performed through a delegatecall call and that the execution context is
                 * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
                 * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
                 * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
                 * fail.
                 */
                modifier onlyProxy() {
                    require(address(this) != __self, "Function must be called through delegatecall");
                    require(_getImplementation() == __self, "Function must be called through active proxy");
                    _;
                }
                /**
                 * @dev Check that the execution is not being performed through a delegate call. This allows a function to be
                 * callable on the implementing contract but not through proxies.
                 */
                modifier notDelegated() {
                    require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
                    _;
                }
                /**
                 * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
                 * implementation. It is used to validate the implementation's compatibility when performing an upgrade.
                 *
                 * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
                 * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
                 * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
                 */
                function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
                    return _IMPLEMENTATION_SLOT;
                }
                /**
                 * @dev Upgrade the implementation of the proxy to `newImplementation`.
                 *
                 * Calls {_authorizeUpgrade}.
                 *
                 * Emits an {Upgraded} event.
                 */
                function upgradeTo(address newImplementation) external virtual onlyProxy {
                    _authorizeUpgrade(newImplementation);
                    _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
                }
                /**
                 * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
                 * encoded in `data`.
                 *
                 * Calls {_authorizeUpgrade}.
                 *
                 * Emits an {Upgraded} event.
                 */
                function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {
                    _authorizeUpgrade(newImplementation);
                    _upgradeToAndCallUUPS(newImplementation, data, true);
                }
                /**
                 * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
                 * {upgradeTo} and {upgradeToAndCall}.
                 *
                 * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
                 *
                 * ```solidity
                 * function _authorizeUpgrade(address) internal override onlyOwner {}
                 * ```
                 */
                function _authorizeUpgrade(address newImplementation) internal virtual;
                /**
                 * @dev This empty reserved space is put in place to allow future versions to add new
                 * variables without shifting down storage in the inheritance chain.
                 * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
                 */
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {ICreatorRoyaltiesControl} from "./ICreatorRoyaltiesControl.sol";
            import {IMinter1155} from "./IMinter1155.sol";
            import {IVersionedContract} from "./IVersionedContract.sol";
            /// @notice Factory for 1155 contracts
            /// @author @iainnash / @tbtstl
            interface IZoraCreator1155Factory is IVersionedContract {
                error Constructor_ImplCannotBeZero();
                event FactorySetup();
                event SetupNewContract(
                    address indexed newContract,
                    address indexed creator,
                    address indexed defaultAdmin,
                    string contractURI,
                    string name,
                    ICreatorRoyaltiesControl.RoyaltyConfiguration defaultRoyaltyConfiguration
                );
                function createContract(
                    string memory contractURI,
                    string calldata name,
                    ICreatorRoyaltiesControl.RoyaltyConfiguration memory defaultRoyaltyConfiguration,
                    address payable defaultAdmin,
                    bytes[] calldata setupActions
                ) external returns (address);
                function defaultMinters() external returns (IMinter1155[] memory minters);
                function initialize(address _owner) external;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol";
            interface IZoraCreator1155Initializer {
                function initialize(
                    string memory contractName,
                    string memory newContractURI,
                    ICreatorRoyaltiesControl.RoyaltyConfiguration memory defaultRoyaltyConfiguration,
                    address payable defaultAdmin,
                    bytes[] calldata setupActions
                ) external;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
            import {IERC1155MetadataURIUpgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC1155MetadataURIUpgradeable.sol";
            import {IZoraCreator1155TypesV1} from "../nft/IZoraCreator1155TypesV1.sol";
            import {IRenderer1155} from "../interfaces/IRenderer1155.sol";
            import {IMinter1155} from "../interfaces/IMinter1155.sol";
            import {IOwnable} from "../interfaces/IOwnable.sol";
            import {IVersionedContract} from "./IVersionedContract.sol";
            import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol";
            /*
                         ░░░░░░░░░░░░░░              
                    ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                  ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
               ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
              ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
              ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
               ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                  ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                      ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                           OURS TRULY,
             */
            /// @notice Main interface for the ZoraCreator1155 contract
            /// @author @iainnash / @tbtstl
            interface IZoraCreator1155 is IZoraCreator1155TypesV1, IVersionedContract, IOwnable, IERC1155MetadataURIUpgradeable {
                function PERMISSION_BIT_ADMIN() external returns (uint256);
                function PERMISSION_BIT_MINTER() external returns (uint256);
                function PERMISSION_BIT_SALES() external returns (uint256);
                function PERMISSION_BIT_METADATA() external returns (uint256);
                /// @notice Used to label the configuration update type
                enum ConfigUpdate {
                    OWNER,
                    FUNDS_RECIPIENT,
                    TRANSFER_HOOK
                }
                event ConfigUpdated(address indexed updater, ConfigUpdate indexed updateType, ContractConfig newConfig);
                event UpdatedToken(address indexed from, uint256 indexed tokenId, TokenData tokenData);
                event SetupNewToken(uint256 indexed tokenId, address indexed sender, string newURI, uint256 maxSupply);
                function setOwner(address newOwner) external;
                event ContractRendererUpdated(IRenderer1155 renderer);
                event ContractMetadataUpdated(address indexed updater, string uri, string name);
                event Purchased(address indexed sender, address indexed minter, uint256 indexed tokenId, uint256 quantity, uint256 value);
                error TokenIdMismatch(uint256 expected, uint256 actual);
                error UserMissingRoleForToken(address user, uint256 tokenId, uint256 role);
                error Config_TransferHookNotSupported(address proposedAddress);
                error Mint_InsolventSaleTransfer();
                error Mint_ValueTransferFail();
                error Mint_TokenIDMintNotAllowed();
                error Mint_UnknownCommand();
                error Burn_NotOwnerOrApproved(address operator, address user);
                error NewOwnerNeedsToBeAdmin();
                error Sale_CannotCallNonSalesContract(address targetContract);
                error CallFailed(bytes reason);
                error Renderer_NotValidRendererContract();
                error ETHWithdrawFailed(address recipient, uint256 amount);
                error FundsWithdrawInsolvent(uint256 amount, uint256 contractValue);
                error CannotMintMoreTokens(uint256 tokenId, uint256 quantity, uint256 totalMinted, uint256 maxSupply);
                /// @notice Only allow minting one token id at time
                /// @dev Mint contract function that calls the underlying sales function for commands
                /// @param minter Address for the minter
                /// @param tokenId tokenId to mint, set to 0 for new tokenId
                /// @param quantity to mint
                /// @param minterArguments calldata for the minter contracts
                function mint(IMinter1155 minter, uint256 tokenId, uint256 quantity, bytes calldata minterArguments) external payable;
                function adminMint(address recipient, uint256 tokenId, uint256 quantity, bytes memory data) external;
                function adminMintBatch(address recipient, uint256[] memory tokenIds, uint256[] memory quantities, bytes memory data) external;
                function burnBatch(address user, uint256[] calldata tokenIds, uint256[] calldata amounts) external;
                /// @notice Contract call to setupNewToken
                /// @param tokenURI URI for the token
                /// @param maxSupply maxSupply for the token, set to 0 for open edition
                function setupNewToken(string memory tokenURI, uint256 maxSupply) external returns (uint256 tokenId);
                function updateTokenURI(uint256 tokenId, string memory _newURI) external;
                function updateContractMetadata(string memory _newURI, string memory _newName) external;
                // Public interface for `setTokenMetadataRenderer(uint256, address) has been deprecated.
                function contractURI() external view returns (string memory);
                function assumeLastTokenIdMatches(uint256 tokenId) external;
                function updateRoyaltiesForToken(uint256 tokenId, ICreatorRoyaltiesControl.RoyaltyConfiguration memory royaltyConfiguration) external;
                function addPermission(uint256 tokenId, address user, uint256 permissionBits) external;
                function removePermission(uint256 tokenId, address user, uint256 permissionBits) external;
                function isAdminOrRole(address user, uint256 tokenId, uint256 role) external view returns (bool);
                function getTokenInfo(uint256 tokenId) external view returns (TokenData memory);
                function callRenderer(uint256 tokenId, bytes memory data) external;
                function callSale(uint256 tokenId, IMinter1155 salesConfig, bytes memory data) external;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol";
            interface ICreatorRoyaltiesControl is IERC2981 {
                /// @notice The RoyaltyConfiguration struct is used to store the royalty configuration for a given token.
                /// @param royaltyMintSchedule Every nth token will go to the royalty recipient.
                /// @param royaltyBPS The royalty amount in basis points for secondary sales.
                /// @param royaltyRecipient The address that will receive the royalty payments.
                struct RoyaltyConfiguration {
                    uint32 royaltyMintSchedule;
                    uint32 royaltyBPS;
                    address royaltyRecipient;
                }
                /// @notice Thrown when a user tries to have 100% supply royalties
                error InvalidMintSchedule();
                /// @notice Event emitted when royalties are updated
                event UpdatedRoyalties(uint256 indexed tokenId, address indexed user, RoyaltyConfiguration configuration);
                /// @notice External data getter to get royalties for a token
                /// @param tokenId tokenId to get royalties configuration for
                function getRoyalties(uint256 tokenId) external view returns (RoyaltyConfiguration memory);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
            import {ICreatorCommands} from "./ICreatorCommands.sol";
            /// @notice Minter standard interface
            /// @dev Minters need to confirm to the ERC165 selector of type(IMinter1155).interfaceId
            interface IMinter1155 is IERC165Upgradeable {
                function requestMint(
                    address sender,
                    uint256 tokenId,
                    uint256 quantity,
                    uint256 ethValueSent,
                    bytes calldata minterArguments
                ) external returns (ICreatorCommands.CommandSet memory commands);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            interface IContractMetadata {
                /// @notice Contract name returns the pretty contract name
                function contractName() external returns (string memory);
                /// @notice Contract URI returns the uri for more information about the given contract
                function contractURI() external returns (string memory);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IOwnable2StepUpgradeable} from "./IOwnable2StepUpgradeable.sol";
            import {IOwnable2StepStorageV1} from "./IOwnable2StepStorageV1.sol";
            import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
            /// @title Ownable
            /// @author Rohan Kulkarni / Iain Nash
            /// @notice Modified from OpenZeppelin Contracts v4.7.3 (access/OwnableUpgradeable.sol)
            /// - Uses custom errors declared in IOwnable
            /// - Adds optional two-step ownership transfer (`safeTransferOwnership` + `acceptOwnership`)
            abstract contract Ownable2StepUpgradeable is IOwnable2StepUpgradeable, IOwnable2StepStorageV1, Initializable {
                ///                                                          ///
                ///                            STORAGE                       ///
                ///                                                          ///
                /// @dev Modifier to check if the address argument is the zero/burn address
                modifier notZeroAddress(address check) {
                    if (check == address(0)) {
                        revert OWNER_CANNOT_BE_ZERO_ADDRESS();
                    }
                    _;
                }
                ///                                                          ///
                ///                           MODIFIERS                      ///
                ///                                                          ///
                /// @dev Ensures the caller is the owner
                modifier onlyOwner() {
                    if (msg.sender != _owner) {
                        revert ONLY_OWNER();
                    }
                    _;
                }
                /// @dev Ensures the caller is the pending owner
                modifier onlyPendingOwner() {
                    if (msg.sender != _pendingOwner) {
                        revert ONLY_PENDING_OWNER();
                    }
                    _;
                }
                ///                                                          ///
                ///                           FUNCTIONS                      ///
                ///                                                          ///
                /// @dev Initializes contract ownership
                /// @param _initialOwner The initial owner address
                function __Ownable_init(address _initialOwner) internal notZeroAddress(_initialOwner) onlyInitializing {
                    _owner = _initialOwner;
                    emit OwnerUpdated(address(0), _initialOwner);
                }
                /// @notice The address of the owner
                function owner() public view virtual returns (address) {
                    return _owner;
                }
                /// @notice The address of the pending owner
                function pendingOwner() public view returns (address) {
                    return _pendingOwner;
                }
                /// @notice Forces an ownership transfer from the last owner
                /// @param _newOwner The new owner address
                function transferOwnership(address _newOwner) public notZeroAddress(_newOwner) onlyOwner {
                    _transferOwnership(_newOwner);
                }
                /// @notice Forces an ownership transfer from any sender
                /// @param _newOwner New owner to transfer contract to
                /// @dev Ensure is called only from trusted internal code, no access control checks.
                function _transferOwnership(address _newOwner) internal {
                    emit OwnerUpdated(_owner, _newOwner);
                    _owner = _newOwner;
                    if (_pendingOwner != address(0)) {
                        delete _pendingOwner;
                    }
                }
                /// @notice Initiates a two-step ownership transfer
                /// @param _newOwner The new owner address
                function safeTransferOwnership(address _newOwner) public notZeroAddress(_newOwner) onlyOwner {
                    _pendingOwner = _newOwner;
                    emit OwnerPending(_owner, _newOwner);
                }
                /// @notice Resign ownership of contract
                /// @dev only callably by the owner, dangerous call.
                function resignOwnership() public onlyOwner {
                    _transferOwnership(address(0));
                }
                /// @notice Accepts an ownership transfer
                function acceptOwnership() public onlyPendingOwner {
                    emit OwnerUpdated(_owner, msg.sender);
                    _transferOwnership(msg.sender);
                }
                /// @notice Cancels a pending ownership transfer
                function cancelOwnershipTransfer() public onlyOwner {
                    emit OwnerCanceled(_owner, _pendingOwner);
                    delete _pendingOwner;
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IFactoryManagedUpgradeGate} from "../interfaces/IFactoryManagedUpgradeGate.sol";
            import {Ownable2StepUpgradeable} from "../utils/ownable/Ownable2StepUpgradeable.sol";
            import {FactoryManagedUpgradeGateStorageV1} from "./FactoryManagedUpgradeGateStorageV1.sol";
            /// @title FactoryManagedUpgradeGate
            /// @notice Contract for managing upgrades and safe upgrade paths for 1155 contracts
            abstract contract FactoryManagedUpgradeGate is IFactoryManagedUpgradeGate, Ownable2StepUpgradeable, FactoryManagedUpgradeGateStorageV1 {
                ///                                                          ///
                ///                CREATOR TOKEN UPGRADES                    ///
                ///                                                          ///
                /// @notice If an implementation is registered by the Builder DAO as an optional upgrade
                /// @param baseImpl The base implementation address
                /// @param upgradeImpl The upgrade implementation address
                function isRegisteredUpgradePath(address baseImpl, address upgradeImpl) public view returns (bool) {
                    return isAllowedUpgrade[baseImpl][upgradeImpl];
                }
                /// @notice Called by the Builder DAO to offer implementation upgrades for created DAOs
                /// @param baseImpls The base implementation addresses
                /// @param upgradeImpl The upgrade implementation address
                function registerUpgradePath(address[] memory baseImpls, address upgradeImpl) public onlyOwner {
                    unchecked {
                        for (uint256 i = 0; i < baseImpls.length; ++i) {
                            isAllowedUpgrade[baseImpls[i]][upgradeImpl] = true;
                            emit UpgradeRegistered(baseImpls[i], upgradeImpl);
                        }
                    }
                }
                /// @notice Called by the Builder DAO to remove an upgrade
                /// @param baseImpl The base implementation address
                /// @param upgradeImpl The upgrade implementation address
                function removeUpgradePath(address baseImpl, address upgradeImpl) public onlyOwner {
                    delete isAllowedUpgrade[baseImpl][upgradeImpl];
                    emit UpgradeRemoved(baseImpl, upgradeImpl);
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {Enjoy} from "_imagine/mint/Enjoy.sol";
            import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
            /*
                         ░░░░░░░░░░░░░░              
                    ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                  ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
               ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
              ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
              ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
               ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                  ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                      ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                           OURS TRULY,
             */
            /// Imagine. Mint. Enjoy.
            /// @notice Imagine. Mint. Enjoy.
            /// @author ZORA @iainnash / @tbtstl
            contract Zora1155 is Enjoy, ERC1967Proxy {
                constructor(address _logic) ERC1967Proxy(_logic, "") {}
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IVersionedContract} from "../interfaces/IVersionedContract.sol";
            /// @title ContractVersionBase
            /// @notice Base contract for versioning contracts
            contract ContractVersionBase is IVersionedContract {
                /// @notice The version of the contract
                function contractVersion() external pure override returns (string memory) {
                    return "1.3.0";
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
            pragma solidity ^0.8.1;
            /**
             * @dev Collection of functions related to the address type
             */
            library AddressUpgradeable {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 *
                 * [IMPORTANT]
                 * ====
                 * You shouldn't rely on `isContract` to protect against flash loan attacks!
                 *
                 * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                 * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                 * constructor.
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize/address.code.length, which returns 0
                    // for contracts in construction, since the code is only stored at the end
                    // of the constructor execution.
                    return account.code.length > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    (bool success, ) = recipient.call{value: amount}("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain `call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    (bool success, bytes memory returndata) = target.call{value: value}(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                 * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                 *
                 * _Available since v4.8._
                 */
                function verifyCallResultFromTarget(
                    address target,
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    if (success) {
                        if (returndata.length == 0) {
                            // only check isContract if the call was successful and the return data is empty
                            // otherwise we already know that it was a contract
                            require(isContract(target), "Address: call to non-contract");
                        }
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                /**
                 * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                 * revert reason or using the provided one.
                 *
                 * _Available since v4.3._
                 */
                function verifyCallResult(
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal pure returns (bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                function _revert(bytes memory returndata, string memory errorMessage) private pure {
                    // Look for revert reason and bubble it up if present
                    if (returndata.length > 0) {
                        // The easiest way to bubble the revert reason is using memory via assembly
                        /// @solidity memory-safe-assembly
                        assembly {
                            let returndata_size := mload(returndata)
                            revert(add(32, returndata), returndata_size)
                        }
                    } else {
                        revert(errorMessage);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
             * proxy whose upgrades are fully controlled by the current implementation.
             */
            interface IERC1822ProxiableUpgradeable {
                /**
                 * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
                 * address.
                 *
                 * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
                 * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
                 * function revert if invoked through a proxy.
                 */
                function proxiableUUID() external view returns (bytes32);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
            pragma solidity ^0.8.2;
            import "../beacon/IBeaconUpgradeable.sol";
            import "../../interfaces/draft-IERC1822Upgradeable.sol";
            import "../../utils/AddressUpgradeable.sol";
            import "../../utils/StorageSlotUpgradeable.sol";
            import "../utils/Initializable.sol";
            /**
             * @dev This abstract contract provides getters and event emitting update functions for
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
             *
             * _Available since v4.1._
             *
             * @custom:oz-upgrades-unsafe-allow delegatecall
             */
            abstract contract ERC1967UpgradeUpgradeable is Initializable {
                function __ERC1967Upgrade_init() internal onlyInitializing {
                }
                function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
                }
                // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
                bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
                /**
                 * @dev Storage slot with the address of the current implementation.
                 * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                /**
                 * @dev Emitted when the implementation is upgraded.
                 */
                event Upgraded(address indexed implementation);
                /**
                 * @dev Returns the current implementation address.
                 */
                function _getImplementation() internal view returns (address) {
                    return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 implementation slot.
                 */
                function _setImplementation(address newImplementation) private {
                    require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                    StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                }
                /**
                 * @dev Perform implementation upgrade
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeTo(address newImplementation) internal {
                    _setImplementation(newImplementation);
                    emit Upgraded(newImplementation);
                }
                /**
                 * @dev Perform implementation upgrade with additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCall(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _upgradeTo(newImplementation);
                    if (data.length > 0 || forceCall) {
                        _functionDelegateCall(newImplementation, data);
                    }
                }
                /**
                 * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCallUUPS(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    // Upgrades from old implementations will perform a rollback test. This test requires the new
                    // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
                    // this special case will break upgrade paths from old UUPS implementation to new ones.
                    if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {
                        _setImplementation(newImplementation);
                    } else {
                        try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                            require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
                        } catch {
                            revert("ERC1967Upgrade: new implementation is not UUPS");
                        }
                        _upgradeToAndCall(newImplementation, data, forceCall);
                    }
                }
                /**
                 * @dev Storage slot with the admin of the contract.
                 * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                /**
                 * @dev Emitted when the admin account has changed.
                 */
                event AdminChanged(address previousAdmin, address newAdmin);
                /**
                 * @dev Returns the current admin.
                 */
                function _getAdmin() internal view returns (address) {
                    return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 admin slot.
                 */
                function _setAdmin(address newAdmin) private {
                    require(newAdmin != address(0), "ERC1967: new admin is the zero address");
                    StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
                }
                /**
                 * @dev Changes the admin of the proxy.
                 *
                 * Emits an {AdminChanged} event.
                 */
                function _changeAdmin(address newAdmin) internal {
                    emit AdminChanged(_getAdmin(), newAdmin);
                    _setAdmin(newAdmin);
                }
                /**
                 * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
                 * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
                 */
                bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
                /**
                 * @dev Emitted when the beacon is upgraded.
                 */
                event BeaconUpgraded(address indexed beacon);
                /**
                 * @dev Returns the current beacon.
                 */
                function _getBeacon() internal view returns (address) {
                    return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
                }
                /**
                 * @dev Stores a new beacon in the EIP1967 beacon slot.
                 */
                function _setBeacon(address newBeacon) private {
                    require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
                    require(
                        AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
                        "ERC1967: beacon implementation is not a contract"
                    );
                    StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
                }
                /**
                 * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
                 * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
                 *
                 * Emits a {BeaconUpgraded} event.
                 */
                function _upgradeBeaconToAndCall(
                    address newBeacon,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _setBeacon(newBeacon);
                    emit BeaconUpgraded(newBeacon);
                    if (data.length > 0 || forceCall) {
                        _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
                    }
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {
                    require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed");
                }
                /**
                 * @dev This empty reserved space is put in place to allow future versions to add new
                 * variables without shifting down storage in the inheritance chain.
                 * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
                 */
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            interface IVersionedContract {
                function contractVersion() external returns (string memory);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol)
            pragma solidity ^0.8.0;
            import "../utils/introspection/IERC165Upgradeable.sol";
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1155MetadataURI.sol)
            pragma solidity ^0.8.0;
            import "../token/ERC1155/extensions/IERC1155MetadataURIUpgradeable.sol";
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {ITransferHookReceiver} from "../interfaces/ITransferHookReceiver.sol";
            /*
                         ░░░░░░░░░░░░░░              
                    ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                  ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
               ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
              ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
              ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
               ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                  ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                      ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                           OURS TRULY,
             */
            /// Imagine. Mint. Enjoy.
            /// @notice Interface for types used across the ZoraCreator1155 contract
            /// @author @iainnash / @tbtstl
            interface IZoraCreator1155TypesV1 {
                /// @notice Used to store individual token data
                struct TokenData {
                    string uri;
                    uint256 maxSupply;
                    uint256 totalMinted;
                }
                /// @notice Used to store contract-level configuration
                struct ContractConfig {
                    address owner;
                    uint96 __gap1;
                    address payable fundsRecipient;
                    uint96 __gap2;
                    ITransferHookReceiver transferHook;
                    uint96 __gap3;
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
            /// @dev IERC165 type required
            interface IRenderer1155 is IERC165Upgradeable {
                /// @notice Called for assigned tokenId, or when token id is globally set to a renderer
                /// @dev contract target is assumed to be msg.sender
                /// @param tokenId token id to get uri for
                function uri(uint256 tokenId) external view returns (string memory);
                /// @notice Only called for tokenId == 0
                /// @dev contract target is assumed to be msg.sender
                function contractURI() external view returns (string memory);
                /// @notice Sets up renderer from contract
                /// @param initData data to setup renderer with
                /// @dev contract target is assumed to be msg.sender
                function setup(bytes memory initData) external;
                // IERC165 type required – set in base helper
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            interface IOwnable {
                function owner() external returns (address);
                event OwnershipTransferred(address lastOwner, address newOwner);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)
            pragma solidity ^0.8.0;
            import "../utils/introspection/IERC165.sol";
            /**
             * @dev Interface for the NFT Royalty Standard.
             *
             * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
             * support for royalty payments across all NFT marketplaces and ecosystem participants.
             *
             * _Available since v4.5._
             */
            interface IERC2981 is IERC165 {
                /**
                 * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
                 * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
                 */
                function royaltyInfo(uint256 tokenId, uint256 salePrice)
                    external
                    view
                    returns (address receiver, uint256 royaltyAmount);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            /// @notice Creator Commands used by minter modules passed back to the main modules
            interface ICreatorCommands {
                /// @notice This enum is used to define supported creator action types.
                /// This can change in the future
                enum CreatorActions {
                    // No operation - also the default for mintings that may not return a command
                    NO_OP,
                    // Send ether
                    SEND_ETH,
                    // Mint operation
                    MINT
                }
                /// @notice This command is for
                struct Command {
                    // Method for operation
                    CreatorActions method;
                    // Arguments used for this operation
                    bytes args;
                }
                /// @notice This command set is returned from the minter back to the user
                struct CommandSet {
                    Command[] commands;
                    uint256 at;
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            /// @title IOwnable2StepUpgradeable
            /// @author Rohan Kulkarni
            /// @notice The external Ownable events, errors, and functions
            interface IOwnable2StepUpgradeable {
                ///                                                          ///
                ///                            EVENTS                        ///
                ///                                                          ///
                /// @notice Emitted when ownership has been updated
                /// @param prevOwner The previous owner address
                /// @param newOwner The new owner address
                event OwnerUpdated(address indexed prevOwner, address indexed newOwner);
                /// @notice Emitted when an ownership transfer is pending
                /// @param owner The current owner address
                /// @param pendingOwner The pending new owner address
                event OwnerPending(address indexed owner, address indexed pendingOwner);
                /// @notice Emitted when a pending ownership transfer has been canceled
                /// @param owner The current owner address
                /// @param canceledOwner The canceled owner address
                event OwnerCanceled(address indexed owner, address indexed canceledOwner);
                ///                                                          ///
                ///                            ERRORS                        ///
                ///                                                          ///
                /// @dev Reverts if an unauthorized user calls an owner function
                error ONLY_OWNER();
                /// @dev Reverts if an unauthorized user calls a pending owner function
                error ONLY_PENDING_OWNER();
                /// @dev Owner cannot be the zero/burn address
                error OWNER_CANNOT_BE_ZERO_ADDRESS();
                ///                                                          ///
                ///                           FUNCTIONS                      ///
                ///                                                          ///
                /// @notice The address of the owner
                function owner() external view returns (address);
                /// @notice The address of the pending owner
                function pendingOwner() external view returns (address);
                /// @notice Forces an ownership transfer
                /// @param newOwner The new owner address
                function transferOwnership(address newOwner) external;
                /// @notice Initiates a two-step ownership transfer
                /// @param newOwner The new owner address
                function safeTransferOwnership(address newOwner) external;
                /// @notice Accepts an ownership transfer
                function acceptOwnership() external;
                /// @notice Cancels a pending ownership transfer
                function cancelOwnershipTransfer() external;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            abstract contract IOwnable2StepStorageV1 {
                /// @dev The address of the owner
                address internal _owner;
                /// @dev The address of the pending owner
                address internal _pendingOwner;
                /// @dev storage gap
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            /// @notice Factory Upgrade Gate Admin Factory Implementation – Allows specific contract upgrades as a safety measure
            interface IFactoryManagedUpgradeGate {
                /// @notice If an implementation is registered by the Builder DAO as an optional upgrade
                /// @param baseImpl The base implementation address
                /// @param upgradeImpl The upgrade implementation address
                function isRegisteredUpgradePath(address baseImpl, address upgradeImpl) external view returns (bool);
                /// @notice Called by the Builder DAO to offer implementation upgrades for created DAOs
                /// @param baseImpls The base implementation addresses
                /// @param upgradeImpl The upgrade implementation address
                function registerUpgradePath(address[] memory baseImpls, address upgradeImpl) external;
                /// @notice Called by the Builder DAO to remove an upgrade
                /// @param baseImpl The base implementation address
                /// @param upgradeImpl The upgrade implementation address
                function removeUpgradePath(address baseImpl, address upgradeImpl) external;
                event UpgradeRegistered(address indexed baseImpl, address indexed upgradeImpl);
                event UpgradeRemoved(address indexed baseImpl, address indexed upgradeImpl);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            abstract contract FactoryManagedUpgradeGateStorageV1 {
                mapping(address => mapping(address => bool)) public isAllowedUpgrade;
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            /*
                         ░░░░░░░░░░░░░░              
                    ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                  ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
               ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
              ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
              ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
               ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                  ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                      ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                           OURS TRULY,
             */
            interface Enjoy {
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)
            pragma solidity ^0.8.0;
            import "../Proxy.sol";
            import "./ERC1967Upgrade.sol";
            /**
             * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
             * implementation address that can be changed. This address is stored in storage in the location specified by
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
             * implementation behind the proxy.
             */
            contract ERC1967Proxy is Proxy, ERC1967Upgrade {
                /**
                 * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
                 *
                 * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
                 * function call, and allows initializing the storage of the proxy like a Solidity constructor.
                 */
                constructor(address _logic, bytes memory _data) payable {
                    _upgradeToAndCall(_logic, _data, false);
                }
                /**
                 * @dev Returns the current implementation address.
                 */
                function _implementation() internal view virtual override returns (address impl) {
                    return ERC1967Upgrade._getImplementation();
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev This is the interface that {BeaconProxy} expects of its beacon.
             */
            interface IBeaconUpgradeable {
                /**
                 * @dev Must return an address that can be used as a delegate call target.
                 *
                 * {BeaconProxy} will check that this address is a contract.
                 */
                function implementation() external view returns (address);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Library for reading and writing primitive types to specific storage slots.
             *
             * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
             * This library helps with reading and writing to such slots without the need for inline assembly.
             *
             * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
             *
             * Example usage to set ERC1967 implementation slot:
             * ```
             * contract ERC1967 {
             *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
             *
             *     function _getImplementation() internal view returns (address) {
             *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
             *     }
             *
             *     function _setImplementation(address newImplementation) internal {
             *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
             *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
             *     }
             * }
             * ```
             *
             * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
             */
            library StorageSlotUpgradeable {
                struct AddressSlot {
                    address value;
                }
                struct BooleanSlot {
                    bool value;
                }
                struct Bytes32Slot {
                    bytes32 value;
                }
                struct Uint256Slot {
                    uint256 value;
                }
                /**
                 * @dev Returns an `AddressSlot` with member `value` located at `slot`.
                 */
                function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
                 */
                function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
                 */
                function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
                 */
                function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Interface of the ERC165 standard, as defined in the
             * https://eips.ethereum.org/EIPS/eip-165[EIP].
             *
             * Implementers can declare support of contract interfaces, which can then be
             * queried by others ({ERC165Checker}).
             *
             * For an implementation, see {ERC165}.
             */
            interface IERC165Upgradeable {
                /**
                 * @dev Returns true if this contract implements the interface defined by
                 * `interfaceId`. See the corresponding
                 * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
                 * to learn more about how these ids are created.
                 *
                 * This function call must use less than 30 000 gas.
                 */
                function supportsInterface(bytes4 interfaceId) external view returns (bool);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)
            pragma solidity ^0.8.0;
            import "../IERC1155Upgradeable.sol";
            /**
             * @dev Interface of the optional ERC1155MetadataExtension interface, as defined
             * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
             *
             * _Available since v3.1._
             */
            interface IERC1155MetadataURIUpgradeable is IERC1155Upgradeable {
                /**
                 * @dev Returns the URI for token type `id`.
                 *
                 * If the `\\{id\\}` substring is present in the URI, it must be replaced by
                 * clients with the actual token type ID.
                 */
                function uri(uint256 id) external view returns (string memory);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
            interface ITransferHookReceiver is IERC165Upgradeable {
                /// @notice Token transfer batch callback
                /// @param target target contract for transfer
                /// @param operator operator address for transfer
                /// @param from user address for amount transferred
                /// @param to user address for amount transferred
                /// @param ids list of token ids transferred
                /// @param amounts list of values transferred
                /// @param data data as perscribed by 1155 standard
                function onTokenTransferBatch(
                    address target,
                    address operator,
                    address from,
                    address to,
                    uint256[] memory ids,
                    uint256[] memory amounts,
                    bytes memory data
                ) external;
                // IERC165 type required
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Interface of the ERC165 standard, as defined in the
             * https://eips.ethereum.org/EIPS/eip-165[EIP].
             *
             * Implementers can declare support of contract interfaces, which can then be
             * queried by others ({ERC165Checker}).
             *
             * For an implementation, see {ERC165}.
             */
            interface IERC165 {
                /**
                 * @dev Returns true if this contract implements the interface defined by
                 * `interfaceId`. See the corresponding
                 * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
                 * to learn more about how these ids are created.
                 *
                 * This function call must use less than 30 000 gas.
                 */
                function supportsInterface(bytes4 interfaceId) external view returns (bool);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
             * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
             * be specified by overriding the virtual {_implementation} function.
             *
             * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
             * different contract through the {_delegate} function.
             *
             * The success and return data of the delegated call will be returned back to the caller of the proxy.
             */
            abstract contract Proxy {
                /**
                 * @dev Delegates the current call to `implementation`.
                 *
                 * This function does not return to its internal call site, it will return directly to the external caller.
                 */
                function _delegate(address implementation) internal virtual {
                    assembly {
                        // Copy msg.data. We take full control of memory in this inline assembly
                        // block because it will not return to Solidity code. We overwrite the
                        // Solidity scratch pad at memory position 0.
                        calldatacopy(0, 0, calldatasize())
                        // Call the implementation.
                        // out and outsize are 0 because we don't know the size yet.
                        let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                        // Copy the returned data.
                        returndatacopy(0, 0, returndatasize())
                        switch result
                        // delegatecall returns 0 on error.
                        case 0 {
                            revert(0, returndatasize())
                        }
                        default {
                            return(0, returndatasize())
                        }
                    }
                }
                /**
                 * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
                 * and {_fallback} should delegate.
                 */
                function _implementation() internal view virtual returns (address);
                /**
                 * @dev Delegates the current call to the address returned by `_implementation()`.
                 *
                 * This function does not return to its internal call site, it will return directly to the external caller.
                 */
                function _fallback() internal virtual {
                    _beforeFallback();
                    _delegate(_implementation());
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                 * function in the contract matches the call data.
                 */
                fallback() external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
                 * is empty.
                 */
                receive() external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
                 * call, or as part of the Solidity `fallback` or `receive` functions.
                 *
                 * If overridden should call `super._beforeFallback()`.
                 */
                function _beforeFallback() internal virtual {}
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
            pragma solidity ^0.8.2;
            import "../beacon/IBeacon.sol";
            import "../../interfaces/draft-IERC1822.sol";
            import "../../utils/Address.sol";
            import "../../utils/StorageSlot.sol";
            /**
             * @dev This abstract contract provides getters and event emitting update functions for
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
             *
             * _Available since v4.1._
             *
             * @custom:oz-upgrades-unsafe-allow delegatecall
             */
            abstract contract ERC1967Upgrade {
                // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
                bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
                /**
                 * @dev Storage slot with the address of the current implementation.
                 * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                /**
                 * @dev Emitted when the implementation is upgraded.
                 */
                event Upgraded(address indexed implementation);
                /**
                 * @dev Returns the current implementation address.
                 */
                function _getImplementation() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 implementation slot.
                 */
                function _setImplementation(address newImplementation) private {
                    require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                    StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                }
                /**
                 * @dev Perform implementation upgrade
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeTo(address newImplementation) internal {
                    _setImplementation(newImplementation);
                    emit Upgraded(newImplementation);
                }
                /**
                 * @dev Perform implementation upgrade with additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCall(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _upgradeTo(newImplementation);
                    if (data.length > 0 || forceCall) {
                        Address.functionDelegateCall(newImplementation, data);
                    }
                }
                /**
                 * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCallUUPS(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    // Upgrades from old implementations will perform a rollback test. This test requires the new
                    // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
                    // this special case will break upgrade paths from old UUPS implementation to new ones.
                    if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
                        _setImplementation(newImplementation);
                    } else {
                        try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                            require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
                        } catch {
                            revert("ERC1967Upgrade: new implementation is not UUPS");
                        }
                        _upgradeToAndCall(newImplementation, data, forceCall);
                    }
                }
                /**
                 * @dev Storage slot with the admin of the contract.
                 * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                /**
                 * @dev Emitted when the admin account has changed.
                 */
                event AdminChanged(address previousAdmin, address newAdmin);
                /**
                 * @dev Returns the current admin.
                 */
                function _getAdmin() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 admin slot.
                 */
                function _setAdmin(address newAdmin) private {
                    require(newAdmin != address(0), "ERC1967: new admin is the zero address");
                    StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
                }
                /**
                 * @dev Changes the admin of the proxy.
                 *
                 * Emits an {AdminChanged} event.
                 */
                function _changeAdmin(address newAdmin) internal {
                    emit AdminChanged(_getAdmin(), newAdmin);
                    _setAdmin(newAdmin);
                }
                /**
                 * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
                 * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
                 */
                bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
                /**
                 * @dev Emitted when the beacon is upgraded.
                 */
                event BeaconUpgraded(address indexed beacon);
                /**
                 * @dev Returns the current beacon.
                 */
                function _getBeacon() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
                }
                /**
                 * @dev Stores a new beacon in the EIP1967 beacon slot.
                 */
                function _setBeacon(address newBeacon) private {
                    require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
                    require(
                        Address.isContract(IBeacon(newBeacon).implementation()),
                        "ERC1967: beacon implementation is not a contract"
                    );
                    StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
                }
                /**
                 * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
                 * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
                 *
                 * Emits a {BeaconUpgraded} event.
                 */
                function _upgradeBeaconToAndCall(
                    address newBeacon,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _setBeacon(newBeacon);
                    emit BeaconUpgraded(newBeacon);
                    if (data.length > 0 || forceCall) {
                        Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)
            pragma solidity ^0.8.0;
            import "../../utils/introspection/IERC165Upgradeable.sol";
            /**
             * @dev Required interface of an ERC1155 compliant contract, as defined in the
             * https://eips.ethereum.org/EIPS/eip-1155[EIP].
             *
             * _Available since v3.1._
             */
            interface IERC1155Upgradeable is IERC165Upgradeable {
                /**
                 * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
                 */
                event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
                /**
                 * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
                 * transfers.
                 */
                event TransferBatch(
                    address indexed operator,
                    address indexed from,
                    address indexed to,
                    uint256[] ids,
                    uint256[] values
                );
                /**
                 * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
                 * `approved`.
                 */
                event ApprovalForAll(address indexed account, address indexed operator, bool approved);
                /**
                 * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
                 *
                 * If an {URI} event was emitted for `id`, the standard
                 * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
                 * returned by {IERC1155MetadataURI-uri}.
                 */
                event URI(string value, uint256 indexed id);
                /**
                 * @dev Returns the amount of tokens of token type `id` owned by `account`.
                 *
                 * Requirements:
                 *
                 * - `account` cannot be the zero address.
                 */
                function balanceOf(address account, uint256 id) external view returns (uint256);
                /**
                 * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
                 *
                 * Requirements:
                 *
                 * - `accounts` and `ids` must have the same length.
                 */
                function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
                    external
                    view
                    returns (uint256[] memory);
                /**
                 * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
                 *
                 * Emits an {ApprovalForAll} event.
                 *
                 * Requirements:
                 *
                 * - `operator` cannot be the caller.
                 */
                function setApprovalForAll(address operator, bool approved) external;
                /**
                 * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
                 *
                 * See {setApprovalForAll}.
                 */
                function isApprovedForAll(address account, address operator) external view returns (bool);
                /**
                 * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
                 *
                 * Emits a {TransferSingle} event.
                 *
                 * Requirements:
                 *
                 * - `to` cannot be the zero address.
                 * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
                 * - `from` must have a balance of tokens of type `id` of at least `amount`.
                 * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
                 * acceptance magic value.
                 */
                function safeTransferFrom(
                    address from,
                    address to,
                    uint256 id,
                    uint256 amount,
                    bytes calldata data
                ) external;
                /**
                 * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
                 *
                 * Emits a {TransferBatch} event.
                 *
                 * Requirements:
                 *
                 * - `ids` and `amounts` must have the same length.
                 * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
                 * acceptance magic value.
                 */
                function safeBatchTransferFrom(
                    address from,
                    address to,
                    uint256[] calldata ids,
                    uint256[] calldata amounts,
                    bytes calldata data
                ) external;
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev This is the interface that {BeaconProxy} expects of its beacon.
             */
            interface IBeacon {
                /**
                 * @dev Must return an address that can be used as a delegate call target.
                 *
                 * {BeaconProxy} will check that this address is a contract.
                 */
                function implementation() external view returns (address);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
             * proxy whose upgrades are fully controlled by the current implementation.
             */
            interface IERC1822Proxiable {
                /**
                 * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
                 * address.
                 *
                 * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
                 * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
                 * function revert if invoked through a proxy.
                 */
                function proxiableUUID() external view returns (bytes32);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
            pragma solidity ^0.8.1;
            /**
             * @dev Collection of functions related to the address type
             */
            library Address {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 *
                 * [IMPORTANT]
                 * ====
                 * You shouldn't rely on `isContract` to protect against flash loan attacks!
                 *
                 * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                 * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                 * constructor.
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize/address.code.length, which returns 0
                    // for contracts in construction, since the code is only stored at the end
                    // of the constructor execution.
                    return account.code.length > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    (bool success, ) = recipient.call{value: amount}("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain `call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    (bool success, bytes memory returndata) = target.call{value: value}(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                 * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                 *
                 * _Available since v4.8._
                 */
                function verifyCallResultFromTarget(
                    address target,
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    if (success) {
                        if (returndata.length == 0) {
                            // only check isContract if the call was successful and the return data is empty
                            // otherwise we already know that it was a contract
                            require(isContract(target), "Address: call to non-contract");
                        }
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                /**
                 * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                 * revert reason or using the provided one.
                 *
                 * _Available since v4.3._
                 */
                function verifyCallResult(
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal pure returns (bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                function _revert(bytes memory returndata, string memory errorMessage) private pure {
                    // Look for revert reason and bubble it up if present
                    if (returndata.length > 0) {
                        // The easiest way to bubble the revert reason is using memory via assembly
                        /// @solidity memory-safe-assembly
                        assembly {
                            let returndata_size := mload(returndata)
                            revert(add(32, returndata), returndata_size)
                        }
                    } else {
                        revert(errorMessage);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Library for reading and writing primitive types to specific storage slots.
             *
             * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
             * This library helps with reading and writing to such slots without the need for inline assembly.
             *
             * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
             *
             * Example usage to set ERC1967 implementation slot:
             * ```
             * contract ERC1967 {
             *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
             *
             *     function _getImplementation() internal view returns (address) {
             *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
             *     }
             *
             *     function _setImplementation(address newImplementation) internal {
             *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
             *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
             *     }
             * }
             * ```
             *
             * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
             */
            library StorageSlot {
                struct AddressSlot {
                    address value;
                }
                struct BooleanSlot {
                    bool value;
                }
                struct Bytes32Slot {
                    bytes32 value;
                }
                struct Uint256Slot {
                    uint256 value;
                }
                /**
                 * @dev Returns an `AddressSlot` with member `value` located at `slot`.
                 */
                function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
                 */
                function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
                 */
                function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
                 */
                function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
            }
            

            File 4 of 4: ZoraCreator1155Impl
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {ERC1155Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol";
            import {IERC1155MetadataURIUpgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC1155MetadataURIUpgradeable.sol";
            import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
            import {IZoraCreator1155} from "../interfaces/IZoraCreator1155.sol";
            import {IZoraCreator1155Initializer} from "../interfaces/IZoraCreator1155Initializer.sol";
            import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
            import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
            import {ContractVersionBase} from "../version/ContractVersionBase.sol";
            import {CreatorPermissionControl} from "../permissions/CreatorPermissionControl.sol";
            import {CreatorRendererControl} from "../renderer/CreatorRendererControl.sol";
            import {CreatorRoyaltiesControl} from "../royalties/CreatorRoyaltiesControl.sol";
            import {ICreatorCommands} from "../interfaces/ICreatorCommands.sol";
            import {IMinter1155} from "../interfaces/IMinter1155.sol";
            import {IRenderer1155} from "../interfaces/IRenderer1155.sol";
            import {ITransferHookReceiver} from "../interfaces/ITransferHookReceiver.sol";
            import {IFactoryManagedUpgradeGate} from "../interfaces/IFactoryManagedUpgradeGate.sol";
            import {IZoraCreator1155} from "../interfaces/IZoraCreator1155.sol";
            import {LegacyNamingControl} from "../legacy-naming/LegacyNamingControl.sol";
            import {MintFeeManager} from "../fee/MintFeeManager.sol";
            import {PublicMulticall} from "../utils/PublicMulticall.sol";
            import {SharedBaseConstants} from "../shared/SharedBaseConstants.sol";
            import {TransferHelperUtils} from "../utils/TransferHelperUtils.sol";
            import {ZoraCreator1155StorageV1} from "./ZoraCreator1155StorageV1.sol";
            /// Imagine. Mint. Enjoy.
            /// @title ZoraCreator1155Impl
            /// @notice The core implementation contract for a creator's 1155 token
            /// @author @iainnash / @tbtstl
            contract ZoraCreator1155Impl is
                IZoraCreator1155,
                IZoraCreator1155Initializer,
                ContractVersionBase,
                ReentrancyGuardUpgradeable,
                PublicMulticall,
                ERC1155Upgradeable,
                MintFeeManager,
                UUPSUpgradeable,
                CreatorRendererControl,
                LegacyNamingControl,
                ZoraCreator1155StorageV1,
                CreatorPermissionControl,
                CreatorRoyaltiesControl
            {
                /// @notice This user role allows for any action to be performed
                uint256 public constant PERMISSION_BIT_ADMIN = 2 ** 1;
                /// @notice This user role allows for only mint actions to be performed
                uint256 public constant PERMISSION_BIT_MINTER = 2 ** 2;
                /// @notice This user role allows for only managing sales configurations
                uint256 public constant PERMISSION_BIT_SALES = 2 ** 3;
                /// @notice This user role allows for only managing metadata configuration
                uint256 public constant PERMISSION_BIT_METADATA = 2 ** 4;
                /// @notice This user role allows for only withdrawing funds and setting funds withdraw address
                uint256 public constant PERMISSION_BIT_FUNDS_MANAGER = 2 ** 5;
                /// @notice Factory contract
                IFactoryManagedUpgradeGate internal immutable factory;
                constructor(uint256 _mintFeeAmount, address _mintFeeRecipient, address _factory) MintFeeManager(_mintFeeAmount, _mintFeeRecipient) initializer {
                    factory = IFactoryManagedUpgradeGate(_factory);
                }
                /// @notice Initializes the contract
                /// @param contractName the legacy on-chain contract name
                /// @param newContractURI The contract URI
                /// @param defaultRoyaltyConfiguration The default royalty configuration
                /// @param defaultAdmin The default admin to manage the token
                /// @param setupActions The setup actions to run, if any
                function initialize(
                    string memory contractName,
                    string memory newContractURI,
                    RoyaltyConfiguration memory defaultRoyaltyConfiguration,
                    address payable defaultAdmin,
                    bytes[] calldata setupActions
                ) external nonReentrant initializer {
                    // We are not initalizing the OZ 1155 implementation
                    // to save contract storage space and runtime
                    // since the only thing affected here is the uri.
                    // __ERC1155_init("");
                    // Setup uups
                    __UUPSUpgradeable_init();
                    // Setup re-entracy guard
                    __ReentrancyGuard_init();
                    // Setup contract-default token ID
                    _setupDefaultToken(defaultAdmin, newContractURI, defaultRoyaltyConfiguration);
                    // Set owner to default admin
                    _setOwner(defaultAdmin);
                    _setFundsRecipient(defaultAdmin);
                    _setName(contractName);
                    // Run Setup actions
                    if (setupActions.length > 0) {
                        // Temporarily make sender admin
                        _addPermission(CONTRACT_BASE_ID, msg.sender, PERMISSION_BIT_ADMIN);
                        // Make calls
                        multicall(setupActions);
                        // Remove admin
                        _removePermission(CONTRACT_BASE_ID, msg.sender, PERMISSION_BIT_ADMIN);
                    }
                }
                /// @notice sets up the global configuration for the 1155 contract
                /// @param newContractURI The contract URI
                /// @param defaultRoyaltyConfiguration The default royalty configuration
                function _setupDefaultToken(address defaultAdmin, string memory newContractURI, RoyaltyConfiguration memory defaultRoyaltyConfiguration) internal {
                    // Add admin permission to default admin to manage contract
                    _addPermission(CONTRACT_BASE_ID, defaultAdmin, PERMISSION_BIT_ADMIN);
                    // Mint token ID 0 / don't allow any user mints
                    _setupNewToken(newContractURI, 0);
                    // Update default royalties
                    _updateRoyalties(CONTRACT_BASE_ID, defaultRoyaltyConfiguration);
                }
                /// @notice Updates the royalty configuration for a token
                /// @param tokenId The token ID to update
                /// @param newConfiguration The new royalty configuration
                function updateRoyaltiesForToken(
                    uint256 tokenId,
                    RoyaltyConfiguration memory newConfiguration
                ) external onlyAdminOrRole(tokenId, PERMISSION_BIT_FUNDS_MANAGER) {
                    _updateRoyalties(tokenId, newConfiguration);
                }
                /// @notice remove this function from openzeppelin impl
                /// @dev This makes this internal function a no-op
                function _setURI(string memory newuri) internal virtual override {}
                /// @notice This gets the next token in line to be minted when minting linearly (default behavior) and updates the counter
                function _getAndUpdateNextTokenId() internal returns (uint256) {
                    unchecked {
                        return nextTokenId++;
                    }
                }
                /// @notice Ensure that the next token ID is correct
                /// @dev This reverts if the invariant doesn't match. This is used for multicall token id assumptions
                /// @param lastTokenId The last token ID
                function assumeLastTokenIdMatches(uint256 lastTokenId) external view {
                    unchecked {
                        if (nextTokenId - 1 != lastTokenId) {
                            revert TokenIdMismatch(lastTokenId, nextTokenId - 1);
                        }
                    }
                }
                /// @notice Checks if a user either has a role for a token or if they are the admin
                /// @dev This is an internal function that is called by the external getter and internal functions
                /// @param user The user to check
                /// @param tokenId The token ID to check
                /// @param role The role to check
                /// @return true or false if the permission exists for the user given the token id
                function _isAdminOrRole(address user, uint256 tokenId, uint256 role) internal view returns (bool) {
                    return _hasAnyPermission(tokenId, user, PERMISSION_BIT_ADMIN | role);
                }
                /// @notice Checks if a user either has a role for a token or if they are the admin
                /// @param user The user to check
                /// @param tokenId The token ID to check
                /// @param role The role to check
                /// @return true or false if the permission exists for the user given the token id
                function isAdminOrRole(address user, uint256 tokenId, uint256 role) external view returns (bool) {
                    return _isAdminOrRole(user, tokenId, role);
                }
                /// @notice Checks if the user is an admin for the given tokenId
                /// @dev This function reverts if the permission does not exist for the given user and tokenId
                /// @param user user to check
                /// @param tokenId tokenId to check
                /// @param role role to check for admin
                function _requireAdminOrRole(address user, uint256 tokenId, uint256 role) internal view {
                    if (!(_hasAnyPermission(tokenId, user, PERMISSION_BIT_ADMIN | role) || _hasAnyPermission(CONTRACT_BASE_ID, user, PERMISSION_BIT_ADMIN))) {
                        revert UserMissingRoleForToken(user, tokenId, role);
                    }
                }
                /// @notice Checks if the user is an admin
                /// @dev This reverts if the user is not an admin for the given token id or contract
                /// @param user user to check
                /// @param tokenId tokenId to check
                function _requireAdmin(address user, uint256 tokenId) internal view {
                    if (!(_hasAnyPermission(tokenId, user, PERMISSION_BIT_ADMIN) || _hasAnyPermission(CONTRACT_BASE_ID, user, PERMISSION_BIT_ADMIN))) {
                        revert UserMissingRoleForToken(user, tokenId, PERMISSION_BIT_ADMIN);
                    }
                }
                /// @notice Modifier checking if the user is an admin or has a role
                /// @dev This reverts if the msg.sender is not an admin for the given token id or contract
                /// @param tokenId tokenId to check
                /// @param role role to check
                modifier onlyAdminOrRole(uint256 tokenId, uint256 role) {
                    _requireAdminOrRole(msg.sender, tokenId, role);
                    _;
                }
                /// @notice Modifier checking if the user is an admin
                /// @dev This reverts if the msg.sender is not an admin for the given token id or contract
                /// @param tokenId tokenId to check
                modifier onlyAdmin(uint256 tokenId) {
                    _requireAdmin(msg.sender, tokenId);
                    _;
                }
                /// @notice Modifier checking if the requested quantity of tokens can be minted for the tokenId
                /// @dev This reverts if the number that can be minted is exceeded
                /// @param tokenId token id to check available allowed quantity
                /// @param quantity requested to be minted
                modifier canMintQuantity(uint256 tokenId, uint256 quantity) {
                    _requireCanMintQuantity(tokenId, quantity);
                    _;
                }
                /// @notice Only from approved address for burn
                /// @param from address that the tokens will be burned from, validate that this is msg.sender or that msg.sender is approved
                modifier onlyFromApprovedForBurn(address from) {
                    if (from != msg.sender && !isApprovedForAll(from, msg.sender)) {
                        revert Burn_NotOwnerOrApproved(msg.sender, from);
                    }
                    _;
                }
                /// @notice Checks if a user can mint a quantity of a token
                /// @dev Reverts if the mint exceeds the allowed quantity (or if the token does not exist)
                /// @param tokenId The token ID to check
                /// @param quantity The quantity of tokens to mint to check
                function _requireCanMintQuantity(uint256 tokenId, uint256 quantity) internal view {
                    TokenData storage tokenInformation = tokens[tokenId];
                    if (tokenInformation.totalMinted + quantity > tokenInformation.maxSupply) {
                        revert CannotMintMoreTokens(tokenId, quantity, tokenInformation.totalMinted, tokenInformation.maxSupply);
                    }
                }
                /// @notice Set up a new token
                /// @param newURI The URI for the token
                /// @param maxSupply The maximum supply of the token
                function setupNewToken(
                    string memory newURI,
                    uint256 maxSupply
                ) public onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_MINTER) nonReentrant returns (uint256) {
                    uint256 tokenId = _setupNewToken(newURI, maxSupply);
                    // Allow the token creator to administrate this token
                    _addPermission(tokenId, msg.sender, PERMISSION_BIT_ADMIN);
                    if (bytes(newURI).length > 0) {
                        emit URI(newURI, tokenId);
                    }
                    emit SetupNewToken(tokenId, msg.sender, newURI, maxSupply);
                    return tokenId;
                }
                /// @notice Update the token URI for a token
                /// @param tokenId The token ID to update the URI for
                /// @param _newURI The new URI
                function updateTokenURI(uint256 tokenId, string memory _newURI) external onlyAdminOrRole(tokenId, PERMISSION_BIT_METADATA) {
                    if (tokenId == CONTRACT_BASE_ID) {
                        revert();
                    }
                    emit URI(_newURI, tokenId);
                    tokens[tokenId].uri = _newURI;
                }
                /// @notice Update the global contract metadata
                /// @param _newURI The new contract URI
                /// @param _newName The new contract name
                function updateContractMetadata(string memory _newURI, string memory _newName) external onlyAdminOrRole(0, PERMISSION_BIT_METADATA) {
                    tokens[CONTRACT_BASE_ID].uri = _newURI;
                    _setName(_newName);
                    emit ContractMetadataUpdated(msg.sender, _newURI, _newName);
                }
                function _setupNewToken(string memory newURI, uint256 maxSupply) internal returns (uint256 tokenId) {
                    tokenId = _getAndUpdateNextTokenId();
                    TokenData memory tokenData = TokenData({uri: newURI, maxSupply: maxSupply, totalMinted: 0});
                    tokens[tokenId] = tokenData;
                    emit UpdatedToken(msg.sender, tokenId, tokenData);
                }
                /// @notice Add a role to a user for a token
                /// @param tokenId The token ID to add the role to
                /// @param user The user to add the role to
                /// @param permissionBits The permission bit to add
                function addPermission(uint256 tokenId, address user, uint256 permissionBits) external onlyAdmin(tokenId) {
                    _addPermission(tokenId, user, permissionBits);
                }
                /// @notice Remove a role from a user for a token
                /// @param tokenId The token ID to remove the role from
                /// @param user The user to remove the role from
                /// @param permissionBits The permission bit to remove
                function removePermission(uint256 tokenId, address user, uint256 permissionBits) external onlyAdmin(tokenId) {
                    _removePermission(tokenId, user, permissionBits);
                    // Clear owner field
                    if (tokenId == CONTRACT_BASE_ID && user == config.owner && !_hasAnyPermission(CONTRACT_BASE_ID, user, PERMISSION_BIT_ADMIN)) {
                        _setOwner(address(0));
                    }
                }
                /// @notice Set the owner of the contract
                /// @param newOwner The new owner of the contract
                function setOwner(address newOwner) external onlyAdmin(CONTRACT_BASE_ID) {
                    if (!_hasAnyPermission(CONTRACT_BASE_ID, newOwner, PERMISSION_BIT_ADMIN)) {
                        revert NewOwnerNeedsToBeAdmin();
                    }
                    // Update owner field
                    _setOwner(newOwner);
                }
                /// @notice Getter for the owner singleton of the contract for outside interfaces
                /// @return the owner of the contract singleton for compat.
                function owner() external view returns (address) {
                    return config.owner;
                }
                /// @notice AdminMint that only checks if the requested quantity can be minted and has a re-entrant guard
                /// @param recipient recipient for admin minted tokens
                /// @param tokenId token id to mint
                /// @param quantity quantity to mint
                /// @param data callback data as specified by the 1155 spec
                function _adminMint(address recipient, uint256 tokenId, uint256 quantity, bytes memory data) internal {
                    _mint(recipient, tokenId, quantity, data);
                }
                /// @notice Mint a token to a user as the admin or minter
                /// @param recipient The recipient of the token
                /// @param tokenId The token ID to mint
                /// @param quantity The quantity of tokens to mint
                /// @param data The data to pass to the onERC1155Received function
                function adminMint(
                    address recipient,
                    uint256 tokenId,
                    uint256 quantity,
                    bytes memory data
                ) external nonReentrant onlyAdminOrRole(tokenId, PERMISSION_BIT_MINTER) {
                    // Call internal admin mint
                    _adminMint(recipient, tokenId, quantity, data);
                }
                /// @notice Batch mint tokens to a user as the admin or minter
                /// @param recipient The recipient of the tokens
                /// @param tokenIds The token IDs to mint
                /// @param quantities The quantities of tokens to mint
                /// @param data The data to pass to the onERC1155BatchReceived function
                function adminMintBatch(address recipient, uint256[] memory tokenIds, uint256[] memory quantities, bytes memory data) external nonReentrant {
                    bool isGlobalAdminOrMinter = _isAdminOrRole(msg.sender, CONTRACT_BASE_ID, PERMISSION_BIT_MINTER);
                    for (uint256 i = 0; i < tokenIds.length; ++i) {
                        if (!isGlobalAdminOrMinter) {
                            _requireAdminOrRole(msg.sender, tokenIds[i], PERMISSION_BIT_MINTER);
                        }
                    }
                    _mintBatch(recipient, tokenIds, quantities, data);
                }
                /// @notice Mint tokens given a minter contract and minter arguments
                /// @param minter The minter contract to use
                /// @param tokenId The token ID to mint
                /// @param quantity The quantity of tokens to mint
                /// @param minterArguments The arguments to pass to the minter
                function mint(IMinter1155 minter, uint256 tokenId, uint256 quantity, bytes calldata minterArguments) external payable nonReentrant {
                    // Require admin from the minter to mint
                    _requireAdminOrRole(address(minter), tokenId, PERMISSION_BIT_MINTER);
                    // Get value sent and handle mint fee
                    uint256 ethValueSent = _handleFeeAndGetValueSent(quantity);
                    // Execute commands returned from minter
                    _executeCommands(minter.requestMint(msg.sender, tokenId, quantity, ethValueSent, minterArguments).commands, ethValueSent, tokenId);
                    emit Purchased(msg.sender, address(minter), tokenId, quantity, msg.value);
                }
                /// @notice Set a metadata renderer for a token
                /// @param tokenId The token ID to set the renderer for
                /// @param renderer The renderer to set
                function setTokenMetadataRenderer(uint256 tokenId, IRenderer1155 renderer) external nonReentrant onlyAdminOrRole(tokenId, PERMISSION_BIT_METADATA) {
                    _setRenderer(tokenId, renderer);
                    if (tokenId == 0) {
                        emit ContractRendererUpdated(renderer);
                    } else {
                        // We don't know the uri from the renderer but can emit a notification to the indexer here
                        emit URI("", tokenId);
                    }
                }
                /// Execute Minter Commands ///
                /// @notice Internal functions to execute commands returned by the minter
                /// @param commands list of command structs
                /// @param ethValueSent the ethereum value sent in the mint transaction into the contract
                /// @param tokenId the token id the user requested to mint (0 if the token id is set by the minter itself across the whole contract)
                function _executeCommands(ICreatorCommands.Command[] memory commands, uint256 ethValueSent, uint256 tokenId) internal {
                    for (uint256 i = 0; i < commands.length; ++i) {
                        ICreatorCommands.CreatorActions method = commands[i].method;
                        if (method == ICreatorCommands.CreatorActions.SEND_ETH) {
                            (address recipient, uint256 amount) = abi.decode(commands[i].args, (address, uint256));
                            if (ethValueSent > amount) {
                                revert Mint_InsolventSaleTransfer();
                            }
                            if (!TransferHelperUtils.safeSendETH(recipient, amount, TransferHelperUtils.FUNDS_SEND_NORMAL_GAS_LIMIT)) {
                                revert Mint_ValueTransferFail();
                            }
                        } else if (method == ICreatorCommands.CreatorActions.MINT) {
                            (address recipient, uint256 mintTokenId, uint256 quantity) = abi.decode(commands[i].args, (address, uint256, uint256));
                            if (tokenId != 0 && mintTokenId != tokenId) {
                                revert Mint_TokenIDMintNotAllowed();
                            }
                            _mint(recipient, tokenId, quantity, "");
                        } else {
                            // no-op
                        }
                    }
                }
                /// @notice Token info getter
                /// @param tokenId token id to get info for
                /// @return TokenData struct returned
                function getTokenInfo(uint256 tokenId) external view returns (TokenData memory) {
                    return tokens[tokenId];
                }
                /// @notice Proxy setter for sale contracts (only callable by SALES permission or admin)
                /// @param tokenId The token ID to call the sale contract with
                /// @param salesConfig The sales config contract to call
                /// @param data The data to pass to the sales config contract
                function callSale(uint256 tokenId, IMinter1155 salesConfig, bytes memory data) external onlyAdminOrRole(tokenId, PERMISSION_BIT_SALES) {
                    _requireAdminOrRole(address(salesConfig), tokenId, PERMISSION_BIT_MINTER);
                    if (!salesConfig.supportsInterface(type(IMinter1155).interfaceId)) {
                        revert Sale_CannotCallNonSalesContract(address(salesConfig));
                    }
                    (bool success, bytes memory why) = address(salesConfig).call(data);
                    if (!success) {
                        revert CallFailed(why);
                    }
                }
                /// @notice Proxy setter for renderer contracts (only callable by METADATA permission or admin)
                /// @param tokenId The token ID to call the renderer contract with
                /// @param data The data to pass to the renderer contract
                function callRenderer(uint256 tokenId, bytes memory data) external onlyAdminOrRole(tokenId, PERMISSION_BIT_METADATA) {
                    // We assume any renderers set are checked for EIP165 signature during write stage.
                    (bool success, bytes memory why) = address(getCustomRenderer(tokenId)).call(data);
                    if (!success) {
                        revert CallFailed(why);
                    }
                }
                /// @notice Returns true if the contract implements the interface defined by interfaceId
                /// @param interfaceId The interface to check for
                /// @return if the interfaceId is marked as supported
                function supportsInterface(
                    bytes4 interfaceId
                ) public view virtual override(CreatorRoyaltiesControl, ERC1155Upgradeable, IERC165Upgradeable) returns (bool) {
                    return super.supportsInterface(interfaceId) || interfaceId == type(IZoraCreator1155).interfaceId || ERC1155Upgradeable.supportsInterface(interfaceId);
                }
                function _handleSupplyRoyalty(uint256 tokenId, uint256 mintAmount, bytes memory data) internal returns (uint256 totalRoyaltyMints) {
                    uint256 royaltyMintSchedule = royalties[tokenId].royaltyMintSchedule;
                    if (royaltyMintSchedule == 0) {
                        royaltyMintSchedule = royalties[CONTRACT_BASE_ID].royaltyMintSchedule;
                    }
                    if (royaltyMintSchedule == 0) {
                        // If we still have no schedule, return 0 supply royalty.
                        return 0;
                    }
                    totalRoyaltyMints = (mintAmount + (tokens[tokenId].totalMinted % royaltyMintSchedule)) / (royaltyMintSchedule - 1);
                    if (totalRoyaltyMints > 0) {
                        address royaltyRecipient = royalties[tokenId].royaltyRecipient;
                        if (royaltyRecipient == address(0)) {
                            royaltyRecipient = royalties[CONTRACT_BASE_ID].royaltyRecipient;
                        }
                        // If we have no recipient set, return 0 supply royalty.
                        if (royaltyRecipient == address(0)) {
                            return 0;
                        }
                        super._mint(royaltyRecipient, tokenId, totalRoyaltyMints, data);
                    }
                }
                /// Generic 1155 function overrides ///
                /// @notice Mint function that 1) checks quantity and 2) handles supply royalty 3) keeps track of allowed tokens
                /// @param to to mint to
                /// @param id token id to mint
                /// @param amount of tokens to mint
                /// @param data as specified by 1155 standard
                function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal virtual override {
                    uint256 supplyRoyaltyMints = _handleSupplyRoyalty(id, amount, data);
                    _requireCanMintQuantity(id, amount + supplyRoyaltyMints);
                    super._mint(to, id, amount, data);
                    tokens[id].totalMinted += amount + supplyRoyaltyMints;
                }
                /// @notice Mint batch function that 1) checks quantity and 2) handles supply royalty 3) keeps track of allowed tokens
                /// @param to to mint to
                /// @param ids token ids to mint
                /// @param amounts of tokens to mint
                /// @param data as specified by 1155 standard
                function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual override {
                    super._mintBatch(to, ids, amounts, data);
                    for (uint256 i = 0; i < ids.length; ++i) {
                        uint256 supplyRoyaltyMints = _handleSupplyRoyalty(ids[i], amounts[i], data);
                        _requireCanMintQuantity(ids[i], amounts[i] + supplyRoyaltyMints);
                        tokens[ids[i]].totalMinted += amounts[i] + supplyRoyaltyMints;
                    }
                }
                /// @notice Burns a batch of tokens
                /// @dev Only the current owner is allowed to burn
                /// @param from the user to burn from
                /// @param tokenIds The token ID to burn
                /// @param amounts The amount of tokens to burn
                function burnBatch(address from, uint256[] calldata tokenIds, uint256[] calldata amounts) external {
                    if (from != msg.sender && !isApprovedForAll(from, msg.sender)) {
                        revert Burn_NotOwnerOrApproved(msg.sender, from);
                    }
                    _burnBatch(from, tokenIds, amounts);
                }
                function setTransferHook(ITransferHookReceiver transferHook) external onlyAdmin(CONTRACT_BASE_ID) {
                    if (address(transferHook) != address(0)) {
                        if (!transferHook.supportsInterface(type(ITransferHookReceiver).interfaceId)) {
                            revert Config_TransferHookNotSupported(address(transferHook));
                        }
                    }
                    config.transferHook = transferHook;
                    emit ConfigUpdated(msg.sender, ConfigUpdate.TRANSFER_HOOK, config);
                }
                /// @notice Hook before token transfer that checks for a transfer hook integration
                /// @param operator operator moving the tokens
                /// @param from from address
                /// @param to to address
                /// @param ids token ids to move
                /// @param amounts amounts of tokens
                /// @param data data of tokens
                function _beforeTokenTransfer(
                    address operator,
                    address from,
                    address to,
                    uint256[] memory ids,
                    uint256[] memory amounts,
                    bytes memory data
                ) internal override {
                    super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
                    if (address(config.transferHook) != address(0)) {
                        config.transferHook.onTokenTransferBatch({target: address(this), operator: operator, from: from, to: to, ids: ids, amounts: amounts, data: data});
                    }
                }
                /// @notice Returns the URI for the contract
                function contractURI() external view returns (string memory) {
                    IRenderer1155 customRenderer = getCustomRenderer(CONTRACT_BASE_ID);
                    if (address(customRenderer) != address(0)) {
                        return customRenderer.contractURI();
                    }
                    return uri(0);
                }
                /// @notice Returns the URI for a token
                /// @param tokenId The token ID to return the URI for
                function uri(uint256 tokenId) public view override(ERC1155Upgradeable, IERC1155MetadataURIUpgradeable) returns (string memory) {
                    if (bytes(tokens[tokenId].uri).length > 0) {
                        return tokens[tokenId].uri;
                    }
                    return _render(tokenId);
                }
                /// @notice Internal setter for contract admin with no access checks
                /// @param newOwner new owner address
                function _setOwner(address newOwner) internal {
                    address lastOwner = config.owner;
                    config.owner = newOwner;
                    emit OwnershipTransferred(lastOwner, newOwner);
                    emit ConfigUpdated(msg.sender, ConfigUpdate.OWNER, config);
                }
                /// @notice Set funds recipient address
                /// @param fundsRecipient new funds recipient address
                function setFundsRecipient(address payable fundsRecipient) external onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_FUNDS_MANAGER) {
                    config.fundsRecipient = fundsRecipient;
                    emit ConfigUpdated(msg.sender, ConfigUpdate.FUNDS_RECIPIENT, config);
                }
                /// @notice Internal no-checks set funds recipient address
                /// @param fundsRecipient new funds recipient address
                function _setFundsRecipient(address payable fundsRecipient) internal {
                    config.fundsRecipient = fundsRecipient;
                    emit ConfigUpdated(msg.sender, ConfigUpdate.FUNDS_RECIPIENT, config);
                }
                /// @notice Withdraws all ETH from the contract to the funds recipient address
                function withdraw() public onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_FUNDS_MANAGER) {
                    uint256 contractValue = address(this).balance;
                    if (!TransferHelperUtils.safeSendETH(config.fundsRecipient, contractValue, TransferHelperUtils.FUNDS_SEND_NORMAL_GAS_LIMIT)) {
                        revert ETHWithdrawFailed(config.fundsRecipient, contractValue);
                    }
                }
                ///                                                          ///
                ///                         MANAGER UPGRADE                  ///
                ///                                                          ///
                /// @notice Ensures the caller is authorized to upgrade the contract
                /// @dev This function is called in `upgradeTo` & `upgradeToAndCall`
                /// @param _newImpl The new implementation address
                function _authorizeUpgrade(address _newImpl) internal view override onlyAdmin(CONTRACT_BASE_ID) {
                    if (!factory.isRegisteredUpgradePath(_getImplementation(), _newImpl)) {
                        revert();
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/ERC1155.sol)
            pragma solidity ^0.8.0;
            import "./IERC1155Upgradeable.sol";
            import "./IERC1155ReceiverUpgradeable.sol";
            import "./extensions/IERC1155MetadataURIUpgradeable.sol";
            import "../../utils/AddressUpgradeable.sol";
            import "../../utils/ContextUpgradeable.sol";
            import "../../utils/introspection/ERC165Upgradeable.sol";
            import "../../proxy/utils/Initializable.sol";
            /**
             * @dev Implementation of the basic standard multi-token.
             * See https://eips.ethereum.org/EIPS/eip-1155
             * Originally based on code by Enjin: https://github.com/enjin/erc-1155
             *
             * _Available since v3.1._
             */
            contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155Upgradeable, IERC1155MetadataURIUpgradeable {
                using AddressUpgradeable for address;
                // Mapping from token ID to account balances
                mapping(uint256 => mapping(address => uint256)) private _balances;
                // Mapping from account to operator approvals
                mapping(address => mapping(address => bool)) private _operatorApprovals;
                // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
                string private _uri;
                /**
                 * @dev See {_setURI}.
                 */
                function __ERC1155_init(string memory uri_) internal onlyInitializing {
                    __ERC1155_init_unchained(uri_);
                }
                function __ERC1155_init_unchained(string memory uri_) internal onlyInitializing {
                    _setURI(uri_);
                }
                /**
                 * @dev See {IERC165-supportsInterface}.
                 */
                function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {
                    return
                        interfaceId == type(IERC1155Upgradeable).interfaceId ||
                        interfaceId == type(IERC1155MetadataURIUpgradeable).interfaceId ||
                        super.supportsInterface(interfaceId);
                }
                /**
                 * @dev See {IERC1155MetadataURI-uri}.
                 *
                 * This implementation returns the same URI for *all* token types. It relies
                 * on the token type ID substitution mechanism
                 * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
                 *
                 * Clients calling this function must replace the `\\{id\\}` substring with the
                 * actual token type ID.
                 */
                function uri(uint256) public view virtual override returns (string memory) {
                    return _uri;
                }
                /**
                 * @dev See {IERC1155-balanceOf}.
                 *
                 * Requirements:
                 *
                 * - `account` cannot be the zero address.
                 */
                function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
                    require(account != address(0), "ERC1155: address zero is not a valid owner");
                    return _balances[id][account];
                }
                /**
                 * @dev See {IERC1155-balanceOfBatch}.
                 *
                 * Requirements:
                 *
                 * - `accounts` and `ids` must have the same length.
                 */
                function balanceOfBatch(address[] memory accounts, uint256[] memory ids)
                    public
                    view
                    virtual
                    override
                    returns (uint256[] memory)
                {
                    require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");
                    uint256[] memory batchBalances = new uint256[](accounts.length);
                    for (uint256 i = 0; i < accounts.length; ++i) {
                        batchBalances[i] = balanceOf(accounts[i], ids[i]);
                    }
                    return batchBalances;
                }
                /**
                 * @dev See {IERC1155-setApprovalForAll}.
                 */
                function setApprovalForAll(address operator, bool approved) public virtual override {
                    _setApprovalForAll(_msgSender(), operator, approved);
                }
                /**
                 * @dev See {IERC1155-isApprovedForAll}.
                 */
                function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
                    return _operatorApprovals[account][operator];
                }
                /**
                 * @dev See {IERC1155-safeTransferFrom}.
                 */
                function safeTransferFrom(
                    address from,
                    address to,
                    uint256 id,
                    uint256 amount,
                    bytes memory data
                ) public virtual override {
                    require(
                        from == _msgSender() || isApprovedForAll(from, _msgSender()),
                        "ERC1155: caller is not token owner or approved"
                    );
                    _safeTransferFrom(from, to, id, amount, data);
                }
                /**
                 * @dev See {IERC1155-safeBatchTransferFrom}.
                 */
                function safeBatchTransferFrom(
                    address from,
                    address to,
                    uint256[] memory ids,
                    uint256[] memory amounts,
                    bytes memory data
                ) public virtual override {
                    require(
                        from == _msgSender() || isApprovedForAll(from, _msgSender()),
                        "ERC1155: caller is not token owner or approved"
                    );
                    _safeBatchTransferFrom(from, to, ids, amounts, data);
                }
                /**
                 * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
                 *
                 * Emits a {TransferSingle} event.
                 *
                 * Requirements:
                 *
                 * - `to` cannot be the zero address.
                 * - `from` must have a balance of tokens of type `id` of at least `amount`.
                 * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
                 * acceptance magic value.
                 */
                function _safeTransferFrom(
                    address from,
                    address to,
                    uint256 id,
                    uint256 amount,
                    bytes memory data
                ) internal virtual {
                    require(to != address(0), "ERC1155: transfer to the zero address");
                    address operator = _msgSender();
                    uint256[] memory ids = _asSingletonArray(id);
                    uint256[] memory amounts = _asSingletonArray(amount);
                    _beforeTokenTransfer(operator, from, to, ids, amounts, data);
                    uint256 fromBalance = _balances[id][from];
                    require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
                    unchecked {
                        _balances[id][from] = fromBalance - amount;
                    }
                    _balances[id][to] += amount;
                    emit TransferSingle(operator, from, to, id, amount);
                    _afterTokenTransfer(operator, from, to, ids, amounts, data);
                    _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
                }
                /**
                 * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.
                 *
                 * Emits a {TransferBatch} event.
                 *
                 * Requirements:
                 *
                 * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
                 * acceptance magic value.
                 */
                function _safeBatchTransferFrom(
                    address from,
                    address to,
                    uint256[] memory ids,
                    uint256[] memory amounts,
                    bytes memory data
                ) internal virtual {
                    require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
                    require(to != address(0), "ERC1155: transfer to the zero address");
                    address operator = _msgSender();
                    _beforeTokenTransfer(operator, from, to, ids, amounts, data);
                    for (uint256 i = 0; i < ids.length; ++i) {
                        uint256 id = ids[i];
                        uint256 amount = amounts[i];
                        uint256 fromBalance = _balances[id][from];
                        require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
                        unchecked {
                            _balances[id][from] = fromBalance - amount;
                        }
                        _balances[id][to] += amount;
                    }
                    emit TransferBatch(operator, from, to, ids, amounts);
                    _afterTokenTransfer(operator, from, to, ids, amounts, data);
                    _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
                }
                /**
                 * @dev Sets a new URI for all token types, by relying on the token type ID
                 * substitution mechanism
                 * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
                 *
                 * By this mechanism, any occurrence of the `\\{id\\}` substring in either the
                 * URI or any of the amounts in the JSON file at said URI will be replaced by
                 * clients with the token type ID.
                 *
                 * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be
                 * interpreted by clients as
                 * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
                 * for token type ID 0x4cce0.
                 *
                 * See {uri}.
                 *
                 * Because these URIs cannot be meaningfully represented by the {URI} event,
                 * this function emits no events.
                 */
                function _setURI(string memory newuri) internal virtual {
                    _uri = newuri;
                }
                /**
                 * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.
                 *
                 * Emits a {TransferSingle} event.
                 *
                 * Requirements:
                 *
                 * - `to` cannot be the zero address.
                 * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
                 * acceptance magic value.
                 */
                function _mint(
                    address to,
                    uint256 id,
                    uint256 amount,
                    bytes memory data
                ) internal virtual {
                    require(to != address(0), "ERC1155: mint to the zero address");
                    address operator = _msgSender();
                    uint256[] memory ids = _asSingletonArray(id);
                    uint256[] memory amounts = _asSingletonArray(amount);
                    _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
                    _balances[id][to] += amount;
                    emit TransferSingle(operator, address(0), to, id, amount);
                    _afterTokenTransfer(operator, address(0), to, ids, amounts, data);
                    _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);
                }
                /**
                 * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
                 *
                 * Emits a {TransferBatch} event.
                 *
                 * Requirements:
                 *
                 * - `ids` and `amounts` must have the same length.
                 * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
                 * acceptance magic value.
                 */
                function _mintBatch(
                    address to,
                    uint256[] memory ids,
                    uint256[] memory amounts,
                    bytes memory data
                ) internal virtual {
                    require(to != address(0), "ERC1155: mint to the zero address");
                    require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
                    address operator = _msgSender();
                    _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
                    for (uint256 i = 0; i < ids.length; i++) {
                        _balances[ids[i]][to] += amounts[i];
                    }
                    emit TransferBatch(operator, address(0), to, ids, amounts);
                    _afterTokenTransfer(operator, address(0), to, ids, amounts, data);
                    _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
                }
                /**
                 * @dev Destroys `amount` tokens of token type `id` from `from`
                 *
                 * Emits a {TransferSingle} event.
                 *
                 * Requirements:
                 *
                 * - `from` cannot be the zero address.
                 * - `from` must have at least `amount` tokens of token type `id`.
                 */
                function _burn(
                    address from,
                    uint256 id,
                    uint256 amount
                ) internal virtual {
                    require(from != address(0), "ERC1155: burn from the zero address");
                    address operator = _msgSender();
                    uint256[] memory ids = _asSingletonArray(id);
                    uint256[] memory amounts = _asSingletonArray(amount);
                    _beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
                    uint256 fromBalance = _balances[id][from];
                    require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
                    unchecked {
                        _balances[id][from] = fromBalance - amount;
                    }
                    emit TransferSingle(operator, from, address(0), id, amount);
                    _afterTokenTransfer(operator, from, address(0), ids, amounts, "");
                }
                /**
                 * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
                 *
                 * Emits a {TransferBatch} event.
                 *
                 * Requirements:
                 *
                 * - `ids` and `amounts` must have the same length.
                 */
                function _burnBatch(
                    address from,
                    uint256[] memory ids,
                    uint256[] memory amounts
                ) internal virtual {
                    require(from != address(0), "ERC1155: burn from the zero address");
                    require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
                    address operator = _msgSender();
                    _beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
                    for (uint256 i = 0; i < ids.length; i++) {
                        uint256 id = ids[i];
                        uint256 amount = amounts[i];
                        uint256 fromBalance = _balances[id][from];
                        require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
                        unchecked {
                            _balances[id][from] = fromBalance - amount;
                        }
                    }
                    emit TransferBatch(operator, from, address(0), ids, amounts);
                    _afterTokenTransfer(operator, from, address(0), ids, amounts, "");
                }
                /**
                 * @dev Approve `operator` to operate on all of `owner` tokens
                 *
                 * Emits an {ApprovalForAll} event.
                 */
                function _setApprovalForAll(
                    address owner,
                    address operator,
                    bool approved
                ) internal virtual {
                    require(owner != operator, "ERC1155: setting approval status for self");
                    _operatorApprovals[owner][operator] = approved;
                    emit ApprovalForAll(owner, operator, approved);
                }
                /**
                 * @dev Hook that is called before any token transfer. This includes minting
                 * and burning, as well as batched variants.
                 *
                 * The same hook is called on both single and batched variants. For single
                 * transfers, the length of the `ids` and `amounts` arrays will be 1.
                 *
                 * Calling conditions (for each `id` and `amount` pair):
                 *
                 * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
                 * of token type `id` will be  transferred to `to`.
                 * - When `from` is zero, `amount` tokens of token type `id` will be minted
                 * for `to`.
                 * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
                 * will be burned.
                 * - `from` and `to` are never both zero.
                 * - `ids` and `amounts` have the same, non-zero length.
                 *
                 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
                 */
                function _beforeTokenTransfer(
                    address operator,
                    address from,
                    address to,
                    uint256[] memory ids,
                    uint256[] memory amounts,
                    bytes memory data
                ) internal virtual {}
                /**
                 * @dev Hook that is called after any token transfer. This includes minting
                 * and burning, as well as batched variants.
                 *
                 * The same hook is called on both single and batched variants. For single
                 * transfers, the length of the `id` and `amount` arrays will be 1.
                 *
                 * Calling conditions (for each `id` and `amount` pair):
                 *
                 * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
                 * of token type `id` will be  transferred to `to`.
                 * - When `from` is zero, `amount` tokens of token type `id` will be minted
                 * for `to`.
                 * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
                 * will be burned.
                 * - `from` and `to` are never both zero.
                 * - `ids` and `amounts` have the same, non-zero length.
                 *
                 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
                 */
                function _afterTokenTransfer(
                    address operator,
                    address from,
                    address to,
                    uint256[] memory ids,
                    uint256[] memory amounts,
                    bytes memory data
                ) internal virtual {}
                function _doSafeTransferAcceptanceCheck(
                    address operator,
                    address from,
                    address to,
                    uint256 id,
                    uint256 amount,
                    bytes memory data
                ) private {
                    if (to.isContract()) {
                        try IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
                            if (response != IERC1155ReceiverUpgradeable.onERC1155Received.selector) {
                                revert("ERC1155: ERC1155Receiver rejected tokens");
                            }
                        } catch Error(string memory reason) {
                            revert(reason);
                        } catch {
                            revert("ERC1155: transfer to non-ERC1155Receiver implementer");
                        }
                    }
                }
                function _doSafeBatchTransferAcceptanceCheck(
                    address operator,
                    address from,
                    address to,
                    uint256[] memory ids,
                    uint256[] memory amounts,
                    bytes memory data
                ) private {
                    if (to.isContract()) {
                        try IERC1155ReceiverUpgradeable(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
                            bytes4 response
                        ) {
                            if (response != IERC1155ReceiverUpgradeable.onERC1155BatchReceived.selector) {
                                revert("ERC1155: ERC1155Receiver rejected tokens");
                            }
                        } catch Error(string memory reason) {
                            revert(reason);
                        } catch {
                            revert("ERC1155: transfer to non-ERC1155Receiver implementer");
                        }
                    }
                }
                function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
                    uint256[] memory array = new uint256[](1);
                    array[0] = element;
                    return array;
                }
                /**
                 * @dev This empty reserved space is put in place to allow future versions to add new
                 * variables without shifting down storage in the inheritance chain.
                 * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
                 */
                uint256[47] private __gap;
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1155MetadataURI.sol)
            pragma solidity ^0.8.0;
            import "../token/ERC1155/extensions/IERC1155MetadataURIUpgradeable.sol";
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol)
            pragma solidity ^0.8.0;
            import "../utils/introspection/IERC165Upgradeable.sol";
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
            import {IERC1155MetadataURIUpgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC1155MetadataURIUpgradeable.sol";
            import {IZoraCreator1155TypesV1} from "../nft/IZoraCreator1155TypesV1.sol";
            import {IRenderer1155} from "../interfaces/IRenderer1155.sol";
            import {IMinter1155} from "../interfaces/IMinter1155.sol";
            import {IOwnable} from "../interfaces/IOwnable.sol";
            import {IVersionedContract} from "./IVersionedContract.sol";
            import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol";
            /*
                         ░░░░░░░░░░░░░░              
                    ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                  ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
               ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
              ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
              ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
               ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                  ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                      ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                           OURS TRULY,
             */
            /// @notice Main interface for the ZoraCreator1155 contract
            /// @author @iainnash / @tbtstl
            interface IZoraCreator1155 is IZoraCreator1155TypesV1, IVersionedContract, IOwnable, IERC1155MetadataURIUpgradeable {
                function PERMISSION_BIT_ADMIN() external returns (uint256);
                function PERMISSION_BIT_MINTER() external returns (uint256);
                function PERMISSION_BIT_SALES() external returns (uint256);
                function PERMISSION_BIT_METADATA() external returns (uint256);
                /// @notice Used to label the configuration update type
                enum ConfigUpdate {
                    OWNER,
                    FUNDS_RECIPIENT,
                    TRANSFER_HOOK
                }
                event ConfigUpdated(address indexed updater, ConfigUpdate indexed updateType, ContractConfig newConfig);
                event UpdatedToken(address indexed from, uint256 indexed tokenId, TokenData tokenData);
                event SetupNewToken(uint256 indexed tokenId, address indexed sender, string newURI, uint256 maxSupply);
                function setOwner(address newOwner) external;
                event ContractRendererUpdated(IRenderer1155 renderer);
                event ContractMetadataUpdated(address indexed updater, string uri, string name);
                event Purchased(address indexed sender, address indexed minter, uint256 indexed tokenId, uint256 quantity, uint256 value);
                error TokenIdMismatch(uint256 expected, uint256 actual);
                error UserMissingRoleForToken(address user, uint256 tokenId, uint256 role);
                error Config_TransferHookNotSupported(address proposedAddress);
                error Mint_InsolventSaleTransfer();
                error Mint_ValueTransferFail();
                error Mint_TokenIDMintNotAllowed();
                error Mint_UnknownCommand();
                error Burn_NotOwnerOrApproved(address operator, address user);
                error NewOwnerNeedsToBeAdmin();
                error Sale_CannotCallNonSalesContract(address targetContract);
                error CallFailed(bytes reason);
                error Renderer_NotValidRendererContract();
                error ETHWithdrawFailed(address recipient, uint256 amount);
                error FundsWithdrawInsolvent(uint256 amount, uint256 contractValue);
                error CannotMintMoreTokens(uint256 tokenId, uint256 quantity, uint256 totalMinted, uint256 maxSupply);
                /// @notice Only allow minting one token id at time
                /// @dev Mint contract function that calls the underlying sales function for commands
                /// @param minter Address for the minter
                /// @param tokenId tokenId to mint, set to 0 for new tokenId
                /// @param quantity to mint
                /// @param minterArguments calldata for the minter contracts
                function mint(IMinter1155 minter, uint256 tokenId, uint256 quantity, bytes calldata minterArguments) external payable;
                function adminMint(address recipient, uint256 tokenId, uint256 quantity, bytes memory data) external;
                function adminMintBatch(address recipient, uint256[] memory tokenIds, uint256[] memory quantities, bytes memory data) external;
                function burnBatch(address user, uint256[] calldata tokenIds, uint256[] calldata amounts) external;
                /// @notice Contract call to setupNewToken
                /// @param tokenURI URI for the token
                /// @param maxSupply maxSupply for the token, set to 0 for open edition
                function setupNewToken(string memory tokenURI, uint256 maxSupply) external returns (uint256 tokenId);
                function updateTokenURI(uint256 tokenId, string memory _newURI) external;
                function updateContractMetadata(string memory _newURI, string memory _newName) external;
                // Public interface for `setTokenMetadataRenderer(uint256, address) has been deprecated.
                function contractURI() external view returns (string memory);
                function assumeLastTokenIdMatches(uint256 tokenId) external;
                function updateRoyaltiesForToken(uint256 tokenId, ICreatorRoyaltiesControl.RoyaltyConfiguration memory royaltyConfiguration) external;
                function addPermission(uint256 tokenId, address user, uint256 permissionBits) external;
                function removePermission(uint256 tokenId, address user, uint256 permissionBits) external;
                function isAdminOrRole(address user, uint256 tokenId, uint256 role) external view returns (bool);
                function getTokenInfo(uint256 tokenId) external view returns (TokenData memory);
                function callRenderer(uint256 tokenId, bytes memory data) external;
                function callSale(uint256 tokenId, IMinter1155 salesConfig, bytes memory data) external;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol";
            interface IZoraCreator1155Initializer {
                function initialize(
                    string memory contractName,
                    string memory newContractURI,
                    ICreatorRoyaltiesControl.RoyaltyConfiguration memory defaultRoyaltyConfiguration,
                    address payable defaultAdmin,
                    bytes[] calldata setupActions
                ) external;
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
            pragma solidity ^0.8.0;
            import "../proxy/utils/Initializable.sol";
            /**
             * @dev Contract module that helps prevent reentrant calls to a function.
             *
             * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
             * available, which can be applied to functions to make sure there are no nested
             * (reentrant) calls to them.
             *
             * Note that because there is a single `nonReentrant` guard, functions marked as
             * `nonReentrant` may not call one another. This can be worked around by making
             * those functions `private`, and then adding `external` `nonReentrant` entry
             * points to them.
             *
             * TIP: If you would like to learn more about reentrancy and alternative ways
             * to protect against it, check out our blog post
             * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
             */
            abstract contract ReentrancyGuardUpgradeable is Initializable {
                // Booleans are more expensive than uint256 or any type that takes up a full
                // word because each write operation emits an extra SLOAD to first read the
                // slot's contents, replace the bits taken up by the boolean, and then write
                // back. This is the compiler's defense against contract upgrades and
                // pointer aliasing, and it cannot be disabled.
                // The values being non-zero value makes deployment a bit more expensive,
                // but in exchange the refund on every call to nonReentrant will be lower in
                // amount. Since refunds are capped to a percentage of the total
                // transaction's gas, it is best to keep them low in cases like this one, to
                // increase the likelihood of the full refund coming into effect.
                uint256 private constant _NOT_ENTERED = 1;
                uint256 private constant _ENTERED = 2;
                uint256 private _status;
                function __ReentrancyGuard_init() internal onlyInitializing {
                    __ReentrancyGuard_init_unchained();
                }
                function __ReentrancyGuard_init_unchained() internal onlyInitializing {
                    _status = _NOT_ENTERED;
                }
                /**
                 * @dev Prevents a contract from calling itself, directly or indirectly.
                 * Calling a `nonReentrant` function from another `nonReentrant`
                 * function is not supported. It is possible to prevent this from happening
                 * by making the `nonReentrant` function external, and making it call a
                 * `private` function that does the actual work.
                 */
                modifier nonReentrant() {
                    _nonReentrantBefore();
                    _;
                    _nonReentrantAfter();
                }
                function _nonReentrantBefore() private {
                    // On the first call to nonReentrant, _status will be _NOT_ENTERED
                    require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
                    // Any calls to nonReentrant after this point will fail
                    _status = _ENTERED;
                }
                function _nonReentrantAfter() private {
                    // By storing the original value once again, a refund is triggered (see
                    // https://eips.ethereum.org/EIPS/eip-2200)
                    _status = _NOT_ENTERED;
                }
                /**
                 * @dev This empty reserved space is put in place to allow future versions to add new
                 * variables without shifting down storage in the inheritance chain.
                 * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
                 */
                uint256[49] private __gap;
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol)
            pragma solidity ^0.8.0;
            import "../../interfaces/draft-IERC1822Upgradeable.sol";
            import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
            import "./Initializable.sol";
            /**
             * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
             * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
             *
             * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
             * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
             * `UUPSUpgradeable` with a custom implementation of upgrades.
             *
             * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
             *
             * _Available since v4.1._
             */
            abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
                function __UUPSUpgradeable_init() internal onlyInitializing {
                }
                function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
                }
                /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
                address private immutable __self = address(this);
                /**
                 * @dev Check that the execution is being performed through a delegatecall call and that the execution context is
                 * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
                 * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
                 * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
                 * fail.
                 */
                modifier onlyProxy() {
                    require(address(this) != __self, "Function must be called through delegatecall");
                    require(_getImplementation() == __self, "Function must be called through active proxy");
                    _;
                }
                /**
                 * @dev Check that the execution is not being performed through a delegate call. This allows a function to be
                 * callable on the implementing contract but not through proxies.
                 */
                modifier notDelegated() {
                    require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
                    _;
                }
                /**
                 * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
                 * implementation. It is used to validate the implementation's compatibility when performing an upgrade.
                 *
                 * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
                 * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
                 * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
                 */
                function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
                    return _IMPLEMENTATION_SLOT;
                }
                /**
                 * @dev Upgrade the implementation of the proxy to `newImplementation`.
                 *
                 * Calls {_authorizeUpgrade}.
                 *
                 * Emits an {Upgraded} event.
                 */
                function upgradeTo(address newImplementation) external virtual onlyProxy {
                    _authorizeUpgrade(newImplementation);
                    _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
                }
                /**
                 * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
                 * encoded in `data`.
                 *
                 * Calls {_authorizeUpgrade}.
                 *
                 * Emits an {Upgraded} event.
                 */
                function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {
                    _authorizeUpgrade(newImplementation);
                    _upgradeToAndCallUUPS(newImplementation, data, true);
                }
                /**
                 * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
                 * {upgradeTo} and {upgradeToAndCall}.
                 *
                 * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
                 *
                 * ```solidity
                 * function _authorizeUpgrade(address) internal override onlyOwner {}
                 * ```
                 */
                function _authorizeUpgrade(address newImplementation) internal virtual;
                /**
                 * @dev This empty reserved space is put in place to allow future versions to add new
                 * variables without shifting down storage in the inheritance chain.
                 * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
                 */
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IVersionedContract} from "../interfaces/IVersionedContract.sol";
            /// @title ContractVersionBase
            /// @notice Base contract for versioning contracts
            contract ContractVersionBase is IVersionedContract {
                /// @notice The version of the contract
                function contractVersion() external pure override returns (string memory) {
                    return "1.3.0";
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {CreatorPermissionStorageV1} from "./CreatorPermissionStorageV1.sol";
            import {ICreatorPermissionControl} from "../interfaces/ICreatorPermissionControl.sol";
            /// Imagine. Mint. Enjoy.
            /// @author @iainnash / @tbtstl
            contract CreatorPermissionControl is CreatorPermissionStorageV1, ICreatorPermissionControl {
                /// @notice Check if the user has the given permissions
                /// @dev if multiple permissions are passed in this checks for all the permissions requested
                /// @return true or false if all of the passed in permissions apply
                function _hasPermissions(uint256 tokenId, address user, uint256 permissionBits) internal view returns (bool) {
                    // Does a bitwise and and checks if any of those permissions match
                    return permissions[tokenId][user] & permissionBits == permissionBits;
                }
                /// @notice Check if the user has any of the given permissions
                /// @dev if multiple permissions are passed in this checks for any one of those permissions
                /// @return true or false if any of the passed in permissions apply
                function _hasAnyPermission(uint256 tokenId, address user, uint256 permissionBits) internal view returns (bool) {
                    // Does a bitwise and and checks if any of those permissions match
                    return permissions[tokenId][user] & permissionBits > 0;
                }
                /// @return raw permission bits for the given user
                function getPermissions(uint256 tokenId, address user) external view returns (uint256) {
                    return permissions[tokenId][user];
                }
                /// @notice addPermission – internal function to add a set of permission bits to a user
                /// @param tokenId token id to add the permission to (0 indicates contract-wide add)
                /// @param user user to update permissions for
                /// @param permissionBits bits to add permissions to
                function _addPermission(uint256 tokenId, address user, uint256 permissionBits) internal {
                    uint256 tokenPermissions = permissions[tokenId][user];
                    tokenPermissions |= permissionBits;
                    permissions[tokenId][user] = tokenPermissions;
                    emit UpdatedPermissions(tokenId, user, tokenPermissions);
                }
                /// @notice _clearPermission clear permissions for user
                /// @param tokenId token id to clear permission from (0 indicates contract-wide action)
                function _clearPermissions(uint256 tokenId, address user) internal {
                    permissions[tokenId][user] = 0;
                    emit UpdatedPermissions(tokenId, user, 0);
                }
                /// @notice _removePermission removes permissions for user
                /// @param tokenId token id to clear permission from (0 indicates contract-wide action)
                /// @param user user to manage permissions for
                /// @param permissionBits set of permission bits to remove
                function _removePermission(uint256 tokenId, address user, uint256 permissionBits) internal {
                    uint256 tokenPermissions = permissions[tokenId][user];
                    tokenPermissions &= ~permissionBits;
                    permissions[tokenId][user] = tokenPermissions;
                    emit UpdatedPermissions(tokenId, user, tokenPermissions);
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {CreatorRendererStorageV1} from "./CreatorRendererStorageV1.sol";
            import {IRenderer1155} from "../interfaces/IRenderer1155.sol";
            import {ITransferHookReceiver} from "../interfaces/ITransferHookReceiver.sol";
            import {SharedBaseConstants} from "../shared/SharedBaseConstants.sol";
            /// @title CreatorRendererControl
            /// @notice Contract for managing the renderer of an 1155 contract
            abstract contract CreatorRendererControl is CreatorRendererStorageV1, SharedBaseConstants {
                function _setRenderer(uint256 tokenId, IRenderer1155 renderer) internal {
                    customRenderers[tokenId] = renderer;
                    if (address(renderer) != address(0)) {
                        if (!renderer.supportsInterface(type(IRenderer1155).interfaceId)) {
                            revert RendererNotValid(address(renderer));
                        }
                    }
                    emit RendererUpdated({tokenId: tokenId, renderer: address(renderer), user: msg.sender});
                }
                /// @notice Return the renderer for a given token
                /// @dev Returns address 0 for no results
                /// @param tokenId The token to get the renderer for
                function getCustomRenderer(uint256 tokenId) public view returns (IRenderer1155 customRenderer) {
                    customRenderer = customRenderers[tokenId];
                    if (address(customRenderer) == address(0)) {
                        customRenderer = customRenderers[CONTRACT_BASE_ID];
                    }
                }
                /// @notice Function called to render when an empty tokenURI exists on the contract
                function _render(uint256 tokenId) internal view returns (string memory) {
                    return getCustomRenderer(tokenId).uri(tokenId);
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {CreatorRoyaltiesStorageV1} from "./CreatorRoyaltiesStorageV1.sol";
            import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol";
            import {SharedBaseConstants} from "../shared/SharedBaseConstants.sol";
            import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol";
            /// Imagine. Mint. Enjoy.
            /// @title CreatorRoyaltiesControl
            /// @author ZORA @iainnash / @tbtstl
            /// @notice Contract for managing the royalties of an 1155 contract
            abstract contract CreatorRoyaltiesControl is CreatorRoyaltiesStorageV1, SharedBaseConstants {
                uint256 immutable ROYALTY_BPS_TO_PERCENT = 10_000;
                /// @notice The royalty information for a given token.
                /// @param tokenId The token ID to get the royalty information for.
                function getRoyalties(uint256 tokenId) public view returns (RoyaltyConfiguration memory) {
                    if (royalties[tokenId].royaltyRecipient != address(0)) {
                        return royalties[tokenId];
                    }
                    // Otherwise, return default.
                    return royalties[CONTRACT_BASE_ID];
                }
                /// @notice Returns the royalty information for a given token.
                /// @param tokenId The token ID to get the royalty information for.
                /// @param salePrice The sale price of the NFT asset specified by tokenId
                function royaltyInfo(uint256 tokenId, uint256 salePrice) public view returns (address receiver, uint256 royaltyAmount) {
                    RoyaltyConfiguration memory config = getRoyalties(tokenId);
                    royaltyAmount = (config.royaltyBPS * salePrice) / ROYALTY_BPS_TO_PERCENT;
                    receiver = config.royaltyRecipient;
                }
                /// @notice Returns the supply royalty information for a given token.
                /// @param tokenId The token ID to get the royalty information for.
                /// @param mintAmount The amount of tokens being minted.
                /// @param totalSupply The total supply of the token,
                function supplyRoyaltyInfo(uint256 tokenId, uint256 totalSupply, uint256 mintAmount) public view returns (address receiver, uint256 royaltyAmount) {
                    RoyaltyConfiguration memory config = getRoyalties(tokenId);
                    if (config.royaltyMintSchedule == 0) {
                        return (config.royaltyRecipient, 0);
                    }
                    uint256 totalRoyaltyMints = (mintAmount + (totalSupply % config.royaltyMintSchedule)) / (config.royaltyMintSchedule - 1);
                    return (config.royaltyRecipient, totalRoyaltyMints);
                }
                function _updateRoyalties(uint256 tokenId, RoyaltyConfiguration memory configuration) internal {
                    // Don't allow 100% supply royalties
                    if (configuration.royaltyMintSchedule == 1) {
                        revert InvalidMintSchedule();
                    }
                    // Don't allow setting royalties to burn address
                    if (configuration.royaltyRecipient == address(0) && (configuration.royaltyMintSchedule > 0 || configuration.royaltyBPS > 0)) {
                        revert InvalidMintSchedule();
                    }
                    royalties[tokenId] = configuration;
                    emit UpdatedRoyalties(tokenId, msg.sender, configuration);
                }
                function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
                    return interfaceId == type(IERC2981).interfaceId;
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            /// @notice Creator Commands used by minter modules passed back to the main modules
            interface ICreatorCommands {
                /// @notice This enum is used to define supported creator action types.
                /// This can change in the future
                enum CreatorActions {
                    // No operation - also the default for mintings that may not return a command
                    NO_OP,
                    // Send ether
                    SEND_ETH,
                    // Mint operation
                    MINT
                }
                /// @notice This command is for
                struct Command {
                    // Method for operation
                    CreatorActions method;
                    // Arguments used for this operation
                    bytes args;
                }
                /// @notice This command set is returned from the minter back to the user
                struct CommandSet {
                    Command[] commands;
                    uint256 at;
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
            import {ICreatorCommands} from "./ICreatorCommands.sol";
            /// @notice Minter standard interface
            /// @dev Minters need to confirm to the ERC165 selector of type(IMinter1155).interfaceId
            interface IMinter1155 is IERC165Upgradeable {
                function requestMint(
                    address sender,
                    uint256 tokenId,
                    uint256 quantity,
                    uint256 ethValueSent,
                    bytes calldata minterArguments
                ) external returns (ICreatorCommands.CommandSet memory commands);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
            /// @dev IERC165 type required
            interface IRenderer1155 is IERC165Upgradeable {
                /// @notice Called for assigned tokenId, or when token id is globally set to a renderer
                /// @dev contract target is assumed to be msg.sender
                /// @param tokenId token id to get uri for
                function uri(uint256 tokenId) external view returns (string memory);
                /// @notice Only called for tokenId == 0
                /// @dev contract target is assumed to be msg.sender
                function contractURI() external view returns (string memory);
                /// @notice Sets up renderer from contract
                /// @param initData data to setup renderer with
                /// @dev contract target is assumed to be msg.sender
                function setup(bytes memory initData) external;
                // IERC165 type required – set in base helper
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
            interface ITransferHookReceiver is IERC165Upgradeable {
                /// @notice Token transfer batch callback
                /// @param target target contract for transfer
                /// @param operator operator address for transfer
                /// @param from user address for amount transferred
                /// @param to user address for amount transferred
                /// @param ids list of token ids transferred
                /// @param amounts list of values transferred
                /// @param data data as perscribed by 1155 standard
                function onTokenTransferBatch(
                    address target,
                    address operator,
                    address from,
                    address to,
                    uint256[] memory ids,
                    uint256[] memory amounts,
                    bytes memory data
                ) external;
                // IERC165 type required
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            /// @notice Factory Upgrade Gate Admin Factory Implementation – Allows specific contract upgrades as a safety measure
            interface IFactoryManagedUpgradeGate {
                /// @notice If an implementation is registered by the Builder DAO as an optional upgrade
                /// @param baseImpl The base implementation address
                /// @param upgradeImpl The upgrade implementation address
                function isRegisteredUpgradePath(address baseImpl, address upgradeImpl) external view returns (bool);
                /// @notice Called by the Builder DAO to offer implementation upgrades for created DAOs
                /// @param baseImpls The base implementation addresses
                /// @param upgradeImpl The upgrade implementation address
                function registerUpgradePath(address[] memory baseImpls, address upgradeImpl) external;
                /// @notice Called by the Builder DAO to remove an upgrade
                /// @param baseImpl The base implementation address
                /// @param upgradeImpl The upgrade implementation address
                function removeUpgradePath(address baseImpl, address upgradeImpl) external;
                event UpgradeRegistered(address indexed baseImpl, address indexed upgradeImpl);
                event UpgradeRemoved(address indexed baseImpl, address indexed upgradeImpl);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {ILegacyNaming} from "../interfaces/ILegacyNaming.sol";
            import {LegacyNamingStorageV1} from "./LegacyNamingStorageV1.sol";
            /// @title LegacyNamingControl
            /// @notice Contract for managing the name and symbol of an 1155 contract in the legacy naming scheme
            contract LegacyNamingControl is LegacyNamingStorageV1, ILegacyNaming {
                /// @notice The name of the contract
                function name() external view returns (string memory) {
                    return _name;
                }
                /// @notice The token symbol of the contract
                function symbol() external pure returns (string memory) {}
                function _setName(string memory _newName) internal {
                    _name = _newName;
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {TransferHelperUtils} from "../utils/TransferHelperUtils.sol";
            import {IMintFeeManager} from "../interfaces/IMintFeeManager.sol";
            /// @title MintFeeManager
            /// @notice Manages mint fees for an 1155 contract
            contract MintFeeManager is IMintFeeManager {
                uint256 public immutable mintFee;
                address public immutable mintFeeRecipient;
                constructor(uint256 _mintFee, address _mintFeeRecipient) {
                    // Set fixed finders fee
                    if (_mintFee >= 0.1 ether) {
                        revert MintFeeCannotBeMoreThanZeroPointOneETH(_mintFee);
                    }
                    if (_mintFeeRecipient == address(0) && _mintFee > 0) {
                        revert CannotSetMintFeeToZeroAddress();
                    }
                    mintFeeRecipient = _mintFeeRecipient;
                    mintFee = _mintFee;
                }
                /// @notice Sends the mint fee to the mint fee recipient and returns the amount of ETH remaining that can be used in this transaction
                /// @param _quantity The amount of toknens being minted
                function _handleFeeAndGetValueSent(uint256 _quantity) internal returns (uint256 ethValueSent) {
                    ethValueSent = msg.value;
                    // Handle mint fee
                    if (mintFeeRecipient != address(0)) {
                        uint256 totalFee = mintFee * _quantity;
                        ethValueSent -= totalFee;
                        if (!TransferHelperUtils.safeSendETH(mintFeeRecipient, totalFee, TransferHelperUtils.FUNDS_SEND_LOW_GAS_LIMIT)) {
                            revert CannotSendMintFee(mintFeeRecipient, totalFee);
                        }
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.17;
            import "@openzeppelin/contracts/utils/Address.sol";
            /// @title PublicMulticall
            /// @notice Contract for executing a batch of function calls on this contract
            abstract contract PublicMulticall {
                /**
                 * @notice Receives and executes a batch of function calls on this contract.
                 */
                function multicall(bytes[] calldata data) public virtual returns (bytes[] memory results) {
                    results = new bytes[](data.length);
                    for (uint256 i = 0; i < data.length; i++) {
                        results[i] = Address.functionDelegateCall(address(this), data[i]);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            contract SharedBaseConstants {
                uint256 public constant CONTRACT_BASE_ID = 0;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            /// @title TransferHelperUtils
            /// @notice Helper functions for sending ETH
            library TransferHelperUtils {
                /// @dev Gas limit to send funds
                uint256 internal constant FUNDS_SEND_LOW_GAS_LIMIT = 110_000;
                // @dev Gas limit to send funds – usable for splits, can use with withdraws
                uint256 internal constant FUNDS_SEND_NORMAL_GAS_LIMIT = 310_000;
                /// @notice Sends ETH to a recipient, making conservative estimates to not run out of gas
                /// @param recipient The address to send ETH to
                /// @param value The amount of ETH to send
                function safeSendETH(address recipient, uint256 value, uint256 gasLimit) internal returns (bool success) {
                    (success, ) = recipient.call{value: value, gas: gasLimit}("");
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IZoraCreator1155TypesV1} from "./IZoraCreator1155TypesV1.sol";
            /*
                         ░░░░░░░░░░░░░░              
                    ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                  ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
               ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
              ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
              ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
               ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                  ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                      ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                           OURS TRULY,
                github.com/ourzora/zora-1155-contracts
             */
            /// Imagine. Mint. Enjoy.
            /// @notice Storage for 1155 contract
            /// @author @iainnash / @tbtstl
            contract ZoraCreator1155StorageV1 is IZoraCreator1155TypesV1 {
                /// @notice token data stored for each token
                mapping(uint256 => TokenData) internal tokens;
                /// @notice metadata renderer contract for each token
                mapping(uint256 => address) public metadataRendererContract;
                /// @notice next token id available when using a linear mint style (default for launch)
                uint256 public nextTokenId;
                /// @notice Global contract configuration
                ContractConfig public config;
                /**
                 * @dev This empty reserved space is put in place to allow future versions to add new
                 * variables without shifting down storage in the inheritance chain.
                 * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
                 */
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)
            pragma solidity ^0.8.0;
            import "../../utils/introspection/IERC165Upgradeable.sol";
            /**
             * @dev Required interface of an ERC1155 compliant contract, as defined in the
             * https://eips.ethereum.org/EIPS/eip-1155[EIP].
             *
             * _Available since v3.1._
             */
            interface IERC1155Upgradeable is IERC165Upgradeable {
                /**
                 * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
                 */
                event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
                /**
                 * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
                 * transfers.
                 */
                event TransferBatch(
                    address indexed operator,
                    address indexed from,
                    address indexed to,
                    uint256[] ids,
                    uint256[] values
                );
                /**
                 * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
                 * `approved`.
                 */
                event ApprovalForAll(address indexed account, address indexed operator, bool approved);
                /**
                 * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
                 *
                 * If an {URI} event was emitted for `id`, the standard
                 * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
                 * returned by {IERC1155MetadataURI-uri}.
                 */
                event URI(string value, uint256 indexed id);
                /**
                 * @dev Returns the amount of tokens of token type `id` owned by `account`.
                 *
                 * Requirements:
                 *
                 * - `account` cannot be the zero address.
                 */
                function balanceOf(address account, uint256 id) external view returns (uint256);
                /**
                 * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
                 *
                 * Requirements:
                 *
                 * - `accounts` and `ids` must have the same length.
                 */
                function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
                    external
                    view
                    returns (uint256[] memory);
                /**
                 * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
                 *
                 * Emits an {ApprovalForAll} event.
                 *
                 * Requirements:
                 *
                 * - `operator` cannot be the caller.
                 */
                function setApprovalForAll(address operator, bool approved) external;
                /**
                 * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
                 *
                 * See {setApprovalForAll}.
                 */
                function isApprovedForAll(address account, address operator) external view returns (bool);
                /**
                 * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
                 *
                 * Emits a {TransferSingle} event.
                 *
                 * Requirements:
                 *
                 * - `to` cannot be the zero address.
                 * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
                 * - `from` must have a balance of tokens of type `id` of at least `amount`.
                 * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
                 * acceptance magic value.
                 */
                function safeTransferFrom(
                    address from,
                    address to,
                    uint256 id,
                    uint256 amount,
                    bytes calldata data
                ) external;
                /**
                 * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
                 *
                 * Emits a {TransferBatch} event.
                 *
                 * Requirements:
                 *
                 * - `ids` and `amounts` must have the same length.
                 * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
                 * acceptance magic value.
                 */
                function safeBatchTransferFrom(
                    address from,
                    address to,
                    uint256[] calldata ids,
                    uint256[] calldata amounts,
                    bytes calldata data
                ) external;
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)
            pragma solidity ^0.8.0;
            import "../../utils/introspection/IERC165Upgradeable.sol";
            /**
             * @dev _Available since v3.1._
             */
            interface IERC1155ReceiverUpgradeable is IERC165Upgradeable {
                /**
                 * @dev Handles the receipt of a single ERC1155 token type. This function is
                 * called at the end of a `safeTransferFrom` after the balance has been updated.
                 *
                 * NOTE: To accept the transfer, this must return
                 * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
                 * (i.e. 0xf23a6e61, or its own function selector).
                 *
                 * @param operator The address which initiated the transfer (i.e. msg.sender)
                 * @param from The address which previously owned the token
                 * @param id The ID of the token being transferred
                 * @param value The amount of tokens being transferred
                 * @param data Additional data with no specified format
                 * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
                 */
                function onERC1155Received(
                    address operator,
                    address from,
                    uint256 id,
                    uint256 value,
                    bytes calldata data
                ) external returns (bytes4);
                /**
                 * @dev Handles the receipt of a multiple ERC1155 token types. This function
                 * is called at the end of a `safeBatchTransferFrom` after the balances have
                 * been updated.
                 *
                 * NOTE: To accept the transfer(s), this must return
                 * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
                 * (i.e. 0xbc197c81, or its own function selector).
                 *
                 * @param operator The address which initiated the batch transfer (i.e. msg.sender)
                 * @param from The address which previously owned the token
                 * @param ids An array containing ids of each token being transferred (order and length must match values array)
                 * @param values An array containing amounts of each token being transferred (order and length must match ids array)
                 * @param data Additional data with no specified format
                 * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
                 */
                function onERC1155BatchReceived(
                    address operator,
                    address from,
                    uint256[] calldata ids,
                    uint256[] calldata values,
                    bytes calldata data
                ) external returns (bytes4);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)
            pragma solidity ^0.8.0;
            import "../IERC1155Upgradeable.sol";
            /**
             * @dev Interface of the optional ERC1155MetadataExtension interface, as defined
             * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
             *
             * _Available since v3.1._
             */
            interface IERC1155MetadataURIUpgradeable is IERC1155Upgradeable {
                /**
                 * @dev Returns the URI for token type `id`.
                 *
                 * If the `\\{id\\}` substring is present in the URI, it must be replaced by
                 * clients with the actual token type ID.
                 */
                function uri(uint256 id) external view returns (string memory);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
            pragma solidity ^0.8.1;
            /**
             * @dev Collection of functions related to the address type
             */
            library AddressUpgradeable {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 *
                 * [IMPORTANT]
                 * ====
                 * You shouldn't rely on `isContract` to protect against flash loan attacks!
                 *
                 * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                 * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                 * constructor.
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize/address.code.length, which returns 0
                    // for contracts in construction, since the code is only stored at the end
                    // of the constructor execution.
                    return account.code.length > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    (bool success, ) = recipient.call{value: amount}("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain `call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    (bool success, bytes memory returndata) = target.call{value: value}(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                 * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                 *
                 * _Available since v4.8._
                 */
                function verifyCallResultFromTarget(
                    address target,
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    if (success) {
                        if (returndata.length == 0) {
                            // only check isContract if the call was successful and the return data is empty
                            // otherwise we already know that it was a contract
                            require(isContract(target), "Address: call to non-contract");
                        }
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                /**
                 * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                 * revert reason or using the provided one.
                 *
                 * _Available since v4.3._
                 */
                function verifyCallResult(
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal pure returns (bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                function _revert(bytes memory returndata, string memory errorMessage) private pure {
                    // Look for revert reason and bubble it up if present
                    if (returndata.length > 0) {
                        // The easiest way to bubble the revert reason is using memory via assembly
                        /// @solidity memory-safe-assembly
                        assembly {
                            let returndata_size := mload(returndata)
                            revert(add(32, returndata), returndata_size)
                        }
                    } else {
                        revert(errorMessage);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
            pragma solidity ^0.8.0;
            import "../proxy/utils/Initializable.sol";
            /**
             * @dev Provides information about the current execution context, including the
             * sender of the transaction and its data. While these are generally available
             * via msg.sender and msg.data, they should not be accessed in such a direct
             * manner, since when dealing with meta-transactions the account sending and
             * paying for execution may not be the actual sender (as far as an application
             * is concerned).
             *
             * This contract is only required for intermediate, library-like contracts.
             */
            abstract contract ContextUpgradeable is Initializable {
                function __Context_init() internal onlyInitializing {
                }
                function __Context_init_unchained() internal onlyInitializing {
                }
                function _msgSender() internal view virtual returns (address) {
                    return msg.sender;
                }
                function _msgData() internal view virtual returns (bytes calldata) {
                    return msg.data;
                }
                /**
                 * @dev This empty reserved space is put in place to allow future versions to add new
                 * variables without shifting down storage in the inheritance chain.
                 * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
                 */
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
            pragma solidity ^0.8.0;
            import "./IERC165Upgradeable.sol";
            import "../../proxy/utils/Initializable.sol";
            /**
             * @dev Implementation of the {IERC165} interface.
             *
             * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
             * for the additional interface id that will be supported. For example:
             *
             * ```solidity
             * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
             *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
             * }
             * ```
             *
             * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
             */
            abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
                function __ERC165_init() internal onlyInitializing {
                }
                function __ERC165_init_unchained() internal onlyInitializing {
                }
                /**
                 * @dev See {IERC165-supportsInterface}.
                 */
                function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
                    return interfaceId == type(IERC165Upgradeable).interfaceId;
                }
                /**
                 * @dev This empty reserved space is put in place to allow future versions to add new
                 * variables without shifting down storage in the inheritance chain.
                 * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
                 */
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)
            pragma solidity ^0.8.2;
            import "../../utils/AddressUpgradeable.sol";
            /**
             * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
             * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
             * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
             * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
             *
             * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
             * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
             * case an upgrade adds a module that needs to be initialized.
             *
             * For example:
             *
             * [.hljs-theme-light.nopadding]
             * ```
             * contract MyToken is ERC20Upgradeable {
             *     function initialize() initializer public {
             *         __ERC20_init("MyToken", "MTK");
             *     }
             * }
             * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
             *     function initializeV2() reinitializer(2) public {
             *         __ERC20Permit_init("MyToken");
             *     }
             * }
             * ```
             *
             * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
             * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
             *
             * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
             * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
             *
             * [CAUTION]
             * ====
             * Avoid leaving a contract uninitialized.
             *
             * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
             * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
             * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
             *
             * [.hljs-theme-light.nopadding]
             * ```
             * /// @custom:oz-upgrades-unsafe-allow constructor
             * constructor() {
             *     _disableInitializers();
             * }
             * ```
             * ====
             */
            abstract contract Initializable {
                /**
                 * @dev Indicates that the contract has been initialized.
                 * @custom:oz-retyped-from bool
                 */
                uint8 private _initialized;
                /**
                 * @dev Indicates that the contract is in the process of being initialized.
                 */
                bool private _initializing;
                /**
                 * @dev Triggered when the contract has been initialized or reinitialized.
                 */
                event Initialized(uint8 version);
                /**
                 * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
                 * `onlyInitializing` functions can be used to initialize parent contracts.
                 *
                 * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
                 * constructor.
                 *
                 * Emits an {Initialized} event.
                 */
                modifier initializer() {
                    bool isTopLevelCall = !_initializing;
                    require(
                        (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
                        "Initializable: contract is already initialized"
                    );
                    _initialized = 1;
                    if (isTopLevelCall) {
                        _initializing = true;
                    }
                    _;
                    if (isTopLevelCall) {
                        _initializing = false;
                        emit Initialized(1);
                    }
                }
                /**
                 * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
                 * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
                 * used to initialize parent contracts.
                 *
                 * A reinitializer may be used after the original initialization step. This is essential to configure modules that
                 * are added through upgrades and that require initialization.
                 *
                 * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
                 * cannot be nested. If one is invoked in the context of another, execution will revert.
                 *
                 * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
                 * a contract, executing them in the right order is up to the developer or operator.
                 *
                 * WARNING: setting the version to 255 will prevent any future reinitialization.
                 *
                 * Emits an {Initialized} event.
                 */
                modifier reinitializer(uint8 version) {
                    require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
                    _initialized = version;
                    _initializing = true;
                    _;
                    _initializing = false;
                    emit Initialized(version);
                }
                /**
                 * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
                 * {initializer} and {reinitializer} modifiers, directly or indirectly.
                 */
                modifier onlyInitializing() {
                    require(_initializing, "Initializable: contract is not initializing");
                    _;
                }
                /**
                 * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
                 * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
                 * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
                 * through proxies.
                 *
                 * Emits an {Initialized} event the first time it is successfully executed.
                 */
                function _disableInitializers() internal virtual {
                    require(!_initializing, "Initializable: contract is initializing");
                    if (_initialized < type(uint8).max) {
                        _initialized = type(uint8).max;
                        emit Initialized(type(uint8).max);
                    }
                }
                /**
                 * @dev Returns the highest version that has been initialized. See {reinitializer}.
                 */
                function _getInitializedVersion() internal view returns (uint8) {
                    return _initialized;
                }
                /**
                 * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
                 */
                function _isInitializing() internal view returns (bool) {
                    return _initializing;
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Interface of the ERC165 standard, as defined in the
             * https://eips.ethereum.org/EIPS/eip-165[EIP].
             *
             * Implementers can declare support of contract interfaces, which can then be
             * queried by others ({ERC165Checker}).
             *
             * For an implementation, see {ERC165}.
             */
            interface IERC165Upgradeable {
                /**
                 * @dev Returns true if this contract implements the interface defined by
                 * `interfaceId`. See the corresponding
                 * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
                 * to learn more about how these ids are created.
                 *
                 * This function call must use less than 30 000 gas.
                 */
                function supportsInterface(bytes4 interfaceId) external view returns (bool);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {ITransferHookReceiver} from "../interfaces/ITransferHookReceiver.sol";
            /*
                         ░░░░░░░░░░░░░░              
                    ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                  ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
               ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
              ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
              ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
              ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
               ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                  ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                      ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                           OURS TRULY,
             */
            /// Imagine. Mint. Enjoy.
            /// @notice Interface for types used across the ZoraCreator1155 contract
            /// @author @iainnash / @tbtstl
            interface IZoraCreator1155TypesV1 {
                /// @notice Used to store individual token data
                struct TokenData {
                    string uri;
                    uint256 maxSupply;
                    uint256 totalMinted;
                }
                /// @notice Used to store contract-level configuration
                struct ContractConfig {
                    address owner;
                    uint96 __gap1;
                    address payable fundsRecipient;
                    uint96 __gap2;
                    ITransferHookReceiver transferHook;
                    uint96 __gap3;
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            interface IOwnable {
                function owner() external returns (address);
                event OwnershipTransferred(address lastOwner, address newOwner);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            interface IVersionedContract {
                function contractVersion() external returns (string memory);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol";
            interface ICreatorRoyaltiesControl is IERC2981 {
                /// @notice The RoyaltyConfiguration struct is used to store the royalty configuration for a given token.
                /// @param royaltyMintSchedule Every nth token will go to the royalty recipient.
                /// @param royaltyBPS The royalty amount in basis points for secondary sales.
                /// @param royaltyRecipient The address that will receive the royalty payments.
                struct RoyaltyConfiguration {
                    uint32 royaltyMintSchedule;
                    uint32 royaltyBPS;
                    address royaltyRecipient;
                }
                /// @notice Thrown when a user tries to have 100% supply royalties
                error InvalidMintSchedule();
                /// @notice Event emitted when royalties are updated
                event UpdatedRoyalties(uint256 indexed tokenId, address indexed user, RoyaltyConfiguration configuration);
                /// @notice External data getter to get royalties for a token
                /// @param tokenId tokenId to get royalties configuration for
                function getRoyalties(uint256 tokenId) external view returns (RoyaltyConfiguration memory);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
             * proxy whose upgrades are fully controlled by the current implementation.
             */
            interface IERC1822ProxiableUpgradeable {
                /**
                 * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
                 * address.
                 *
                 * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
                 * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
                 * function revert if invoked through a proxy.
                 */
                function proxiableUUID() external view returns (bytes32);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
            pragma solidity ^0.8.2;
            import "../beacon/IBeaconUpgradeable.sol";
            import "../../interfaces/draft-IERC1822Upgradeable.sol";
            import "../../utils/AddressUpgradeable.sol";
            import "../../utils/StorageSlotUpgradeable.sol";
            import "../utils/Initializable.sol";
            /**
             * @dev This abstract contract provides getters and event emitting update functions for
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
             *
             * _Available since v4.1._
             *
             * @custom:oz-upgrades-unsafe-allow delegatecall
             */
            abstract contract ERC1967UpgradeUpgradeable is Initializable {
                function __ERC1967Upgrade_init() internal onlyInitializing {
                }
                function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
                }
                // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
                bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
                /**
                 * @dev Storage slot with the address of the current implementation.
                 * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                /**
                 * @dev Emitted when the implementation is upgraded.
                 */
                event Upgraded(address indexed implementation);
                /**
                 * @dev Returns the current implementation address.
                 */
                function _getImplementation() internal view returns (address) {
                    return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 implementation slot.
                 */
                function _setImplementation(address newImplementation) private {
                    require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                    StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                }
                /**
                 * @dev Perform implementation upgrade
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeTo(address newImplementation) internal {
                    _setImplementation(newImplementation);
                    emit Upgraded(newImplementation);
                }
                /**
                 * @dev Perform implementation upgrade with additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCall(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _upgradeTo(newImplementation);
                    if (data.length > 0 || forceCall) {
                        _functionDelegateCall(newImplementation, data);
                    }
                }
                /**
                 * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCallUUPS(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    // Upgrades from old implementations will perform a rollback test. This test requires the new
                    // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
                    // this special case will break upgrade paths from old UUPS implementation to new ones.
                    if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {
                        _setImplementation(newImplementation);
                    } else {
                        try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                            require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
                        } catch {
                            revert("ERC1967Upgrade: new implementation is not UUPS");
                        }
                        _upgradeToAndCall(newImplementation, data, forceCall);
                    }
                }
                /**
                 * @dev Storage slot with the admin of the contract.
                 * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                /**
                 * @dev Emitted when the admin account has changed.
                 */
                event AdminChanged(address previousAdmin, address newAdmin);
                /**
                 * @dev Returns the current admin.
                 */
                function _getAdmin() internal view returns (address) {
                    return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 admin slot.
                 */
                function _setAdmin(address newAdmin) private {
                    require(newAdmin != address(0), "ERC1967: new admin is the zero address");
                    StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
                }
                /**
                 * @dev Changes the admin of the proxy.
                 *
                 * Emits an {AdminChanged} event.
                 */
                function _changeAdmin(address newAdmin) internal {
                    emit AdminChanged(_getAdmin(), newAdmin);
                    _setAdmin(newAdmin);
                }
                /**
                 * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
                 * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
                 */
                bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
                /**
                 * @dev Emitted when the beacon is upgraded.
                 */
                event BeaconUpgraded(address indexed beacon);
                /**
                 * @dev Returns the current beacon.
                 */
                function _getBeacon() internal view returns (address) {
                    return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
                }
                /**
                 * @dev Stores a new beacon in the EIP1967 beacon slot.
                 */
                function _setBeacon(address newBeacon) private {
                    require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
                    require(
                        AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
                        "ERC1967: beacon implementation is not a contract"
                    );
                    StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
                }
                /**
                 * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
                 * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
                 *
                 * Emits a {BeaconUpgraded} event.
                 */
                function _upgradeBeaconToAndCall(
                    address newBeacon,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _setBeacon(newBeacon);
                    emit BeaconUpgraded(newBeacon);
                    if (data.length > 0 || forceCall) {
                        _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
                    }
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {
                    require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed");
                }
                /**
                 * @dev This empty reserved space is put in place to allow future versions to add new
                 * variables without shifting down storage in the inheritance chain.
                 * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
                 */
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            /// Imagine. Mint. Enjoy.
            /// @author @iainnash / @tbtstl
            contract CreatorPermissionStorageV1 {
                mapping(uint256 => mapping(address => uint256)) public permissions;
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            /// @notice Generic control interface for bit-based permissions-control
            interface ICreatorPermissionControl {
                /// @notice Emitted when permissions are updated
                event UpdatedPermissions(uint256 indexed tokenId, address indexed user, uint256 indexed permissions);
                /// @notice Public interface to get permissions given a token id and a user address
                /// @return Returns raw permission bits
                function getPermissions(uint256 tokenId, address user) external view returns (uint256);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {ICreatorRendererControl} from "../interfaces/ICreatorRendererControl.sol";
            import {IRenderer1155} from "../interfaces/IRenderer1155.sol";
            /// @notice Creator Renderer Storage Configuration Contract V1
            abstract contract CreatorRendererStorageV1 is ICreatorRendererControl {
                /// @notice Mapping for custom renderers
                mapping(uint256 => IRenderer1155) public customRenderers;
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol";
            /// Imagine. Mint. Enjoy.
            /// @title CreatorRoyaltiesControl
            /// @author ZORA @iainnash / @tbtstl
            /// @notice Royalty storage contract pattern
            abstract contract CreatorRoyaltiesStorageV1 is ICreatorRoyaltiesControl {
                mapping(uint256 => RoyaltyConfiguration) public royalties;
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)
            pragma solidity ^0.8.0;
            import "../utils/introspection/IERC165.sol";
            /**
             * @dev Interface for the NFT Royalty Standard.
             *
             * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
             * support for royalty payments across all NFT marketplaces and ecosystem participants.
             *
             * _Available since v4.5._
             */
            interface IERC2981 is IERC165 {
                /**
                 * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
                 * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
                 */
                function royaltyInfo(uint256 tokenId, uint256 salePrice)
                    external
                    view
                    returns (address receiver, uint256 royaltyAmount);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            interface ILegacyNaming {
                function name() external returns (string memory);
                function symbol() external returns (string memory);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            contract LegacyNamingStorageV1 {
                string internal _name;
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            interface IMintFeeManager {
                error MintFeeCannotBeMoreThanZeroPointOneETH(uint256 mintFeeBPS);
                error CannotSendMintFee(address mintFeeRecipient, uint256 mintFee);
                error CannotSetMintFeeToZeroAddress();
                function mintFee() external view returns (uint256);
                function mintFeeRecipient() external view returns (address);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
            pragma solidity ^0.8.1;
            /**
             * @dev Collection of functions related to the address type
             */
            library Address {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 *
                 * [IMPORTANT]
                 * ====
                 * You shouldn't rely on `isContract` to protect against flash loan attacks!
                 *
                 * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                 * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                 * constructor.
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize/address.code.length, which returns 0
                    // for contracts in construction, since the code is only stored at the end
                    // of the constructor execution.
                    return account.code.length > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    (bool success, ) = recipient.call{value: amount}("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain `call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    (bool success, bytes memory returndata) = target.call{value: value}(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                 * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                 *
                 * _Available since v4.8._
                 */
                function verifyCallResultFromTarget(
                    address target,
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    if (success) {
                        if (returndata.length == 0) {
                            // only check isContract if the call was successful and the return data is empty
                            // otherwise we already know that it was a contract
                            require(isContract(target), "Address: call to non-contract");
                        }
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                /**
                 * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                 * revert reason or using the provided one.
                 *
                 * _Available since v4.3._
                 */
                function verifyCallResult(
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal pure returns (bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                function _revert(bytes memory returndata, string memory errorMessage) private pure {
                    // Look for revert reason and bubble it up if present
                    if (returndata.length > 0) {
                        // The easiest way to bubble the revert reason is using memory via assembly
                        /// @solidity memory-safe-assembly
                        assembly {
                            let returndata_size := mload(returndata)
                            revert(add(32, returndata), returndata_size)
                        }
                    } else {
                        revert(errorMessage);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev This is the interface that {BeaconProxy} expects of its beacon.
             */
            interface IBeaconUpgradeable {
                /**
                 * @dev Must return an address that can be used as a delegate call target.
                 *
                 * {BeaconProxy} will check that this address is a contract.
                 */
                function implementation() external view returns (address);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Library for reading and writing primitive types to specific storage slots.
             *
             * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
             * This library helps with reading and writing to such slots without the need for inline assembly.
             *
             * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
             *
             * Example usage to set ERC1967 implementation slot:
             * ```
             * contract ERC1967 {
             *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
             *
             *     function _getImplementation() internal view returns (address) {
             *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
             *     }
             *
             *     function _setImplementation(address newImplementation) internal {
             *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
             *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
             *     }
             * }
             * ```
             *
             * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
             */
            library StorageSlotUpgradeable {
                struct AddressSlot {
                    address value;
                }
                struct BooleanSlot {
                    bool value;
                }
                struct Bytes32Slot {
                    bytes32 value;
                }
                struct Uint256Slot {
                    uint256 value;
                }
                /**
                 * @dev Returns an `AddressSlot` with member `value` located at `slot`.
                 */
                function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
                 */
                function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
                 */
                function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
                 */
                function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.17;
            import {IRenderer1155} from "./IRenderer1155.sol";
            /// @notice Interface for creator renderer controls
            interface ICreatorRendererControl {
                /// @notice Get the custom renderer contract (if any) for the given token id
                /// @dev Reverts if not custom renderer is set for this token
                function getCustomRenderer(uint256 tokenId) external view returns (IRenderer1155 renderer);
                error NoRendererForToken(uint256 tokenId);
                error RendererNotValid(address renderer);
                event RendererUpdated(uint256 indexed tokenId, address indexed renderer, address indexed user);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Interface of the ERC165 standard, as defined in the
             * https://eips.ethereum.org/EIPS/eip-165[EIP].
             *
             * Implementers can declare support of contract interfaces, which can then be
             * queried by others ({ERC165Checker}).
             *
             * For an implementation, see {ERC165}.
             */
            interface IERC165 {
                /**
                 * @dev Returns true if this contract implements the interface defined by
                 * `interfaceId`. See the corresponding
                 * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
                 * to learn more about how these ids are created.
                 *
                 * This function call must use less than 30 000 gas.
                 */
                function supportsInterface(bytes4 interfaceId) external view returns (bool);
            }