ETH Price: $2,631.51 (-0.26%)

Transaction Decoder

Block:
19033273 at Jan-18-2024 10:52:23 AM +UTC
Transaction Fee:
0.02272282647275735 ETH $59.80
Gas Used:
774,941 Gas / 29.32200835 Gwei

Emitted Events:

371 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b( 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b, 0x000000000000000000000000f62b0d56ba617f803df1c464c519ff7d29451b2f )
372 Zora1155Factory.0xa45800684f65ae010ceb4385eceaed88dec7f6a6bcbe11f7ffd8bd24dd2653f4( 0xa45800684f65ae010ceb4385eceaed88dec7f6a6bcbe11f7ffd8bd24dd2653f4, 0x0000000000000000000000006430f63c18e0a3798e39d8a0e3f00c2f5f295cd8, 0x000000000000000000000000dfd4593407463a9aac266fb33f89e874de48ec63, 0x000000000000000000000000dfd4593407463a9aac266fb33f89e874de48ec63, 00000000000000000000000000000000000000000000000000000000000000a0, 0000000000000000000000000000000000000000000000000000000000000120, 0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000000000000000000000000000000000000000001f4, 000000000000000000000000dfd4593407463a9aac266fb33f89e874de48ec63, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b7265696733696e6a6c336c33343535626d72703674, 3773657966717a6e726c323766747a6a693234623673777573746572646c3736, 7571000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000009, 5468726573686f6c640000000000000000000000000000000000000000000000 )
373 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000dfd4593407463a9aac266fb33f89e874de48ec63, 0x0000000000000000000000000000000000000000000000000000000000000002 )
374 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe( 0x5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000060, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b7265696733696e6a6c336c33343535626d72703674, 3773657966717a6e726c323766747a6a693234623673777573746572646c3736, 7571000000000000000000000000000000000000000000000000000000000000 )
375 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d( 0x5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000000000000000000000000000000000000000001f4, 000000000000000000000000dfd4593407463a9aac266fb33f89e874de48ec63 )
376 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0( 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0, 0000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000dfd4593407463a9aac266fb33f89e874de48ec63 )
377 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f( 0x3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000dfd4593407463a9aac266fb33f89e874de48ec63, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
378 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f( 0x3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000001, 000000000000000000000000dfd4593407463a9aac266fb33f89e874de48ec63, 0000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000dfd4593407463a9aac266fb33f89e874de48ec63, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
379 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000002 )
380 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe( 0x5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000060, 000000000000000000000000000000000000000000000000000000000000000a, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b7265696166637075686a716c7278706a6f33687773, 6c70706c796c6a793469356a6933347079756e6e68346f7174616f7474377973, 7a61000000000000000000000000000000000000000000000000000000000000 )
381 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000002 )
382 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b( 0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b, 0x0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b7265696166637075686a716c7278706a6f33687773, 6c70706c796c6a793469356a6933347079756e6e68346f7174616f7474377973, 7a61000000000000000000000000000000000000000000000000000000000000 )
383 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc068( 0x1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc068, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0000000000000000000000000000000000000000000000000000000000000040, 000000000000000000000000000000000000000000000000000000000000000a, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b7265696166637075686a716c7278706a6f33687773, 6c70706c796c6a793469356a6933347079756e6e68346f7174616f7474377973, 7a61000000000000000000000000000000000000000000000000000000000000 )
384 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d( 0x5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000000000000000000000000000000000000000001f4, 000000000000000000000000dfd4593407463a9aac266fb33f89e874de48ec63 )
385 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000008a1dbe9b1ceb1d17f92bebf10216fcfab5c3fba7, 0x0000000000000000000000000000000000000000000000000000000000000004 )
386 ZoraCreatorFixedPriceSaleStrategy.SaleSet( mediaContract=0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8, tokenId=1, salesConfig=[{name:saleStart, type:uint64, order:1, indexed:false, value:1705574676, valueString:1705574676}, {name:saleEnd, type:uint64, order:2, indexed:false, value:1708166676, valueString:1708166676}, {name:maxTokensPerAddress, type:uint64, order:3, indexed:false, value:1, valueString:1}, {name:pricePerToken, type:uint96, order:4, indexed:false, value:0, valueString:0}, {name:fundsRecipient, type:address, order:5, indexed:false, value:0xdFd4593407463A9AAC266FB33F89E874DE48Ec63, valueString:0xdFd4593407463A9AAC266FB33F89E874DE48Ec63}] )
387 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62( 0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000dfd4593407463a9aac266fb33f89e874de48ec63, 0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000001 )
388 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000000 )
389 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498, 0000000000000000000000000000000000000000000000000000000000000001 )

Account State Difference:

  Address   Before After State Difference Code
0x6430f63C...F5f295CD8
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 7580990366191477516319551431636853775417539837550867334602508048238757929087879027900449337487518794946950352205601743281030887287489436310908839699191659809388444823355674645354979357162961249134900110529687881663019692932138136169432064773836259952710621644470898343405927174133984597236657651087359028670195474342013788531238380808257890765480551801068149982708333191330653462914990335414292036779052701522397263760767722087683826927505529058253836012422366209295387656704517895932345491714654640330818408147054761662211806231406253405064807161040797747
0x8A1DBE9b...Ab5C3fbA7
(beaverbuild)
16.74669471151990066 Eth16.74670782503275561 Eth0.00001311351285495
0xA6C5f2DE...91748cb85
0xdFd45934...4DE48Ec63
0.061975363178806191 Eth
Nonce: 14
0.039252536706048841 Eth
Nonce: 15
0.02272282647275735

Execution Trace

