Transaction Hash:
Block:
20507091 at Aug-11-2024 06:14:47 PM +UTC
Transaction Fee:
0.00108216909432676 ETH
$2.83
Gas Used:
739,105 Gas / 1.464161512 Gwei
Emitted Events:
348 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b( 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b, 0x000000000000000000000000f62b0d56ba617f803df1c464c519ff7d29451b2f )
|
349 |
Zora1155Factory.0xa45800684f65ae010ceb4385eceaed88dec7f6a6bcbe11f7ffd8bd24dd2653f4( 0xa45800684f65ae010ceb4385eceaed88dec7f6a6bcbe11f7ffd8bd24dd2653f4, 0x000000000000000000000000aedc792d23ab8681f8c0154b2d57225095c7dbb3, 0x000000000000000000000000dc783b3cb88fdb2b01c61997746b655d7b54003e, 0x000000000000000000000000dc783b3cb88fdb2b01c61997746b655d7b54003e, 00000000000000000000000000000000000000000000000000000000000000a0, 0000000000000000000000000000000000000000000000000000000000000120, 0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000000000000000000000000000000000000000001f4, 000000000000000000000000dc783b3cb88fdb2b01c61997746b655d7b54003e, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b72656964776266766f6e3469687971637272367a6a, 32656874733773656c3466643662717373787478616373656e7a62616272616d, 716d000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000011, 44616e63696e67204d6f63617373696e73000000000000000000000000000000 )
|
350 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000dc783b3cb88fdb2b01c61997746b655d7b54003e, 0x0000000000000000000000000000000000000000000000000000000000000002 )
|
351 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe( 0x5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000060, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b72656964776266766f6e3469687971637272367a6a, 32656874733773656c3466643662717373787478616373656e7a62616272616d, 716d000000000000000000000000000000000000000000000000000000000000 )
|
352 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d( 0x5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000000000000000000000000000000000000000001f4, 000000000000000000000000dc783b3cb88fdb2b01c61997746b655d7b54003e )
|
353 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0( 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0, 0000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000dc783b3cb88fdb2b01c61997746b655d7b54003e )
|
354 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f( 0x3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000dc783b3cb88fdb2b01c61997746b655d7b54003e, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
|
355 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f( 0x3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000001, 000000000000000000000000dc783b3cb88fdb2b01c61997746b655d7b54003e, 0000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000dc783b3cb88fdb2b01c61997746b655d7b54003e, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
|
356 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000002 )
|
357 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe( 0x5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000060, ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b72656966326569747232656f71707662786b716c6e, 35637a6c6734757a33766636343234366934797435796a67626e627862616637, 3265000000000000000000000000000000000000000000000000000000000000 )
|
358 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000002 )
|
359 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b( 0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b, 0x0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b72656966326569747232656f71707662786b716c6e, 35637a6c6734757a33766636343234366934797435796a67626e627862616637, 3265000000000000000000000000000000000000000000000000000000000000 )
|
360 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc068( 0x1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc068, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0000000000000000000000000000000000000000000000000000000000000040, ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0000000000000000000000000000000000000000000000000000000000000042, 697066733a2f2f6261666b72656966326569747232656f71707662786b716c6e, 35637a6c6734757a33766636343234366934797435796a67626e627862616637, 3265000000000000000000000000000000000000000000000000000000000000 )
|
361 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d( 0x5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000000000000000000000000000000000000000001f4, 000000000000000000000000dc783b3cb88fdb2b01c61997746b655d7b54003e )
|
362 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x00000000000000000000000004e2516a2c207e84a1839755675dfd8ef6302f0a, 0x0000000000000000000000000000000000000000000000000000000000000004 )
|
363 |
ZoraCreatorFixedPriceSaleStrategy.SaleSet( mediaContract=0xaedc792d23ab8681f8c0154b2d57225095c7dbb3, tokenId=1, salesConfig=[{name:saleStart, type:uint64, order:1, indexed:false, value:1723399500, valueString:1723399500}, {name:saleEnd, type:uint64, order:2, indexed:false, value:18446744073709551615, valueString:18446744073709551615}, {name:maxTokensPerAddress, type:uint64, order:3, indexed:false, value:0, valueString:0}, {name:pricePerToken, type:uint96, order:4, indexed:false, value:15000000000000000, valueString:15000000000000000}, {name:fundsRecipient, type:address, order:5, indexed:false, value:0xDc783b3cb88Fdb2B01c61997746B655D7b54003e, valueString:0xDc783b3cb88Fdb2B01c61997746B655D7b54003e}] )
|
364 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca( 0x35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85, 0x0000000000000000000000000000000000000000000000000000000000000000 )
|
365 |
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498, 0000000000000000000000000000000000000000000000000000000000000001 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x04E2516A...eF6302F0a | |||||
0x4838B106...B0BAD5f97
Miner
| (Titan Builder) | 8.772756246750041411 Eth | 8.773206544974603786 Eth | 0.000450298224562375 | |
0xA6C5f2DE...91748cb85 | |||||
0xAedc792d...095c7dbB3 |
0 Eth
Nonce: 0
|
0 Eth
Nonce: 1
| |||
0xDc783b3c...D7b54003e |
0.014204400211053749 Eth
Nonce: 28
|
0.013122231116726989 Eth
Nonce: 29
| 0.00108216909432676 |
Execution Trace
Zora1155Factory.0582823a( )
ZoraCreator1155FactoryImpl.createContract( newContractURI=ipfs://bafkreidwbfvon4ihyqcrr6zj2ehts7sel4fd6bqssxtxacsenzbabramqm, name=Dancing Mocassins, 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:0xDc783b3cb88Fdb2B01c61997746B655D7b54003e, valueString:0xDc783b3cb88Fdb2B01c61997746B655D7b54003e}], defaultAdmin=0xDc783b3cb88Fdb2B01c61997746B655D7b54003e, setupActions=[Z0y65gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABg//////////////////////////////////////////8AAAAAAAAAAAAAAAB/ksjnrAjL7KEcpukpIGciZ4abBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCaXBmczovL2JhZmtyZWlmMmVpdHIyZW9xcHZieGtxbG41Y3psZzR1ejN2ZjY0MjQ2aTR5dDV5amdibmJ4YmFmNzJlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, r+1+ngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9AAAAAAAAAAAAAAAANx4Ozy4j9srAcYZl3RrZV17VAA+, jsmYoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAABOJRaiwgfoShg5dVZ139jvYwLwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA==, 2QS5SgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAABOJRaiwgfoShg5dVZ139jvYwLwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADENNt+7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGa4/UwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVKa6ehgAAAAAAAAAAAAAAAAADceDs8uI/bKwHGGZd0a2Vde1QAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=] ) => ( 0xAedc792d23AB8681F8c0154b2d57225095c7dbB3 )
-
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.60406080( )
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.8a08eb4c( )
ZoraCreator1155Impl.initialize( contractName=Dancing Mocassins, newContractURI=ipfs://bafkreidwbfvon4ihyqcrr6zj2ehts7sel4fd6bqssxtxacsenzbabramqm, 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:0xDc783b3cb88Fdb2B01c61997746B655D7b54003e, valueString:0xDc783b3cb88Fdb2B01c61997746B655D7b54003e}], defaultAdmin=0xDc783b3cb88Fdb2B01c61997746B655D7b54003e, setupActions=[Z0y65gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABg//////////////////////////////////////////8AAAAAAAAAAAAAAAB/ksjnrAjL7KEcpukpIGciZ4abBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCaXBmczovL2JhZmtyZWlmMmVpdHIyZW9xcHZieGtxbG41Y3psZzR1ejN2ZjY0MjQ2aTR5dDV5amdibmJ4YmFmNzJlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, r+1+ngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9AAAAAAAAAAAAAAAANx4Ozy4j9srAcYZl3RrZV17VAA+, jsmYoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAABOJRaiwgfoShg5dVZ139jvYwLwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA==, 2QS5SgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAABOJRaiwgfoShg5dVZ139jvYwLwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADENNt+7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGa4/UwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVKa6ehgAAAAAAAAAAAAAAAAADceDs8uI/bKwHGGZd0a2Vde1QAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=] )
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.674cbae6( )
-
ZoraCreator1155Impl.setupNewTokenWithCreateReferral( newURI=ipfs://bafkreif2eitr2eoqpvbxkqln5czlg4uz3vf64246i4yt5yjgbnbxbaf72e, maxSupply=115792089237316195423570985008687907853269984665640564039457584007913129639935, createReferral=0x7f92C8e7AC08cBECa11ca6e92920672267869B06 ) => ( 1 )
-
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.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:0xDc783b3cb88Fdb2B01c61997746B655D7b54003e, valueString:0xDc783b3cb88Fdb2B01c61997746B655D7b54003e}] )
-
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.8ec998a0( )
-
ZoraCreator1155Impl.addPermission( tokenId=1, user=0x04E2516A2c207E84a1839755675dfd8eF6302F0a, permissionBits=4 )
-
0xaedc792d23ab8681f8c0154b2d57225095c7dbb3.d904b94a( )
ZoraCreator1155Impl.callSale( tokenId=1, salesConfig=0x04E2516A2c207E84a1839755675dfd8eF6302F0a, data=0x34DB7EEE00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000066B8FD4C000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000354A6BA7A18000000000000000000000000000DC783B3CB88FDB2B01C61997746B655D7B54003E )
-
ZoraCreatorFixedPriceSaleStrategy.supportsInterface( interfaceId=System.Byte[] ) => ( True )
-
ZoraCreatorFixedPriceSaleStrategy.setSale( tokenId=1, salesConfig=[{name:saleStart, type:uint64, order:1, indexed:false, value:1723399500, valueString:1723399500}, {name:saleEnd, type:uint64, order:2, indexed:false, value:18446744073709551615, valueString:18446744073709551615}, {name:maxTokensPerAddress, type:uint64, order:3, indexed:false, value:0, valueString:0}, {name:pricePerToken, type:uint96, order:4, indexed:false, value:15000000000000000, valueString:15000000000000000}, {name:fundsRecipient, type:address, order:5, indexed:false, value:0xDc783b3cb88Fdb2B01c61997746B655D7b54003e, valueString:0xDc783b3cb88Fdb2B01c61997746B655D7b54003e}] )
-
-
createContract[ZoraCreator1155FactoryImpl (ln:57)]
SetupNewContract[ZoraCreator1155FactoryImpl (ln:65)]
initialize[ZoraCreator1155FactoryImpl (ln:73)]
File 1 of 4: Zora1155Factory
File 2 of 4: ZoraCreatorFixedPriceSaleStrategy
File 3 of 4: ZoraCreator1155FactoryImpl
File 4 of 4: ZoraCreator1155Impl
// 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 "@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; /// @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 {IMinter1155} from "../interfaces/IMinter1155.sol"; import {IContractMetadata} from "../interfaces/IContractMetadata.sol"; import {IVersionedContract} from "../interfaces/IVersionedContract.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 IHasContractName { /// @notice Contract name returns the pretty contract name function contractName() external returns (string memory); } interface IContractMetadata is IHasContractName { /// @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 "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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); }