Zora1155Factory.0582823a( )
  • ZoraCreator1155FactoryImpl.createContract( newContractURI=ipfs://bafkreig3injl3l3455bmrp6t7seyfqznrl27ftzji24b6swusterdl76uq, name=Threshold, defaultRoyaltyConfiguration=[{name:royaltyMintSchedule, type:uint32, order:1, indexed:false, value:0, valueString:0}, {name:royaltyBPS, type:uint32, order:2, indexed:false, value:500, valueString:500}, {name:royaltyRecipient, type:address, order:3, indexed:false, value:0xdFd4593407463A9AAC266FB33F89E874DE48Ec63, valueString:0xdFd4593407463A9AAC266FB33F89E874DE48Ec63}], defaultAdmin=0xdFd4593407463A9AAC266FB33F89E874DE48Ec63, setupActions=[5yh4tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, Z0y65gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCaXBmczovL2JhZmtyZWlhZmNwdWhqcWxyeHBqbzNod3NscHBseWxqeTRpNWppMzRweXVubmg0b3F0YW90dDd5c3phAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, r+1+ngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9AAAAAAAAAAAAAAAAN/UWTQHRjqarCZvsz+J6HTeSOxj, jsmYoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAih2+mxzrHRf5K+vxAhb8+rXD+6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA==, 2QS5SgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAih2+mxzrHRf5K+vxAhb8+rXD+6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADENNt+7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGWpARQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZdCOFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADf1Fk0B0Y6mqwmb7M/ieh03kjsYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=, wjjR7gAAAAAAAAAAAAAAAN/UWTQHRjqarCZvsz+J6HTeSOxjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==] ) => ( 0x6430f63C18E0A3798E39D8a0E3f00c2F5f295CD8 )
    • 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.60406080( )
    • 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.8a08eb4c( )
      • ZoraCreator1155Impl.initialize( contractName=Threshold, newContractURI=ipfs://bafkreig3injl3l3455bmrp6t7seyfqznrl27ftzji24b6swusterdl76uq, defaultRoyaltyConfiguration=[{name:royaltyMintSchedule, type:uint32, order:1, indexed:false, value:0, valueString:0}, {name:royaltyBPS, type:uint32, order:2, indexed:false, value:500, valueString:500}, {name:royaltyRecipient, type:address, order:3, indexed:false, value:0xdFd4593407463A9AAC266FB33F89E874DE48Ec63, valueString:0xdFd4593407463A9AAC266FB33F89E874DE48Ec63}], defaultAdmin=0xdFd4593407463A9AAC266FB33F89E874DE48Ec63, setupActions=[5yh4tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, Z0y65gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCaXBmczovL2JhZmtyZWlhZmNwdWhqcWxyeHBqbzNod3NscHBseWxqeTRpNWppMzRweXVubmg0b3F0YW90dDd5c3phAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, r+1+ngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9AAAAAAAAAAAAAAAAN/UWTQHRjqarCZvsz+J6HTeSOxj, jsmYoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAih2+mxzrHRf5K+vxAhb8+rXD+6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA==, 2QS5SgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAih2+mxzrHRf5K+vxAhb8+rXD+6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADENNt+7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGWpARQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZdCOFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADf1Fk0B0Y6mqwmb7M/ieh03kjsYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=, wjjR7gAAAAAAAAAAAAAAAN/UWTQHRjqarCZvsz+J6HTeSOxjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==] )
        • 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.e72878b4( )
        • 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.674cbae6( )
          • ZoraCreator1155Impl.setupNewTokenWithCreateReferral( newURI=ipfs://bafkreiafcpuhjqlrxpjo3hwslpplyljy4i5ji34pyunnh4oqtaott7ysza, maxSupply=10, createReferral=0x0000000000000000000000000000000000000000 ) => ( 1 )
          • 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.afed7e9e( )
            • ZoraCreator1155Impl.updateRoyaltiesForToken( tokenId=1, newConfiguration=[{name:royaltyMintSchedule, type:uint32, order:1, indexed:false, value:0, valueString:0}, {name:royaltyBPS, type:uint32, order:2, indexed:false, value:500, valueString:500}, {name:royaltyRecipient, type:address, order:3, indexed:false, value:0xdFd4593407463A9AAC266FB33F89E874DE48Ec63, valueString:0xdFd4593407463A9AAC266FB33F89E874DE48Ec63}] )
            • 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.8ec998a0( )
              • ZoraCreator1155Impl.addPermission( tokenId=1, user=0x8A1DBE9b1CeB1d17f92Bebf10216FCFAb5C3fbA7, permissionBits=4 )
              • 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.d904b94a( )
                • ZoraCreator1155Impl.callSale( tokenId=1, salesConfig=0x8A1DBE9b1CeB1d17f92Bebf10216FCFAb5C3fbA7, data=0x34DB7EEE00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000065A901140000000000000000000000000000000000000000000000000000000065D08E1400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000DFD4593407463A9AAC266FB33F89E874DE48EC63 )
                  • ZoraCreatorFixedPriceSaleStrategy.supportsInterface( interfaceId=System.Byte[] ) => ( True )
                  • ZoraCreatorFixedPriceSaleStrategy.setSale( tokenId=1, salesConfig=[{name:saleStart, type:uint64, order:1, indexed:false, value:1705574676, valueString:1705574676}, {name:saleEnd, type:uint64, order:2, indexed:false, value:1708166676, valueString:1708166676}, {name:maxTokensPerAddress, type:uint64, order:3, indexed:false, value:1, valueString:1}, {name:pricePerToken, type:uint96, order:4, indexed:false, value:0, valueString:0}, {name:fundsRecipient, type:address, order:5, indexed:false, value:0xdFd4593407463A9AAC266FB33F89E874DE48Ec63, valueString:0xdFd4593407463A9AAC266FB33F89E874DE48Ec63}] )
                  • 0x6430f63c18e0a3798e39d8a0e3f00c2f5f295cd8.c238d1ee( )
                    • ZoraCreator1155Impl.adminMint( recipient=0xdFd4593407463A9AAC266FB33F89E874DE48Ec63, tokenId=1, quantity=1, data=0x0000000000000000000000000000000000000000 )
                      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: ZoraCreatorFixedPriceSaleStrategy
                      // SPDX-License-Identifier: MIT
                      pragma solidity 0.8.17;
                      import {Enjoy} from "_imagine/mint/Enjoy.sol";
                      import {IMinter1155} from "../../interfaces/IMinter1155.sol";
                      import {ICreatorCommands} from "../../interfaces/ICreatorCommands.sol";
                      import {SaleStrategy} from "../SaleStrategy.sol";
                      import {SaleCommandHelper} from "../utils/SaleCommandHelper.sol";
                      import {LimitedMintPerAddress} from "../utils/LimitedMintPerAddress.sol";
                      /*
                                   ░░░░░░░░░░░░░░              
                              ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                            ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                          ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
                         ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
                        ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
                        ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
                        ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
                        ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
                         ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                          ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                          ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                            ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                                ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                                     OURS TRULY,
                          github.com/ourzora/zora-1155-contracts
                      */
                      /// @title ZoraCreatorFixedPriceSaleStrategy
                      /// @notice A sale strategy for ZoraCreator that allows for fixed price sales over a given time period
                      /// @author @iainnash / @tbtstl
                      contract ZoraCreatorFixedPriceSaleStrategy is Enjoy, SaleStrategy, LimitedMintPerAddress {
                          struct SalesConfig {
                              /// @notice Unix timestamp for the sale start
                              uint64 saleStart;
                              /// @notice Unix timestamp for the sale end
                              uint64 saleEnd;
                              /// @notice Max tokens that can be minted for an address, 0 if unlimited
                              uint64 maxTokensPerAddress;
                              /// @notice Price per token in eth wei
                              uint96 pricePerToken;
                              /// @notice Funds recipient (0 if no different funds recipient than the contract global)
                              address fundsRecipient;
                          }
                          // target -> tokenId -> settings
                          mapping(address => mapping(uint256 => SalesConfig)) internal salesConfigs;
                          using SaleCommandHelper for ICreatorCommands.CommandSet;
                          function contractURI() external pure override returns (string memory) {
                              return "https://github.com/ourzora/zora-1155-contracts/";
                          }
                          /// @notice The name of the sale strategy
                          function contractName() external pure override returns (string memory) {
                              return "Fixed Price Sale Strategy";
                          }
                          /// @notice The version of the sale strategy
                          function contractVersion() external pure override returns (string memory) {
                              return "1.1.0";
                          }
                          error WrongValueSent();
                          error SaleEnded();
                          error SaleHasNotStarted();
                          event SaleSet(address indexed mediaContract, uint256 indexed tokenId, SalesConfig salesConfig);
                          event MintComment(address indexed sender, address indexed tokenContract, uint256 indexed tokenId, uint256 quantity, string comment);
                          /// @notice Compiles and returns the commands needed to mint a token using this sales strategy
                          /// @param tokenId The token ID to mint
                          /// @param quantity The quantity of tokens to mint
                          /// @param ethValueSent The amount of ETH sent with the transaction
                          /// @param minterArguments The arguments passed to the minter, which should be the address to mint to
                          function requestMint(
                              address,
                              uint256 tokenId,
                              uint256 quantity,
                              uint256 ethValueSent,
                              bytes calldata minterArguments
                          ) external returns (ICreatorCommands.CommandSet memory commands) {
                              address mintTo;
                              string memory comment = "";
                              if (minterArguments.length == 32) {
                                  mintTo = abi.decode(minterArguments, (address));
                              } else {
                                  (mintTo, comment) = abi.decode(minterArguments, (address, string));
                              }
                              SalesConfig storage config = salesConfigs[msg.sender][tokenId];
                              // If sales config does not exist this first check will always fail.
                              // Check sale end
                              if (block.timestamp > config.saleEnd) {
                                  revert SaleEnded();
                              }
                              // Check sale start
                              if (block.timestamp < config.saleStart) {
                                  revert SaleHasNotStarted();
                              }
                              // Check value sent
                              if (config.pricePerToken * quantity != ethValueSent) {
                                  revert WrongValueSent();
                              }
                              // Check minted per address limit
                              if (config.maxTokensPerAddress > 0) {
                                  _requireMintNotOverLimitAndUpdate(config.maxTokensPerAddress, quantity, msg.sender, tokenId, mintTo);
                              }
                              bool shouldTransferFunds = config.fundsRecipient != address(0);
                              commands.setSize(shouldTransferFunds ? 2 : 1);
                              // Mint command
                              commands.mint(mintTo, tokenId, quantity);
                              if (bytes(comment).length > 0) {
                                  emit MintComment(mintTo, msg.sender, tokenId, quantity, comment);
                              }
                              // Should transfer funds if funds recipient is set to a non-default address
                              if (shouldTransferFunds) {
                                  commands.transfer(config.fundsRecipient, ethValueSent);
                              }
                          }
                          /// @notice Sets the sale config for a given token
                          function setSale(uint256 tokenId, SalesConfig memory salesConfig) external {
                              salesConfigs[msg.sender][tokenId] = salesConfig;
                              // Emit event
                              emit SaleSet(msg.sender, tokenId, salesConfig);
                          }
                          /// @notice Deletes the sale config for a given token
                          function resetSale(uint256 tokenId) external override {
                              delete salesConfigs[msg.sender][tokenId];
                              // Deleted sale emit event
                              emit SaleSet(msg.sender, tokenId, salesConfigs[msg.sender][tokenId]);
                          }
                          /// @notice Returns the sale config for a given token
                          function sale(address tokenContract, uint256 tokenId) external view returns (SalesConfig memory) {
                              return salesConfigs[tokenContract][tokenId];
                          }
                          function supportsInterface(bytes4 interfaceId) public pure virtual override(LimitedMintPerAddress, SaleStrategy) returns (bool) {
                              return super.supportsInterface(interfaceId) || LimitedMintPerAddress.supportsInterface(interfaceId) || SaleStrategy.supportsInterface(interfaceId);
                          }
                      }
                      // SPDX-License-Identifier: MIT
                      pragma solidity 0.8.17;
                      /*
                                   ░░░░░░░░░░░░░░              
                              ░░▒▒░░░░░░░░░░░░░░░░░░░░        
                            ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░      
                          ░░▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░    
                         ░▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░    
                        ░▓▓▓▒▒▒▒░░░░░░░░░░░░        ░░░░░░░░  
                        ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░    ░░░░░░░░░░  
                        ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░  
                        ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░  
                         ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░  
                          ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░    
                          ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░    
                            ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░      
                                ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░          
                                     OURS TRULY,
                       */
                      interface Enjoy {
                      }
                      // 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;
                      /// @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 {IMinter1155} from "../interfaces/IMinter1155.sol";
                      import {IContractMetadata} from "../interfaces/IContractMetadata.sol";
                      import {IVersionedContract} from "../interfaces/IVersionedContract.sol";
                      import {ICreatorCommands} from "../interfaces/ICreatorCommands.sol";
                      import {SaleCommandHelper} from "./utils/SaleCommandHelper.sol";
                      /// @notice Sales Strategy Helper contract template on top of IMinter1155
                      /// @author @iainnash / @tbtstl
                      abstract contract SaleStrategy is IMinter1155, IVersionedContract, IContractMetadata {
                          /// @notice This function resets the sales configuration for a given tokenId and contract.
                          /// @dev This function is intentioned to be called directly from the affected sales contract
                          function resetSale(uint256 tokenId) external virtual;
                          function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
                              return interfaceId == type(IMinter1155).interfaceId || interfaceId == type(IERC165Upgradeable).interfaceId;
                          }
                      }
                      // SPDX-License-Identifier: MIT
                      pragma solidity 0.8.17;
                      import {ICreatorCommands} from "../../interfaces/ICreatorCommands.sol";
                      /// @title SaleCommandHelper
                      /// @notice Helper library for creating commands for the sale contract
                      /// @author @iainnash / @tbtstl
                      library SaleCommandHelper {
                          /// @notice Sets the size of commands and initializes command array. Empty entries are skipped by the resolver.
                          /// @dev Beware: this removes all previous command entries from memory
                          /// @param commandSet command set struct storage.
                          /// @param size size to set for the new struct
                          function setSize(ICreatorCommands.CommandSet memory commandSet, uint256 size) internal pure {
                              commandSet.commands = new ICreatorCommands.Command[](size);
                          }
                          /// @notice Creates a command to mint a token
                          /// @param commandSet The command set to add the command to
                          /// @param to The address to mint to
                          /// @param tokenId The token ID to mint
                          /// @param quantity The quantity of tokens to mint
                          function mint(ICreatorCommands.CommandSet memory commandSet, address to, uint256 tokenId, uint256 quantity) internal pure {
                              unchecked {
                                  commandSet.commands[commandSet.at++] = ICreatorCommands.Command({
                                      method: ICreatorCommands.CreatorActions.MINT,
                                      args: abi.encode(to, tokenId, quantity)
                                  });
                              }
                          }
                          /// @notice Creates a command to transfer ETH
                          /// @param commandSet The command set to add the command to
                          /// @param to The address to transfer to
                          /// @param amount The amount of ETH to transfer
                          function transfer(ICreatorCommands.CommandSet memory commandSet, address to, uint256 amount) internal pure {
                              unchecked {
                                  commandSet.commands[commandSet.at++] = ICreatorCommands.Command({method: ICreatorCommands.CreatorActions.SEND_ETH, args: abi.encode(to, amount)});
                              }
                          }
                      }
                      // SPDX-License-Identifier: MIT
                      pragma solidity 0.8.17;
                      import {ILimitedMintPerAddress} from "../../interfaces/ILimitedMintPerAddress.sol";
                      contract LimitedMintPerAddress is ILimitedMintPerAddress {
                          /// @notice Storage for slot to check user mints
                          /// @notice target contract -> tokenId -> minter user -> numberMinted
                          /// @dev No gap or stroage interface since this is used within non-upgradeable contracts
                          mapping(address => mapping(uint256 => mapping(address => uint256))) internal mintedPerAddress;
                          function getMintedPerWallet(address tokenContract, uint256 tokenId, address wallet) external view returns (uint256) {
                              return mintedPerAddress[tokenContract][tokenId][wallet];
                          }
                          function _requireMintNotOverLimitAndUpdate(uint256 limit, uint256 numRequestedMint, address tokenContract, uint256 tokenId, address wallet) internal {
                              mintedPerAddress[tokenContract][tokenId][wallet] += numRequestedMint;
                              if (mintedPerAddress[tokenContract][tokenId][wallet] > limit) {
                                  revert UserExceedsMintLimit(wallet, limit, mintedPerAddress[tokenContract][tokenId][wallet]);
                              }
                          }
                          function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) {
                              return interfaceId == type(ILimitedMintPerAddress).interfaceId;
                          }
                      }
                      // 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;
                      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;
                      interface IVersionedContract {
                          function contractVersion() external returns (string memory);
                      }
                      // SPDX-License-Identifier: MIT
                      pragma solidity 0.8.17;
                      import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
                      interface ILimitedMintPerAddress is IERC165Upgradeable {
                          error UserExceedsMintLimit(address user, uint256 limit, uint256 requestedAmount);
                          function getMintedPerWallet(address token, uint256 tokenId, address wallet) external view returns (uint256);
                      }
                      // 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);
                      }
                      

                      File 3 of 4: ZoraCreator1155FactoryImpl
                      // SPDX-License-Identifier: MIT
                      pragma solidity 0.8.17;
                      import {Initializable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol";
                      import {UUPSUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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 {
                              if (!_equals(IContractMetadata(_newImpl).contractName(), this.contractName())) {
                                  revert UpgradeToMismatchedContractName(this.contractName(), IContractMetadata(_newImpl).contractName());
                              }
                          }
                          function _equals(string memory a, string memory b) internal pure returns (bool) {
                              return (keccak256(bytes(a)) == keccak256(bytes(b)));
                          }
                      }
                      // SPDX-License-Identifier: MIT
                      // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol)
                      pragma solidity ^0.8.2;
                      import "../../utils/AddressUpgradeable.sol";
                      error INITIALIZABLE_CONTRACT_ALREADY_INITIALIZED();
                      error INITIALIZABLE_CONTRACT_IS_NOT_INITIALIZING();
                      error INITIALIZABLE_CONTRACT_IS_INITIALIZING();
                      /**
                       * @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]
                       * ```solidity
                       * 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;
                              if ((!isTopLevelCall || _initialized != 0) && (AddressUpgradeable.isContract(address(this)) || _initialized != 1)) {
                                  revert INITIALIZABLE_CONTRACT_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) {
                              if (_initializing || _initialized >= version) {
                                  revert INITIALIZABLE_CONTRACT_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() {
                              if (!_initializing) {
                                  revert 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 {
                              if (_initializing) {
                                  revert 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";
                      error FUNCTION_MUST_BE_CALLED_THROUGH_DELEGATECALL();
                      error FUNCTION_MUST_BE_CALLED_THROUGH_ACTIVE_PROXY();
                      error UUPS_UPGRADEABLE_MUST_NOT_BE_CALLED_THROUGH_DELEGATECALL();
                      /**
                       * @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() {
                              if (address(this) == __self) {
                                  revert FUNCTION_MUST_BE_CALLED_THROUGH_DELEGATECALL();
                              }
                              if (_getImplementation() != __self) {
                                  revert 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() {
                              if (address(this) != __self) {
                                  revert UUPS_UPGRADEABLE_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.
                           *
                           * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
                           */
                          function upgradeTo(address newImplementation) public 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.
                           *
                           * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
                           */
                          function upgradeToAndCall(address newImplementation, bytes memory data) public 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();
                          error UpgradeToMismatchedContractName(string expected, string actual);
                          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 "@zoralabs/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC165Upgradeable.sol";
                      import {IERC1155MetadataURIUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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 ProtocolRewardsWithdrawFailed(address caller, address recipient, uint256 amount);
                          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 "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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 "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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.4.0";
                          }
                      }
                      // SPDX-License-Identifier: MIT
                      // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
                      pragma solidity ^0.8.1;
                      error ADDRESS_INSUFFICIENT_BALANCE();
                      error ADDRESS_UNABLE_TO_SEND_VALUE();
                      error ADDRESS_LOW_LEVEL_CALL_FAILED();
                      error ADDRESS_LOW_LEVEL_CALL_WITH_VALUE_FAILED();
                      error ADDRESS_INSUFFICIENT_BALANCE_FOR_CALL();
                      error ADDRESS_LOW_LEVEL_STATIC_CALL_FAILED();
                      error ADDRESS_CALL_TO_NON_CONTRACT();
                      /**
                       * @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
                           *
                           * Furthermore, `isContract` will also return true if the target contract within
                           * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
                           * which only has an effect at the end of a transaction.
                           * ====
                           *
                           * [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://consensys.net/diligence/blog/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 {
                              if (address(this).balance > amount) {
                                  revert ADDRESS_INSUFFICIENT_BALANCE();
                              }
                              (bool success, ) = recipient.call{value: amount}("");
                              if (!success) {
                                  revert ADDRESS_UNABLE_TO_SEND_VALUE();
                              }
                          }
                          /**
                           * @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);
                          }
                          /**
                           * @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) {
                              if (address(this).balance < value) {
                                  revert ADDRESS_INSUFFICIENT_BALANCE();
                              }
                              (bool success, bytes memory returndata) = target.call{value: value}(data);
                              return verifyCallResultFromTarget(target, success, returndata);
                          }
                          /**
                           * @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) {
                              (bool success, bytes memory returndata) = target.staticcall(data);
                              return verifyCallResultFromTarget(target, success, returndata);
                          }
                          /**
                           * @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
                          ) 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
                                      if (!isContract(target)) {
                                          revert ADDRESS_CALL_TO_NON_CONTRACT();
                                      }
                                  }
                                  return returndata;
                              } else {
                                  _revert(returndata);
                              }
                          }
                          /**
                           * @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
                          ) internal pure returns (bytes memory) {
                              if (success) {
                                  return returndata;
                              } else {
                                  _revert(returndata);
                              }
                          }
                          function _revert(bytes memory returndata) 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 ADDRESS_LOW_LEVEL_CALL_FAILED();
                              }
                          }
                      }
                      // 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";
                      error ERC1967_NEW_IMPL_NOT_CONTRACT();
                      error ERC1967_UNSUPPORTED_PROXIABLEUUID();
                      error ERC1967_NEW_IMPL_NOT_UUPS();
                      error ERC1967_NEW_ADMIN_IS_ZERO_ADDRESS();
                      error ERC1967_NEW_BEACON_IS_NOT_CONTRACT();
                      error ERC1967_BEACON_IMPL_IS_NOT_CONTRACT();
                      error ADDRESS_DELEGATECALL_TO_NON_CONTRACT();
                      /**
                       * @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._
                       */
                      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 {
                              if (!AddressUpgradeable.isContract(newImplementation)) {
                                  revert ERC1967_NEW_IMPL_NOT_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) {
                                      if (slot != _IMPLEMENTATION_SLOT) {
                                          revert ERC1967_UNSUPPORTED_PROXIABLEUUID();
                                      }
                                  } catch {
                                      revert ERC1967_NEW_IMPL_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 {
                              if (newAdmin == address(0)) {
                                  revert ERC1967_NEW_ADMIN_IS_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 {
                              if (!AddressUpgradeable.isContract(newBeacon)) {
                                  revert ERC1967_NEW_BEACON_IS_NOT_CONTRACT();
                              }
                              if (!AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation())) {
                                  revert ERC1967_BEACON_IMPL_IS_NOT_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) {
                              if (!AddressUpgradeable.isContract(target)) {
                                  revert ADDRESS_DELEGATECALL_TO_NON_CONTRACT();
                              }
                              // solhint-disable-next-line avoid-low-level-calls
                              (bool success, bytes memory returndata) = target.delegatecall(data);
                              return AddressUpgradeable.verifyCallResult(success, returndata);
                          }
                          /**
                           * @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 "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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.9.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)
                      // This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
                      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:
                       * ```solidity
                       * 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`, `uint256`._
                       * _Available since v4.9 for `string`, `bytes`._
                       */
                      library StorageSlotUpgradeable {
                          struct AddressSlot {
                              address value;
                          }
                          struct BooleanSlot {
                              bool value;
                          }
                          struct Bytes32Slot {
                              bytes32 value;
                          }
                          struct Uint256Slot {
                              uint256 value;
                          }
                          struct StringSlot {
                              string value;
                          }
                          struct BytesSlot {
                              bytes 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
                              }
                          }
                          /**
                           * @dev Returns an `StringSlot` with member `value` located at `slot`.
                           */
                          function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
                              /// @solidity memory-safe-assembly
                              assembly {
                                  r.slot := slot
                              }
                          }
                          /**
                           * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
                           */
                          function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
                              /// @solidity memory-safe-assembly
                              assembly {
                                  r.slot := store.slot
                              }
                          }
                          /**
                           * @dev Returns an `BytesSlot` with member `value` located at `slot`.
                           */
                          function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
                              /// @solidity memory-safe-assembly
                              assembly {
                                  r.slot := slot
                              }
                          }
                          /**
                           * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
                           */
                          function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
                              /// @solidity memory-safe-assembly
                              assembly {
                                  r.slot := store.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 "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
                      pragma solidity ^0.8.2;
                      import "../beacon/IBeacon.sol";
                      import "../../interfaces/IERC1967.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._
                       */
                      abstract contract ERC1967Upgrade is IERC1967 {
                          // 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 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 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 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.9.0) (interfaces/IERC1967.sol)
                      pragma solidity ^0.8.0;
                      /**
                       * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
                       *
                       * _Available since v4.8.3._
                       */
                      interface IERC1967 {
                          /**
                           * @dev Emitted when the implementation is upgraded.
                           */
                          event Upgraded(address indexed implementation);
                          /**
                           * @dev Emitted when the admin account has changed.
                           */
                          event AdminChanged(address previousAdmin, address newAdmin);
                          /**
                           * @dev Emitted when the beacon is changed.
                           */
                          event BeaconUpgraded(address indexed beacon);
                      }
                      // 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.9.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
                           *
                           * Furthermore, `isContract` will also return true if the target contract within
                           * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
                           * which only has an effect at the end of a transaction.
                           * ====
                           *
                           * [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://consensys.net/diligence/blog/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.8.0/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.9.0) (utils/StorageSlot.sol)
                      // This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
                      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:
                       * ```solidity
                       * 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`, `uint256`._
                       * _Available since v4.9 for `string`, `bytes`._
                       */
                      library StorageSlot {
                          struct AddressSlot {
                              address value;
                          }
                          struct BooleanSlot {
                              bool value;
                          }
                          struct Bytes32Slot {
                              bytes32 value;
                          }
                          struct Uint256Slot {
                              uint256 value;
                          }
                          struct StringSlot {
                              string value;
                          }
                          struct BytesSlot {
                              bytes 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
                              }
                          }
                          /**
                           * @dev Returns an `StringSlot` with member `value` located at `slot`.
                           */
                          function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
                              /// @solidity memory-safe-assembly
                              assembly {
                                  r.slot := slot
                              }
                          }
                          /**
                           * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
                           */
                          function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
                              /// @solidity memory-safe-assembly
                              assembly {
                                  r.slot := store.slot
                              }
                          }
                          /**
                           * @dev Returns an `BytesSlot` with member `value` located at `slot`.
                           */
                          function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
                              /// @solidity memory-safe-assembly
                              assembly {
                                  r.slot := slot
                              }
                          }
                          /**
                           * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
                           */
                          function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
                              /// @solidity memory-safe-assembly
                              assembly {
                                  r.slot := store.slot
                              }
                          }
                      }
                      

                      File 4 of 4: ZoraCreator1155Impl
                      // SPDX-License-Identifier: MIT
                      pragma solidity 0.8.17;
                      import {ERC1155Upgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol";
                      import {ReentrancyGuardUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol";
                      import {UUPSUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol";
                      import {IERC1155MetadataURIUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC1155MetadataURIUpgradeable.sol";
                      import {IERC165Upgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC165Upgradeable.sol";
                      import {IProtocolRewards} from "@zoralabs/protocol-rewards/dist/contracts/interfaces/IProtocolRewards.sol";
                      import {ERC1155Rewards} from "@zoralabs/protocol-rewards/dist/contracts/abstract/ERC1155/ERC1155Rewards.sol";
                      import {ERC1155RewardsStorageV1} from "@zoralabs/protocol-rewards/dist/contracts/abstract/ERC1155/ERC1155RewardsStorageV1.sol";
                      import {IZoraCreator1155} from "../interfaces/IZoraCreator1155.sol";
                      import {IZoraCreator1155Initializer} from "../interfaces/IZoraCreator1155Initializer.sol";
                      import {ReentrancyGuardUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol";
                      import {UUPSUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol";
                      import {MathUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/utils/math/MathUpgradeable.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,
                          ERC1155Rewards,
                          ERC1155RewardsStorageV1
                      {
                          /// @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,
                              address _protocolRewards
                          ) MintFeeManager(_mintFeeAmount, _mintFeeRecipient) ERC1155Rewards(_protocolRewards, _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 | role))) {
                                  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 calldata newURI,
                              uint256 maxSupply
                          ) public onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_MINTER) nonReentrant returns (uint256) {
                              uint256 tokenId = _setupNewTokenAndPermission(newURI, maxSupply, msg.sender, PERMISSION_BIT_ADMIN);
                              return tokenId;
                          }
                          /// @notice Set up a new token with a create referral
                          /// @param newURI The URI for the token
                          /// @param maxSupply The maximum supply of the token
                          /// @param createReferral The address of the create referral
                          function setupNewTokenWithCreateReferral(
                              string calldata newURI,
                              uint256 maxSupply,
                              address createReferral
                          ) public onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_MINTER) nonReentrant returns (uint256) {
                              uint256 tokenId = _setupNewTokenAndPermission(newURI, maxSupply, msg.sender, PERMISSION_BIT_ADMIN);
                              _setCreateReferral(tokenId, createReferral);
                              return tokenId;
                          }
                          function _setupNewTokenAndPermission(string calldata newURI, uint256 maxSupply, address user, uint256 permission) internal returns (uint256) {
                              uint256 tokenId = _setupNewToken(newURI, maxSupply);
                              _addPermission(tokenId, user, permission);
                              if (bytes(newURI).length > 0) {
                                  emit URI(newURI, tokenId);
                              }
                              emit SetupNewToken(tokenId, user, 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 Get the creator reward recipient address
                          /// @dev The creator is not enforced to set a funds recipient address, so in that case the reward would be claimable by creator's contract
                          function getCreatorRewardRecipient() public view returns (address payable) {
                              return config.fundsRecipient != address(0) ? config.fundsRecipient : payable(address(this));
                          }
                          /// @notice Mint tokens and payout rewards given a minter contract, minter arguments, a finder, and a origin
                          /// @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
                          /// @param mintReferral The referrer of the mint
                          function mintWithRewards(
                              IMinter1155 minter,
                              uint256 tokenId,
                              uint256 quantity,
                              bytes calldata minterArguments,
                              address mintReferral
                          ) external payable nonReentrant {
                              // Require admin from the minter to mint
                              _requireAdminOrRole(address(minter), tokenId, PERMISSION_BIT_MINTER);
                              // Get value sent and handle mint rewards
                              uint256 ethValueSent = _handleRewardsAndGetValueSent(msg.value, quantity, getCreatorRewardRecipient(), createReferrals[tokenId], mintReferral);
                              // 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;
                              }
                              uint256 maxSupply = tokens[tokenId].maxSupply;
                              uint256 totalMinted = tokens[tokenId].totalMinted;
                              totalRoyaltyMints = (mintAmount + (totalMinted % royaltyMintSchedule)) / (royaltyMintSchedule - 1);
                              totalRoyaltyMints = MathUpgradeable.min(totalRoyaltyMints, maxSupply - (mintAmount + totalMinted));
                              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 _beforeBatchTokenTransfer(
                              address operator,
                              address from,
                              address to,
                              uint256[] memory ids,
                              uint256[] memory amounts,
                              bytes memory data
                          ) internal override {
                              super._beforeBatchTokenTransfer(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) {
                              _setFundsRecipient(fundsRecipient);
                          }
                          /// @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 Allows the create referral to update the address that can claim their rewards
                          function updateCreateReferral(uint256 tokenId, address recipient) external {
                              if (msg.sender != createReferrals[tokenId]) revert ONLY_CREATE_REFERRAL();
                              _setCreateReferral(tokenId, recipient);
                          }
                          function _setCreateReferral(uint256 tokenId, address recipient) internal {
                              createReferrals[tokenId] = recipient;
                          }
                          /// @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);
                              }
                          }
                          /// @notice Withdraws ETH from the Zora Rewards contract
                          function withdrawRewards(address to, uint256 amount) public onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_FUNDS_MANAGER) {
                              bytes memory data = abi.encodeWithSelector(IProtocolRewards.withdraw.selector, to, amount);
                              (bool success, ) = address(protocolRewards).call(data);
                              if (!success) {
                                  revert ProtocolRewardsWithdrawFailed(msg.sender, to, amount);
                              }
                          }
                          ///                                                          ///
                          ///                         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
                      // Modifications from OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/ERC1155.sol):
                      // - Revert strings replaced with custom errors
                      // - Decoupled hooks 
                      //   - `_beforeTokenTransfer` --> `_beforeTokenTransfer` & `_beforeBatchTokenTransfer`
                      //   - `_afterTokenTransfer` --> `_afterTokenTransfer` & `_afterBatchTokenTransfer`
                      // - Minor gas optimizations (eg. array length caching, unchecked loop iteration)
                      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";
                      error ERC1155_ADDRESS_ZERO_IS_NOT_A_VALID_OWNER();
                      error ERC1155_ACCOUNTS_AND_IDS_LENGTH_MISMATCH();
                      error ERC1155_IDS_AND_AMOUNTS_LENGTH_MISMATCH();
                      error ERC1155_CALLER_IS_NOT_TOKEN_OWNER_OR_APPROVED();
                      error ERC1155_TRANSFER_TO_ZERO_ADDRESS();
                      error ERC1155_INSUFFICIENT_BALANCE_FOR_TRANSFER();
                      error ERC1155_MINT_TO_ZERO_ADDRESS();
                      error ERC1155_BURN_FROM_ZERO_ADDRESS();
                      error ERC1155_BURN_AMOUNT_EXCEEDS_BALANCE();
                      error ERC1155_SETTING_APPROVAL_FOR_SELF();
                      error ERC1155_ERC1155RECEIVER_REJECTED_TOKENS();
                      error ERC1155_TRANSFER_TO_NON_ERC1155RECEIVER_IMPLEMENTER();
                      /**
                       * @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) {
                              if (account == address(0)) {
                                  revert 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 batchBalances) {
                              uint256 numAccounts = accounts.length;
                              if (numAccounts != ids.length) {
                                  revert ERC1155_ACCOUNTS_AND_IDS_LENGTH_MISMATCH();
                              }
                              batchBalances = new uint256[](numAccounts);
                              unchecked {
                                  for (uint256 i; i < numAccounts; ++i) {
                                      batchBalances[i] = balanceOf(accounts[i], ids[i]);
                                  }
                              }
                          }
                          /**
                           * @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 {
                              if (from != _msgSender() && !isApprovedForAll(from, _msgSender())) {
                                  revert 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 {
                              if (from != _msgSender() && !isApprovedForAll(from, _msgSender())) {
                                  revert 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 {
                              if (to == address(0)) {
                                  revert ERC1155_TRANSFER_TO_ZERO_ADDRESS();
                              }
                              address operator = _msgSender();
                              _beforeTokenTransfer(operator, from, to, id, amount, data);
                              uint256 fromBalance = _balances[id][from];
                              if (fromBalance < amount) {
                                  revert 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, id, amount, 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 {
                              uint256 numIds = ids.length;
                              if (numIds != amounts.length) {
                                  revert ERC1155_ACCOUNTS_AND_IDS_LENGTH_MISMATCH();
                              }
                              if (to == address(0)) {
                                  revert ERC1155_TRANSFER_TO_ZERO_ADDRESS();
                              }
                              address operator = _msgSender();
                              _beforeBatchTokenTransfer(operator, from, to, ids, amounts, data);
                              uint256 id;
                              uint256 amount;
                              uint256 fromBalance;
                              for (uint256 i; i < numIds; ) {
                                  id = ids[i];
                                  amount = amounts[i];
                                  fromBalance = _balances[id][from];
                                  if (fromBalance < amount) {
                                      revert ERC1155_INSUFFICIENT_BALANCE_FOR_TRANSFER();
                                  }
                                  _balances[id][to] += amount;
                                  unchecked {
                                      _balances[id][from] = fromBalance - amount;
                                      ++i;
                                  }
                              }
                              emit TransferBatch(operator, from, to, ids, amounts);
                              _afterBatchTokenTransfer(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 {
                              if (to == address(0)) {
                                  revert ERC1155_MINT_TO_ZERO_ADDRESS();
                              }
                              address operator = _msgSender();
                              _beforeTokenTransfer(operator, address(0), to, id, amount, data);
                              _balances[id][to] += amount;
                              emit TransferSingle(operator, address(0), to, id, amount);
                              _afterTokenTransfer(operator, address(0), to, id, amount, 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 {
                              if (to == address(0)) {
                                  revert ERC1155_MINT_TO_ZERO_ADDRESS();
                              }
                              uint256 numIds = ids.length;
                              if (numIds != amounts.length) {
                                  revert ERC1155_IDS_AND_AMOUNTS_LENGTH_MISMATCH();
                              }
                              address operator = _msgSender();
                              _beforeBatchTokenTransfer(operator, address(0), to, ids, amounts, data);
                              for (uint256 i; i < numIds; ) {
                                  _balances[ids[i]][to] += amounts[i];
                                  unchecked {
                                      ++i;
                                  }
                              }
                              emit TransferBatch(operator, address(0), to, ids, amounts);
                              _afterBatchTokenTransfer(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 {
                              if (from == address(0)) {
                                  revert ERC1155_BURN_FROM_ZERO_ADDRESS();
                              }
                              address operator = _msgSender();
                              _beforeTokenTransfer(operator, from, address(0), id, amount, "");
                              uint256 fromBalance = _balances[id][from];
                              if (fromBalance < amount) {
                                  revert ERC1155_BURN_AMOUNT_EXCEEDS_BALANCE();
                              }
                              unchecked {
                                  _balances[id][from] = fromBalance - amount;
                              }
                              emit TransferSingle(operator, from, address(0), id, amount);
                              _afterTokenTransfer(operator, from, address(0), id, amount, "");
                          }
                          /**
                           * @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 {
                              if (from == address(0)) {
                                  revert ERC1155_BURN_FROM_ZERO_ADDRESS();
                              }
                              uint256 numIds = ids.length;
                              if (numIds != amounts.length) {
                                  revert ERC1155_IDS_AND_AMOUNTS_LENGTH_MISMATCH();
                              }
                              address operator = _msgSender();
                              _beforeBatchTokenTransfer(operator, from, address(0), ids, amounts, "");
                              uint256 id;
                              uint256 amount;
                              uint256 fromBalance;
                              for (uint256 i; i < numIds; ) {
                                  id = ids[i];
                                  amount = amounts[i];
                                  fromBalance = _balances[id][from];
                                  if (fromBalance < amount) {
                                      revert ERC1155_BURN_AMOUNT_EXCEEDS_BALANCE();
                                  }
                                  unchecked {
                                      _balances[id][from] = fromBalance - amount;
                                      ++i;
                                  }
                              }
                              emit TransferBatch(operator, from, address(0), ids, amounts);
                              _afterBatchTokenTransfer(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 {
                              if (owner == operator) {
                                  revert ERC1155_SETTING_APPROVAL_FOR_SELF();
                              }
                              _operatorApprovals[owner][operator] = approved;
                              emit ApprovalForAll(owner, operator, approved);
                          }
                          /**
                           * @dev Hook that is called before a single token transfer.
                           */
                          function _beforeTokenTransfer(
                              address operator,
                              address from,
                              address to,
                              uint256 id,
                              uint256 amount,
                              bytes memory data
                          ) internal virtual { }
                          /**
                           * @dev Hook that is called before a batch token transfer.
                           */
                          function _beforeBatchTokenTransfer(
                              address operator,
                              address from,
                              address to,
                              uint256[] memory ids,
                              uint256[] memory amounts,
                              bytes memory data
                          ) internal virtual {}
                          /**
                           * @dev Hook that is called after a single token transfer.
                           */
                          function _afterTokenTransfer(
                              address operator,
                              address from,
                              address to,
                              uint256 id,
                              uint256 amount,
                              bytes memory data
                          ) internal virtual {}
                          /**
                           * @dev Hook that is called after a batch token transfer.
                           */
                          function _afterBatchTokenTransfer(
                              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();
                                  }
                              }
                          }
                          /**
                           * @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 (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 Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
                           * `nonReentrant` function in the call stack.
                           */
                          function _reentrancyGuardEntered() internal view returns (bool) {
                              return _status == _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";
                      error FUNCTION_MUST_BE_CALLED_THROUGH_DELEGATECALL();
                      error FUNCTION_MUST_BE_CALLED_THROUGH_ACTIVE_PROXY();
                      error UUPS_UPGRADEABLE_MUST_NOT_BE_CALLED_THROUGH_DELEGATECALL();
                      /**
                       * @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() {
                              if (address(this) == __self) {
                                  revert FUNCTION_MUST_BE_CALLED_THROUGH_DELEGATECALL();
                              }
                              if (_getImplementation() != __self) {
                                  revert 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() {
                              if (address(this) != __self) {
                                  revert UUPS_UPGRADEABLE_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.
                           *
                           * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
                           */
                          function upgradeTo(address newImplementation) public 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.
                           *
                           * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
                           */
                          function upgradeToAndCall(address newImplementation, bytes memory data) public 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
                      // 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;
                      /// @title IProtocolRewards
                      /// @notice The interface for deposits & withdrawals of protocol rewards
                      interface IProtocolRewards {
                          event RewardsDeposit(
                              address indexed creator,
                              address indexed createReferral,
                              address indexed mintReferral,
                              address firstMinter,
                              address zora,
                              address from,
                              uint256 creatorReward,
                              uint256 createReferralReward,
                              uint256 mintReferralReward,
                              uint256 firstMinterReward,
                              uint256 zoraReward
                          );
                          event Deposit(address indexed from, address indexed to, uint256 amount, string comment);
                          event Withdraw(address indexed from, address indexed to, uint256 amount);
                          error ADDRESS_ZERO();
                          error ARRAY_LENGTH_MISMATCH();
                          error INVALID_DEPOSIT();
                          error INVALID_SIGNATURE();
                          error INVALID_WITHDRAW();
                          error SIGNATURE_DEADLINE_EXPIRED();
                          error TRANSFER_FAILED();
                          function deposit(address to, string calldata comment) external payable;
                          function depositBatch(address[] calldata recipients, uint256[] calldata amounts, string calldata comment) external payable;
                          function depositRewards(
                              address creator,
                              uint256 creatorReward,
                              address createReferral,
                              uint256 createReferralReward,
                              address mintReferral,
                              uint256 mintReferralReward,
                              address firstMinter,
                              uint256 firstMinterReward,
                              address zora,
                              uint256 zoraReward
                          ) external payable;
                          function withdraw(address to, uint256 amount) external;
                          function withdrawWithSig(address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
                      }
                      // SPDX-License-Identifier: MIT
                      pragma solidity 0.8.17;
                      import {RewardSplits} from "../RewardSplits.sol";
                      /// @notice The base logic for handling Zora ERC-1155 protocol rewards
                      /// @dev Used in https://github.com/ourzora/zora-1155-contracts/blob/main/src/nft/ZoraCreator1155Impl.sol
                      abstract contract ERC1155Rewards is RewardSplits {
                          constructor(address _protocolRewards, address _zoraRewardRecipient) payable RewardSplits(_protocolRewards, _zoraRewardRecipient) {}
                          function _handleRewardsAndGetValueSent(
                              uint256 msgValue,
                              uint256 numTokens,
                              address creator,
                              address createReferral,
                              address mintReferral
                          ) internal returns (uint256) {
                              uint256 totalReward = computeTotalReward(numTokens);
                              if (msgValue < totalReward) {
                                  revert INVALID_ETH_AMOUNT();
                              } else if (msgValue == totalReward) {
                                  _depositFreeMintRewards(totalReward, numTokens, creator, createReferral, mintReferral);
                                  return 0;
                              } else {
                                  _depositPaidMintRewards(totalReward, numTokens, creator, createReferral, mintReferral);
                                  unchecked {
                                      return msgValue - totalReward;
                                  }
                              }
                          }
                      }
                      // SPDX-License-Identifier: MIT
                      pragma solidity 0.8.17;
                      contract ERC1155RewardsStorageV1 {
                          mapping(uint256 => address) public createReferrals;
                      }
                      // SPDX-License-Identifier: MIT
                      pragma solidity 0.8.17;
                      import {IERC165Upgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC165Upgradeable.sol";
                      import {IERC1155MetadataURIUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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 ProtocolRewardsWithdrawFailed(address caller, address recipient, uint256 amount);
                          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) (utils/math/Math.sol)
                      pragma solidity ^0.8.0;
                      /**
                       * @dev Standard math utilities missing in the Solidity language.
                       */
                      library MathUpgradeable {
                          enum Rounding {
                              Down, // Toward negative infinity
                              Up, // Toward infinity
                              Zero // Toward zero
                          }
                          /**
                           * @dev Returns the largest of two numbers.
                           */
                          function max(uint256 a, uint256 b) internal pure returns (uint256) {
                              return a > b ? a : b;
                          }
                          /**
                           * @dev Returns the smallest of two numbers.
                           */
                          function min(uint256 a, uint256 b) internal pure returns (uint256) {
                              return a < b ? a : b;
                          }
                          /**
                           * @dev Returns the average of two numbers. The result is rounded towards
                           * zero.
                           */
                          function average(uint256 a, uint256 b) internal pure returns (uint256) {
                              // (a + b) / 2 can overflow.
                              return (a & b) + (a ^ b) / 2;
                          }
                          /**
                           * @dev Returns the ceiling of the division of two numbers.
                           *
                           * This differs from standard division with `/` in that it rounds up instead
                           * of rounding down.
                           */
                          function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
                              // (a + b - 1) / b can overflow on addition, so we distribute.
                              return a == 0 ? 0 : (a - 1) / b + 1;
                          }
                          /**
                           * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
                           * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
                           * with further edits by Uniswap Labs also under MIT license.
                           */
                          function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
                              unchecked {
                                  // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
                                  // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
                                  // variables such that product = prod1 * 2^256 + prod0.
                                  uint256 prod0; // Least significant 256 bits of the product
                                  uint256 prod1; // Most significant 256 bits of the product
                                  assembly {
                                      let mm := mulmod(x, y, not(0))
                                      prod0 := mul(x, y)
                                      prod1 := sub(sub(mm, prod0), lt(mm, prod0))
                                  }
                                  // Handle non-overflow cases, 256 by 256 division.
                                  if (prod1 == 0) {
                                      return prod0 / denominator;
                                  }
                                  // Make sure the result is less than 2^256. Also prevents denominator == 0.
                                  require(denominator > prod1, "Math: mulDiv overflow");
                                  ///////////////////////////////////////////////
                                  // 512 by 256 division.
                                  ///////////////////////////////////////////////
                                  // Make division exact by subtracting the remainder from [prod1 prod0].
                                  uint256 remainder;
                                  assembly {
                                      // Compute remainder using mulmod.
                                      remainder := mulmod(x, y, denominator)
                                      // Subtract 256 bit number from 512 bit number.
                                      prod1 := sub(prod1, gt(remainder, prod0))
                                      prod0 := sub(prod0, remainder)
                                  }
                                  // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
                                  // See https://cs.stackexchange.com/q/138556/92363.
                                  // Does not overflow because the denominator cannot be zero at this stage in the function.
                                  uint256 twos = denominator & (~denominator + 1);
                                  assembly {
                                      // Divide denominator by twos.
                                      denominator := div(denominator, twos)
                                      // Divide [prod1 prod0] by twos.
                                      prod0 := div(prod0, twos)
                                      // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                                      twos := add(div(sub(0, twos), twos), 1)
                                  }
                                  // Shift in bits from prod1 into prod0.
                                  prod0 |= prod1 * twos;
                                  // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
                                  // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
                                  // four bits. That is, denominator * inv = 1 mod 2^4.
                                  uint256 inverse = (3 * denominator) ^ 2;
                                  // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
                                  // in modular arithmetic, doubling the correct bits in each step.
                                  inverse *= 2 - denominator * inverse; // inverse mod 2^8
                                  inverse *= 2 - denominator * inverse; // inverse mod 2^16
                                  inverse *= 2 - denominator * inverse; // inverse mod 2^32
                                  inverse *= 2 - denominator * inverse; // inverse mod 2^64
                                  inverse *= 2 - denominator * inverse; // inverse mod 2^128
                                  inverse *= 2 - denominator * inverse; // inverse mod 2^256
                                  // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
                                  // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
                                  // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
                                  // is no longer required.
                                  result = prod0 * inverse;
                                  return result;
                              }
                          }
                          /**
                           * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
                           */
                          function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
                              uint256 result = mulDiv(x, y, denominator);
                              if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
                                  result += 1;
                              }
                              return result;
                          }
                          /**
                           * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
                           *
                           * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
                           */
                          function sqrt(uint256 a) internal pure returns (uint256) {
                              if (a == 0) {
                                  return 0;
                              }
                              // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
                              //
                              // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
                              // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
                              //
                              // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
                              // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
                              // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
                              //
                              // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
                              uint256 result = 1 << (log2(a) >> 1);
                              // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
                              // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
                              // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
                              // into the expected uint128 result.
                              unchecked {
                                  result = (result + a / result) >> 1;
                                  result = (result + a / result) >> 1;
                                  result = (result + a / result) >> 1;
                                  result = (result + a / result) >> 1;
                                  result = (result + a / result) >> 1;
                                  result = (result + a / result) >> 1;
                                  result = (result + a / result) >> 1;
                                  return min(result, a / result);
                              }
                          }
                          /**
                           * @notice Calculates sqrt(a), following the selected rounding direction.
                           */
                          function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
                              unchecked {
                                  uint256 result = sqrt(a);
                                  return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
                              }
                          }
                          /**
                           * @dev Return the log in base 2, rounded down, of a positive value.
                           * Returns 0 if given 0.
                           */
                          function log2(uint256 value) internal pure returns (uint256) {
                              uint256 result = 0;
                              unchecked {
                                  if (value >> 128 > 0) {
                                      value >>= 128;
                                      result += 128;
                                  }
                                  if (value >> 64 > 0) {
                                      value >>= 64;
                                      result += 64;
                                  }
                                  if (value >> 32 > 0) {
                                      value >>= 32;
                                      result += 32;
                                  }
                                  if (value >> 16 > 0) {
                                      value >>= 16;
                                      result += 16;
                                  }
                                  if (value >> 8 > 0) {
                                      value >>= 8;
                                      result += 8;
                                  }
                                  if (value >> 4 > 0) {
                                      value >>= 4;
                                      result += 4;
                                  }
                                  if (value >> 2 > 0) {
                                      value >>= 2;
                                      result += 2;
                                  }
                                  if (value >> 1 > 0) {
                                      result += 1;
                                  }
                              }
                              return result;
                          }
                          /**
                           * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
                           * Returns 0 if given 0.
                           */
                          function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
                              unchecked {
                                  uint256 result = log2(value);
                                  return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
                              }
                          }
                          /**
                           * @dev Return the log in base 10, rounded down, of a positive value.
                           * Returns 0 if given 0.
                           */
                          function log10(uint256 value) internal pure returns (uint256) {
                              uint256 result = 0;
                              unchecked {
                                  if (value >= 10 ** 64) {
                                      value /= 10 ** 64;
                                      result += 64;
                                  }
                                  if (value >= 10 ** 32) {
                                      value /= 10 ** 32;
                                      result += 32;
                                  }
                                  if (value >= 10 ** 16) {
                                      value /= 10 ** 16;
                                      result += 16;
                                  }
                                  if (value >= 10 ** 8) {
                                      value /= 10 ** 8;
                                      result += 8;
                                  }
                                  if (value >= 10 ** 4) {
                                      value /= 10 ** 4;
                                      result += 4;
                                  }
                                  if (value >= 10 ** 2) {
                                      value /= 10 ** 2;
                                      result += 2;
                                  }
                                  if (value >= 10 ** 1) {
                                      result += 1;
                                  }
                              }
                              return result;
                          }
                          /**
                           * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
                           * Returns 0 if given 0.
                           */
                          function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
                              unchecked {
                                  uint256 result = log10(value);
                                  return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
                              }
                          }
                          /**
                           * @dev Return the log in base 256, rounded down, of a positive value.
                           * Returns 0 if given 0.
                           *
                           * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
                           */
                          function log256(uint256 value) internal pure returns (uint256) {
                              uint256 result = 0;
                              unchecked {
                                  if (value >> 128 > 0) {
                                      value >>= 128;
                                      result += 16;
                                  }
                                  if (value >> 64 > 0) {
                                      value >>= 64;
                                      result += 8;
                                  }
                                  if (value >> 32 > 0) {
                                      value >>= 32;
                                      result += 4;
                                  }
                                  if (value >> 16 > 0) {
                                      value >>= 16;
                                      result += 2;
                                  }
                                  if (value >> 8 > 0) {
                                      result += 1;
                                  }
                              }
                              return result;
                          }
                          /**
                           * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
                           * Returns 0 if given 0.
                           */
                          function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
                              unchecked {
                                  uint256 result = log256(value);
                                  return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
                              }
                          }
                      }
                      // 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.4.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 "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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 "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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 "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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;
                      error ADDRESS_INSUFFICIENT_BALANCE();
                      error ADDRESS_UNABLE_TO_SEND_VALUE();
                      error ADDRESS_LOW_LEVEL_CALL_FAILED();
                      error ADDRESS_LOW_LEVEL_CALL_WITH_VALUE_FAILED();
                      error ADDRESS_INSUFFICIENT_BALANCE_FOR_CALL();
                      error ADDRESS_LOW_LEVEL_STATIC_CALL_FAILED();
                      error ADDRESS_CALL_TO_NON_CONTRACT();
                      /**
                       * @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
                           *
                           * Furthermore, `isContract` will also return true if the target contract within
                           * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
                           * which only has an effect at the end of a transaction.
                           * ====
                           *
                           * [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://consensys.net/diligence/blog/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 {
                              if (address(this).balance > amount) {
                                  revert ADDRESS_INSUFFICIENT_BALANCE();
                              }
                              (bool success, ) = recipient.call{value: amount}("");
                              if (!success) {
                                  revert ADDRESS_UNABLE_TO_SEND_VALUE();
                              }
                          }
                          /**
                           * @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);
                          }
                          /**
                           * @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) {
                              if (address(this).balance < value) {
                                  revert ADDRESS_INSUFFICIENT_BALANCE();
                              }
                              (bool success, bytes memory returndata) = target.call{value: value}(data);
                              return verifyCallResultFromTarget(target, success, returndata);
                          }
                          /**
                           * @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) {
                              (bool success, bytes memory returndata) = target.staticcall(data);
                              return verifyCallResultFromTarget(target, success, returndata);
                          }
                          /**
                           * @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
                          ) 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
                                      if (!isContract(target)) {
                                          revert ADDRESS_CALL_TO_NON_CONTRACT();
                                      }
                                  }
                                  return returndata;
                              } else {
                                  _revert(returndata);
                              }
                          }
                          /**
                           * @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
                          ) internal pure returns (bytes memory) {
                              if (success) {
                                  return returndata;
                              } else {
                                  _revert(returndata);
                              }
                          }
                          function _revert(bytes memory returndata) 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 ADDRESS_LOW_LEVEL_CALL_FAILED();
                              }
                          }
                      }
                      // 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.0) (proxy/utils/Initializable.sol)
                      pragma solidity ^0.8.2;
                      import "../../utils/AddressUpgradeable.sol";
                      error INITIALIZABLE_CONTRACT_ALREADY_INITIALIZED();
                      error INITIALIZABLE_CONTRACT_IS_NOT_INITIALIZING();
                      error INITIALIZABLE_CONTRACT_IS_INITIALIZING();
                      /**
                       * @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]
                       * ```solidity
                       * 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;
                              if ((!isTopLevelCall || _initialized != 0) && (AddressUpgradeable.isContract(address(this)) || _initialized != 1)) {
                                  revert INITIALIZABLE_CONTRACT_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) {
                              if (_initializing || _initialized >= version) {
                                  revert INITIALIZABLE_CONTRACT_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() {
                              if (!_initializing) {
                                  revert 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 {
                              if (_initializing) {
                                  revert 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.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";
                      error ERC1967_NEW_IMPL_NOT_CONTRACT();
                      error ERC1967_UNSUPPORTED_PROXIABLEUUID();
                      error ERC1967_NEW_IMPL_NOT_UUPS();
                      error ERC1967_NEW_ADMIN_IS_ZERO_ADDRESS();
                      error ERC1967_NEW_BEACON_IS_NOT_CONTRACT();
                      error ERC1967_BEACON_IMPL_IS_NOT_CONTRACT();
                      error ADDRESS_DELEGATECALL_TO_NON_CONTRACT();
                      /**
                       * @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._
                       */
                      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 {
                              if (!AddressUpgradeable.isContract(newImplementation)) {
                                  revert ERC1967_NEW_IMPL_NOT_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) {
                                      if (slot != _IMPLEMENTATION_SLOT) {
                                          revert ERC1967_UNSUPPORTED_PROXIABLEUUID();
                                      }
                                  } catch {
                                      revert ERC1967_NEW_IMPL_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 {
                              if (newAdmin == address(0)) {
                                  revert ERC1967_NEW_ADMIN_IS_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 {
                              if (!AddressUpgradeable.isContract(newBeacon)) {
                                  revert ERC1967_NEW_BEACON_IS_NOT_CONTRACT();
                              }
                              if (!AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation())) {
                                  revert ERC1967_BEACON_IMPL_IS_NOT_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) {
                              if (!AddressUpgradeable.isContract(target)) {
                                  revert ADDRESS_DELEGATECALL_TO_NON_CONTRACT();
                              }
                              // solhint-disable-next-line avoid-low-level-calls
                              (bool success, bytes memory returndata) = target.delegatecall(data);
                              return AddressUpgradeable.verifyCallResult(success, returndata);
                          }
                          /**
                           * @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/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 {IProtocolRewards} from "../interfaces/IProtocolRewards.sol";
                      struct RewardsSettings {
                          uint256 creatorReward;
                          uint256 createReferralReward;
                          uint256 mintReferralReward;
                          uint256 firstMinterReward;
                          uint256 zoraReward;
                      }
                      /// @notice Common logic for between Zora ERC-721 & ERC-1155 contracts for protocol reward splits & deposits
                      abstract contract RewardSplits {
                          error CREATOR_FUNDS_RECIPIENT_NOT_SET();
                          error INVALID_ADDRESS_ZERO();
                          error INVALID_ETH_AMOUNT();
                          error ONLY_CREATE_REFERRAL();
                          uint256 internal constant TOTAL_REWARD_PER_MINT = 0.000777 ether;
                          uint256 internal constant CREATOR_REWARD = 0.000333 ether;
                          uint256 internal constant FIRST_MINTER_REWARD = 0.000111 ether;
                          uint256 internal constant CREATE_REFERRAL_FREE_MINT_REWARD = 0.000111 ether;
                          uint256 internal constant MINT_REFERRAL_FREE_MINT_REWARD = 0.000111 ether;
                          uint256 internal constant ZORA_FREE_MINT_REWARD = 0.000111 ether;
                          uint256 internal constant MINT_REFERRAL_PAID_MINT_REWARD = 0.000222 ether;
                          uint256 internal constant CREATE_REFERRAL_PAID_MINT_REWARD = 0.000222 ether;
                          uint256 internal constant ZORA_PAID_MINT_REWARD = 0.000222 ether;
                          address internal immutable zoraRewardRecipient;
                          IProtocolRewards internal immutable protocolRewards;
                          constructor(address _protocolRewards, address _zoraRewardRecipient) payable {
                              if (_protocolRewards == address(0) || _zoraRewardRecipient == address(0)) {
                                  revert INVALID_ADDRESS_ZERO();
                              }
                              protocolRewards = IProtocolRewards(_protocolRewards);
                              zoraRewardRecipient = _zoraRewardRecipient;
                          }
                          function computeTotalReward(uint256 numTokens) public pure returns (uint256) {
                              return numTokens * TOTAL_REWARD_PER_MINT;
                          }
                          function computeFreeMintRewards(uint256 numTokens) public pure returns (RewardsSettings memory) {
                              return
                                  RewardsSettings({
                                      creatorReward: numTokens * CREATOR_REWARD,
                                      createReferralReward: numTokens * CREATE_REFERRAL_FREE_MINT_REWARD,
                                      mintReferralReward: numTokens * MINT_REFERRAL_FREE_MINT_REWARD,
                                      firstMinterReward: numTokens * FIRST_MINTER_REWARD,
                                      zoraReward: numTokens * ZORA_FREE_MINT_REWARD
                                  });
                          }
                          function computePaidMintRewards(uint256 numTokens) public pure returns (RewardsSettings memory) {
                              return
                                  RewardsSettings({
                                      creatorReward: 0,
                                      createReferralReward: numTokens * CREATE_REFERRAL_PAID_MINT_REWARD,
                                      mintReferralReward: numTokens * MINT_REFERRAL_PAID_MINT_REWARD,
                                      firstMinterReward: numTokens * FIRST_MINTER_REWARD,
                                      zoraReward: numTokens * ZORA_PAID_MINT_REWARD
                                  });
                          }
                          function _depositFreeMintRewards(uint256 totalReward, uint256 numTokens, address creator, address createReferral, address mintReferral) internal {
                              RewardsSettings memory settings = computeFreeMintRewards(numTokens);
                              if (createReferral == address(0)) {
                                  createReferral = zoraRewardRecipient;
                              }
                              if (mintReferral == address(0)) {
                                  mintReferral = zoraRewardRecipient;
                              }
                              protocolRewards.depositRewards{value: totalReward}(
                                  creator,
                                  settings.creatorReward,
                                  createReferral,
                                  settings.createReferralReward,
                                  mintReferral,
                                  settings.mintReferralReward,
                                  creator,
                                  settings.firstMinterReward,
                                  zoraRewardRecipient,
                                  settings.zoraReward
                              );
                          }
                          function _depositPaidMintRewards(uint256 totalReward, uint256 numTokens, address creator, address createReferral, address mintReferral) internal {
                              RewardsSettings memory settings = computePaidMintRewards(numTokens);
                              if (createReferral == address(0)) {
                                  createReferral = zoraRewardRecipient;
                              }
                              if (mintReferral == address(0)) {
                                  mintReferral = zoraRewardRecipient;
                              }
                              protocolRewards.depositRewards{value: totalReward}(
                                  address(0),
                                  0,
                                  createReferral,
                                  settings.createReferralReward,
                                  mintReferral,
                                  settings.mintReferralReward,
                                  creator,
                                  settings.firstMinterReward,
                                  zoraRewardRecipient,
                                  settings.zoraReward
                              );
                          }
                      }
                      // 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
                      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.9.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.9.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
                           *
                           * Furthermore, `isContract` will also return true if the target contract within
                           * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
                           * which only has an effect at the end of a transaction.
                           * ====
                           *
                           * [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://consensys.net/diligence/blog/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.8.0/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)
                      // This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
                      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:
                       * ```solidity
                       * 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`, `uint256`._
                       * _Available since v4.9 for `string`, `bytes`._
                       */
                      library StorageSlotUpgradeable {
                          struct AddressSlot {
                              address value;
                          }
                          struct BooleanSlot {
                              bool value;
                          }
                          struct Bytes32Slot {
                              bytes32 value;
                          }
                          struct Uint256Slot {
                              uint256 value;
                          }
                          struct StringSlot {
                              string value;
                          }
                          struct BytesSlot {
                              bytes 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
                              }
                          }
                          /**
                           * @dev Returns an `StringSlot` with member `value` located at `slot`.
                           */
                          function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
                              /// @solidity memory-safe-assembly
                              assembly {
                                  r.slot := slot
                              }
                          }
                          /**
                           * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
                           */
                          function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
                              /// @solidity memory-safe-assembly
                              assembly {
                                  r.slot := store.slot
                              }
                          }
                          /**
                           * @dev Returns an `BytesSlot` with member `value` located at `slot`.
                           */
                          function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
                              /// @solidity memory-safe-assembly
                              assembly {
                                  r.slot := slot
                              }
                          }
                          /**
                           * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
                           */
                          function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
                              /// @solidity memory-safe-assembly
                              assembly {
                                  r.slot := store.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);
                      }