@artblocks/contracts 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. package/README.md +86 -34
  2. package/artifacts/contracts/AdminACLV0.sol/AdminACLV0.json +2 -2
  3. package/artifacts/contracts/AdminACLV1.sol/AdminACLV1.json +2 -2
  4. package/artifacts/contracts/BytecodeStorageReaders/BytecodeStorageReaderContractV2.sol/BytecodeStorageReaderContractV2.json +201 -0
  5. package/artifacts/contracts/BytecodeStorageReaders/UniversalBytecodeStorageReader.sol/UniversalBytecodeStorageReader.json +154 -0
  6. package/artifacts/contracts/BytecodeStorageV2Writer.sol/BytecodeStorageV2Writer.json +87 -0
  7. package/artifacts/contracts/DependencyRegistryV0.sol/DependencyRegistryV0.json +403 -155
  8. package/artifacts/contracts/GenArt721CoreV3_Curated.sol/GenArt721CoreV3_Curated.json +2493 -0
  9. package/artifacts/contracts/OwnedCreate2FactoryV0.sol/OwnedCreate2FactoryV0.json +311 -0
  10. package/artifacts/contracts/archive/GenArt721CoreV3.sol/GenArt721CoreV3.json +2060 -0
  11. package/artifacts/contracts/archive/GenArt721CoreV3_Explorations.sol/GenArt721CoreV3_Explorations.json +2034 -0
  12. package/artifacts/contracts/{minter-suite → archive/minter-suite}/Minters/MinterBase_v0_1_1.sol/MinterBase.json +1 -1
  13. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExp/MinterDAExpV2.sol/MinterDAExpV2.json +2 -2
  14. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExp/MinterDAExpV3.sol/MinterDAExpV3.json +2 -2
  15. package/artifacts/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterDAExp}/MinterDAExpV4.sol/MinterDAExpV4.json +3 -3
  16. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExpSettlement/MinterDAExpSettlementV0.sol/MinterDAExpSettlementV0.json +2 -2
  17. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExpSettlement/MinterDAExpSettlementV1.sol/MinterDAExpSettlementV1.json +2 -2
  18. package/artifacts/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterDAExpSettlement}/MinterDAExpSettlementV2.sol/MinterDAExpSettlementV2.json +3 -3
  19. package/artifacts/contracts/archive/minter-suite/Minters/MinterDALin/MinterDALinV2.sol/MinterDALinV2.json +2 -2
  20. package/artifacts/contracts/archive/minter-suite/Minters/MinterDALin/MinterDALinV3.sol/MinterDALinV3.json +2 -2
  21. package/artifacts/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterDALin}/MinterDALinV4.sol/MinterDALinV4.json +3 -3
  22. package/artifacts/contracts/archive/minter-suite/Minters/MinterHolder/MinterHolderV1.sol/MinterHolderV1.json +2 -2
  23. package/artifacts/contracts/archive/minter-suite/Minters/MinterHolder/MinterHolderV2.sol/MinterHolderV2.json +2 -2
  24. package/artifacts/contracts/archive/minter-suite/Minters/MinterHolder/MinterHolderV3.sol/MinterHolderV3.json +2 -2
  25. package/artifacts/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterHolder}/MinterHolderV4.sol/MinterHolderV4.json +3 -3
  26. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV1.sol/MinterMerkleV1.json +2 -2
  27. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV2.sol/MinterMerkleV2.json +2 -2
  28. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV3.sol/MinterMerkleV3.json +2 -2
  29. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV4.sol/MinterMerkleV4.json +2 -2
  30. package/artifacts/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterMerkle}/MinterMerkleV5.sol/MinterMerkleV5.json +3 -3
  31. package/artifacts/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterPolyptych}/MinterPolyptychV0.sol/IGenArt721CoreContractV3WithRandomizer.json +54 -49
  32. package/artifacts/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterPolyptych}/MinterPolyptychV0.sol/MinterPolyptychV0.json +3 -3
  33. package/artifacts/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterSEA}/MinterSEAV0.sol/MinterSEAV0.json +3 -3
  34. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPrice/MinterSetPriceV2.sol/MinterSetPriceV2.json +2 -2
  35. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPrice/MinterSetPriceV3.sol/MinterSetPriceV3.json +2 -2
  36. package/artifacts/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterSetPrice}/MinterSetPriceV4.sol/MinterSetPriceV4.json +3 -3
  37. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V0.sol/MinterSetPriceERC20V0.json +65 -2
  38. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V1.sol/MinterSetPriceERC20V1.json +65 -2
  39. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V2.sol/MinterSetPriceERC20V2.json +2 -2
  40. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V3.sol/MinterSetPriceERC20V3.json +2 -2
  41. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V4.sol/MinterSetPriceERC20V4.json +807 -0
  42. package/artifacts/contracts/engine/V2/GenArt721MinterBurner_PBAB.sol/GenArt721MinterBurner_PBAB.json +65 -2
  43. package/artifacts/contracts/engine/V2/GenArt721Minter_PBAB.sol/GenArt721Minter_PBAB.json +65 -2
  44. package/artifacts/contracts/engine/V3/EngineFactoryV0.sol/EngineFactoryV0.json +624 -0
  45. package/artifacts/contracts/engine/V3/GenArt721CoreV3_Engine.sol/GenArt721CoreV3_Engine.json +613 -216
  46. package/artifacts/contracts/engine/V3/GenArt721CoreV3_Engine_Flex.sol/GenArt721CoreV3_Engine_Flex.json +805 -206
  47. package/artifacts/contracts/engine/V3/forks/GenArt721CoreV3_Engine_Flex_PROOF.sol/GenArt721CoreV3_Engine_Flex_PROOF.json +51 -8
  48. package/artifacts/contracts/engine/V3/forks/PROHIBITION/AdminACLV0_PROHIBITION.sol/AdminACLV0_PROHIBITION.json +2 -2
  49. package/artifacts/contracts/engine/V3/forks/PROHIBITION/GenArt721CoreV3_Engine_Flex_PROHIBITION.sol/GenArt721CoreV3_Engine_Flex_PROHIBITION.json +51 -8
  50. package/artifacts/contracts/engine/V3/forks/PROHIBITION/interfaces/IGenArt721CoreContractV3_Engine_Flex_PROHIBITION.sol/IGenArt721CoreContractV3_Engine_Flex_PROHIBITION.json +59 -54
  51. package/artifacts/contracts/engine-registry/CoreRegistryV1.sol/CoreRegistryV1.json +2 -2
  52. package/artifacts/contracts/generator/AddressChunks.sol/AddressChunks.json +10 -0
  53. package/artifacts/contracts/generator/GenArt721GeneratorV0.sol/GenArt721GeneratorV0.json +333 -0
  54. package/artifacts/contracts/generator/GenArt721GeneratorV0.sol/ILegacyGenArt721CoreV2_PBAB_Flex.json +47 -0
  55. package/artifacts/contracts/interfaces/v0.8.x/IAdminACLV0_Extended.sol/IAdminACLV0_Extended.json +140 -0
  56. package/artifacts/contracts/interfaces/v0.8.x/IBytecodeStorageReader.sol/IBytecodeStorageReader.json +7 -7
  57. package/artifacts/contracts/interfaces/v0.8.x/IBytecodeStorageReaderV2.sol/IBytecodeStorageReaderV2.json +130 -0
  58. package/artifacts/contracts/interfaces/v0.8.x/IBytecodeStorageReader_Base.sol/IBytecodeStorageReader_Base.json +30 -0
  59. package/artifacts/contracts/interfaces/v0.8.x/ICoreRegistryV1.sol/ICoreRegistryV1.json +13 -0
  60. package/artifacts/contracts/interfaces/v0.8.x/IDependencyRegistryV0.sol/IDependencyRegistryV0.json +228 -45
  61. package/artifacts/contracts/interfaces/v0.8.x/IEngineFactoryV0.sol/IEngineFactoryV0.json +283 -0
  62. package/artifacts/contracts/interfaces/v0.8.x/IFilteredMinterDAExpSettlementV0.sol/IFilteredMinterDAExpSettlementV0.json +12 -12
  63. package/artifacts/contracts/interfaces/v0.8.x/IFilteredMinterDAExpSettlementV1.sol/IFilteredMinterDAExpSettlementV1.json +12 -12
  64. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3.sol/IGenArt721CoreContractV3.json +53 -48
  65. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Base.sol/IGenArt721CoreContractV3_Base.json +53 -48
  66. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine.sol/IGenArt721CoreContractV3_Engine.json +198 -90
  67. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex.sol/IGenArt721CoreContractV3_Engine_Flex.json +198 -90
  68. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex_PreV3p2.sol/IGenArt721CoreContractV3_Engine_Flex_PreV3p2.json +1065 -0
  69. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_PreV3p2.sol/IGenArt721CoreContractV3_Engine_PreV3p2.json +778 -0
  70. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_ProjectFinance.sol/IGenArt721CoreContractV3_ProjectFinance.json +87 -0
  71. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreProjectScriptV0.sol/IGenArt721CoreProjectScriptV0.json +59 -0
  72. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreProjectScriptV1.sol/IGenArt721CoreProjectScriptV1.json +64 -0
  73. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreTokenHashProviderV0.sol/IGenArt721CoreTokenHashProviderV0.json +30 -0
  74. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreTokenHashProviderV1.sol/IGenArt721CoreTokenHashProviderV1.json +30 -0
  75. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721GeneratorV0.sol/IGenArt721GeneratorV0.json +63 -0
  76. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721Minter_PBAB.sol/IGenArt721Minter_PBAB.json +279 -0
  77. package/artifacts/contracts/interfaces/v0.8.x/IOwnedCreate2FactoryV0.sol/IOwnedCreate2FactoryV0.json +74 -0
  78. package/artifacts/contracts/interfaces/v0.8.x/IPseudorandomAtomic.sol/IPseudorandomAtomic.json +1 -1
  79. package/artifacts/contracts/interfaces/v0.8.x/ISeaDropShimForContract.sol/ISeaDropShimForContract.json +37 -0
  80. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterDAExpSettlementV0.sol/ISharedMinterDAExpSettlementV0.json +18 -0
  81. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterMinPriceV0.sol/ISharedMinterMinPriceV0.json +37 -0
  82. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterRAMV0.sol/ISharedMinterRAMV0.json +62 -0
  83. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterRequired.sol/ISharedMinterRequired.json +37 -0
  84. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterSEAV0.sol/ISharedMinterSEAV0.json +1 -1
  85. package/artifacts/contracts/interfaces/v0.8.x/ISplitAtomicFactoryV0.sol/ISplitAtomicFactoryV0.json +170 -0
  86. package/artifacts/contracts/interfaces/v0.8.x/ISplitAtomicV0.sol/ISplitAtomicV0.json +126 -0
  87. package/artifacts/contracts/interfaces/v0.8.x/ISplitProviderV0.sol/ISplitProviderV0.json +98 -0
  88. package/artifacts/contracts/interfaces/v0.8.x/IUniversalBytecodeStorageReader.sol/IUniversalBytecodeStorageReader.json +56 -0
  89. package/artifacts/contracts/interfaces/v0.8.x/integration-refs/OpenSea/ERC721SeaDropStructsErrorsAndEvents.sol/ERC721SeaDropStructsErrorsAndEvents.json +43 -0
  90. package/artifacts/contracts/interfaces/v0.8.x/integration-refs/OpenSea/INonFungibleSeaDropToken.sol/INonFungibleSeaDropToken.json +715 -0
  91. package/artifacts/contracts/interfaces/v0.8.x/integration-refs/OpenSea/ISeaDrop.sol/ISeaDrop.json +1571 -0
  92. package/artifacts/contracts/interfaces/v0.8.x/integration-refs/OpenSea/ISeaDropTokenContractMetadata.sol/ISeaDropTokenContractMetadata.json +345 -0
  93. package/artifacts/contracts/interfaces/v0.8.x/integration-refs/OpenSea/SeaDropErrorsAndEvents.sol/SeaDropErrorsAndEvents.json +717 -0
  94. package/artifacts/contracts/interfaces/v0.8.x/integration-refs/splits-0x-v2/ISplitFactoryV2.sol/ISplitFactoryV2.json +123 -0
  95. package/artifacts/contracts/libs/integration-refs/delegation-registry/DelegationRegistry.sol/DelegationRegistry.json +2 -2
  96. package/artifacts/contracts/libs/integration-refs/gnosis-safe/GnosisSafeMock.sol/GnosisSafeMock.json +2 -2
  97. package/artifacts/contracts/libs/integration-refs/gnosis-safe/GnosisSafeProxyFactoryMock.sol/GnosisSafeProxyFactoryMock.json +2 -2
  98. package/artifacts/contracts/libs/integration-refs/gnosis-safe/MultiSendMock.sol/MultiSendMock.json +2 -2
  99. package/artifacts/contracts/libs/integration-refs/weth9/weth9.sol/WETH9_.json +2 -2
  100. package/artifacts/contracts/libs/v0.8.x/ABHelpers.sol/ABHelpers.json +2 -2
  101. package/artifacts/contracts/libs/v0.8.x/AuthLib.sol/AuthLib.json +2 -2
  102. package/artifacts/contracts/libs/v0.8.x/BitMap.sol/BitMaps256.json +10 -0
  103. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV0.sol/BytecodeStorage.json +2 -2
  104. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV1.sol/BytecodeStorageReader.json +2 -2
  105. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV1.sol/BytecodeStorageWriter.json +2 -2
  106. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV2.sol/BytecodeStorageReader.json +214 -0
  107. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV2.sol/BytecodeStorageWriter.json +10 -0
  108. package/artifacts/contracts/libs/v0.8.x/Bytes32Strings.sol/Bytes32Strings.json +2 -2
  109. package/artifacts/contracts/libs/v0.8.x/DependencyRegistryStorageLib.sol/DependencyRegistryStorageLib.json +10 -0
  110. package/artifacts/contracts/libs/v0.8.x/ERC721_PackedHashSeed.sol/ERC721_PackedHashSeed.json +2 -2
  111. package/artifacts/contracts/libs/v0.8.x/ERC721_PackedHashSeedV1.sol/ERC721_PackedHashSeedV1.json +444 -0
  112. package/artifacts/contracts/libs/v0.8.x/JsonStatic.sol/JsonStatic.json +10 -0
  113. package/artifacts/contracts/libs/v0.8.x/PackedBools.sol/PackedBools.json +10 -0
  114. package/artifacts/contracts/libs/v0.8.x/SSTORE2.sol/SSTORE2.json +2 -2
  115. package/artifacts/contracts/libs/v0.8.x/V3FlexLib.sol/V3FlexLib.json +195 -0
  116. package/artifacts/contracts/libs/v0.8.x/minter-libs/DAExpLib.sol/DAExpLib.json +2 -2
  117. package/artifacts/contracts/libs/v0.8.x/minter-libs/DALib.sol/DALib.json +2 -2
  118. package/artifacts/contracts/libs/v0.8.x/minter-libs/DALinLib.sol/DALinLib.json +2 -2
  119. package/artifacts/contracts/libs/v0.8.x/minter-libs/GenericMinterEventsLib.sol/GenericMinterEventsLib.json +2 -2
  120. package/artifacts/contracts/libs/v0.8.x/minter-libs/MaxInvocationsLib.sol/MaxInvocationsLib.json +2 -2
  121. package/artifacts/contracts/libs/v0.8.x/minter-libs/MerkleLib.sol/MerkleLib.json +2 -2
  122. package/artifacts/contracts/libs/v0.8.x/minter-libs/MinPriceLib.sol/MinPriceLib.json +24 -0
  123. package/artifacts/contracts/libs/v0.8.x/minter-libs/PolyptychLib.sol/PolyptychLib.json +2 -2
  124. package/artifacts/contracts/libs/v0.8.x/minter-libs/RAMLib.sol/RAMLib.json +398 -0
  125. package/artifacts/contracts/libs/v0.8.x/minter-libs/SEALib.sol/SEALib.json +2 -2
  126. package/artifacts/contracts/libs/v0.8.x/minter-libs/SetPriceLib.sol/SetPriceLib.json +2 -2
  127. package/artifacts/contracts/libs/v0.8.x/minter-libs/SettlementExpLib.sol/SettlementExpLib.json +2 -2
  128. package/artifacts/contracts/libs/v0.8.x/minter-libs/SplitFundsLib.sol/SplitFundsLib.json +2 -2
  129. package/artifacts/contracts/libs/v0.8.x/minter-libs/TokenHolderLib.sol/TokenHolderLib.json +2 -2
  130. package/artifacts/contracts/minter-suite/MinterFilter/MinterFilterV1.sol/MinterFilterV1.json +2 -2
  131. package/artifacts/contracts/minter-suite/MinterFilter/MinterFilterV2.sol/MinterFilterV2.json +2 -2
  132. package/artifacts/contracts/minter-suite/Minters/MinterDAExpHolderV5.sol/MinterDAExpHolderV5.json +2 -2
  133. package/artifacts/contracts/minter-suite/Minters/MinterDAExpSettlementV3.sol/MinterDAExpSettlementV3.json +2 -2
  134. package/artifacts/contracts/minter-suite/Minters/MinterDAExpV5.sol/MinterDAExpV5.json +2 -2
  135. package/artifacts/contracts/minter-suite/Minters/MinterDALinHolderV5.sol/MinterDALinHolderV5.json +2 -2
  136. package/artifacts/contracts/minter-suite/Minters/MinterDALinV5.sol/MinterDALinV5.json +2 -2
  137. package/artifacts/contracts/minter-suite/Minters/MinterMinPriceMerkleV0.sol/MinterMinPriceMerkleV0.json +664 -0
  138. package/artifacts/contracts/minter-suite/Minters/MinterMinPriceV0.sol/MinterMinPriceV0.json +387 -0
  139. package/artifacts/contracts/minter-suite/Minters/MinterRAMV0.sol/MinterRAMV0.json +1374 -0
  140. package/artifacts/contracts/minter-suite/Minters/MinterSEAV1.sol/MinterSEAV1.json +7 -7
  141. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceERC20V5.sol/MinterSetPriceERC20V5.json +2 -2
  142. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceHolderV5.sol/MinterSetPriceHolderV5.json +2 -2
  143. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceMerkleV5.sol/MinterSetPriceMerkleV5.json +2 -2
  144. package/artifacts/contracts/minter-suite/Minters/MinterSetPricePolyptychERC20V5.sol/MinterSetPricePolyptychERC20V5.json +2 -2
  145. package/artifacts/contracts/minter-suite/Minters/MinterSetPricePolyptychV5.sol/MinterSetPricePolyptychV5.json +2 -2
  146. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceV5.sol/MinterSetPriceV5.json +2 -2
  147. package/artifacts/contracts/minter-suite/Minters/one-off/MinterSetPriceV5_SingleCore.sol/MinterSetPriceV5_SingleCore.json +417 -0
  148. package/artifacts/contracts/minter-suite/Minters/one-off/SeaDropXArtBlocksShim.sol/SeaDropXArtBlocksShim.json +1206 -0
  149. package/artifacts/contracts/mock/BytecodeV1LibCallsMock.sol/BytecodeV1LibCallsMock.json +2 -2
  150. package/artifacts/contracts/mock/BytecodeV2LibCallsMock.sol/BytecodeV2LibCallsMock.json +154 -0
  151. package/artifacts/contracts/mock/BytecodeV2TextCR_DMock.sol/BytecodeV2TextCR_DMock.json +428 -0
  152. package/artifacts/contracts/mock/DummySharedMinter.sol/DummySharedMinter.json +2 -2
  153. package/artifacts/contracts/mock/ERC20Mock.sol/ERC20Mock.json +2 -2
  154. package/artifacts/contracts/mock/ERC20MockAltDecimals.sol/ERC20MockAltDecimals.json +318 -0
  155. package/artifacts/contracts/mock/ForceSendMock.sol/ForceSendMock.json +24 -0
  156. package/artifacts/contracts/mock/GenArt721CoreV3_Engine_IncorrectCoreType.sol/GenArt721CoreV3_Engine_IncorrectCoreType.json +2 -2
  157. package/artifacts/contracts/mock/Mock0xSplitsV2PullFactory.sol/Mock0xSplitsV2PullFactory.json +149 -0
  158. package/artifacts/contracts/mock/Mock0xSplitsV2Splitter.sol/Mock0xSplitsV2Splitter.json +99 -0
  159. package/artifacts/contracts/mock/MockAdminACLV0.sol/MockAdminACLV0Events.json +20 -2
  160. package/artifacts/contracts/mock/MockAdminACLV0_PROHIBITION.sol/MockAdminACLV0Events_PROHIBITION.json +20 -2
  161. package/artifacts/contracts/mock/MockFileStore.sol/MockFileStore.json +35 -0
  162. package/artifacts/contracts/mock/OriginRegisterMock.sol/OriginRegisterMock.json +2 -2
  163. package/artifacts/contracts/mock/RandomizerV2_NoAssignMock.sol/RandomizerV2_NoAssignMock.json +2 -2
  164. package/artifacts/contracts/mock/ReentrancyGenArt721MinterMock.sol/ReentrancyGenArt721MinterMock.json +100 -0
  165. package/artifacts/contracts/mock/ReentrancyHolderMock.sol/ReentrancyHolderMock.json +2 -2
  166. package/artifacts/contracts/mock/ReentrancyHolderMockShared.sol/ReentrancyHolderMockShared.json +2 -2
  167. package/artifacts/contracts/mock/ReentrancyMerkleMock.sol/ReentrancyMerkleMock.json +2 -2
  168. package/artifacts/contracts/mock/ReentrancyMerkleMockShared.sol/ReentrancyMerkleMockShared.json +2 -2
  169. package/artifacts/contracts/mock/ReentrancyMock.sol/ReentrancyMock.json +2 -2
  170. package/artifacts/contracts/mock/ReentrancyMockShared.sol/ReentrancyMockShared.json +2 -2
  171. package/artifacts/contracts/mock/ReentrancySEAMock.sol/ReentrancySEAAutoBidderMock.json +2 -2
  172. package/artifacts/contracts/mock/ReentrancySEAMockShared.sol/ReentrancySEAAutoBidderMockShared.json +2 -2
  173. package/artifacts/contracts/mock/ReentrancySplitterMocks.sol/ReentrancySplitterDrainETHMock.json +54 -0
  174. package/artifacts/contracts/mock/ReentrancySplitterMocks.sol/ReentrancySplitterSendETHMock.json +54 -0
  175. package/artifacts/contracts/randomizer/deprecated/PolyptychRandomizerV0.sol/BasicPolyptychRandomizerV0.json +2 -2
  176. package/artifacts/contracts/randomizer/deprecated/RandomizerV2.sol/BasicRandomizerV2.json +2 -2
  177. package/artifacts/contracts/randomizer/primitive/PseudorandomAtomicBasic.sol/PseudorandomAtomic.json +2 -2
  178. package/artifacts/contracts/randomizer/shared/SharedRandomizerV0.sol/SharedRandomizerV0.json +2 -2
  179. package/artifacts/contracts/split/SplitAtomicFactoryV0.sol/SplitAtomicFactoryV0.json +203 -0
  180. package/artifacts/contracts/split/SplitAtomicV0.sol/SplitAtomicV0.json +168 -0
  181. package/artifacts/contracts/split/split-provider/SplitProviderV0.sol/SplitProviderV0.json +141 -0
  182. package/contracts/AdminACLV0.sol +6 -2
  183. package/contracts/AdminACLV1.sol +2 -2
  184. package/contracts/BytecodeStorageReaders/BytecodeStorageReaderContractV2.sol +103 -0
  185. package/contracts/BytecodeStorageReaders/UniversalBytecodeStorageReader.sol +70 -0
  186. package/contracts/BytecodeStorageV2Writer.sol +69 -0
  187. package/contracts/DependencyRegistryV0.sol +878 -430
  188. package/contracts/GenArt721CoreV3_Curated.sol +133 -0
  189. package/contracts/OwnedCreate2FactoryV0.sol +173 -0
  190. package/contracts/{GenArt721CoreV3.sol → archive/GenArt721CoreV3.sol} +56 -20
  191. package/contracts/{explorations → archive}/GenArt721CoreV3_Explorations.sol +49 -13
  192. package/contracts/{minter-suite → archive/minter-suite}/Minters/MinterBase_v0_1_1.sol +4 -4
  193. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterDAExp}/MinterDAExpV4.sol +4 -4
  194. package/contracts/archive/minter-suite/Minters/MinterDAExpSettlement/MinterDAExpSettlementV0.sol +4 -4
  195. package/contracts/archive/minter-suite/Minters/MinterDAExpSettlement/MinterDAExpSettlementV1.sol +5 -5
  196. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterDAExpSettlement}/MinterDAExpSettlementV2.sol +8 -8
  197. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterDALin}/MinterDALinV4.sol +4 -4
  198. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterHolder}/MinterHolderV4.sol +5 -5
  199. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterMerkle}/MinterMerkleV5.sol +5 -5
  200. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterPolyptych}/MinterPolyptychV0.sol +7 -7
  201. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterSEA}/MinterSEAV0.sol +13 -13
  202. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterSetPrice}/MinterSetPriceV4.sol +4 -4
  203. package/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V0.sol +82 -10
  204. package/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V1.sol +82 -10
  205. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterSetPriceERC20}/MinterSetPriceERC20V4.sol +88 -21
  206. package/contracts/engine/V2/GenArt721MinterBurner_PBAB.sol +81 -22
  207. package/contracts/engine/V2/GenArt721Minter_PBAB.sol +80 -22
  208. package/contracts/engine/V3/EngineFactoryV0.sol +427 -0
  209. package/contracts/engine/V3/GenArt721CoreV3_Engine.sol +977 -502
  210. package/contracts/engine/V3/GenArt721CoreV3_Engine_Flex.sol +1137 -663
  211. package/contracts/engine/V3/forks/GenArt721CoreV3_Engine_Flex_PROOF.sol +3 -3
  212. package/contracts/engine/V3/forks/PROHIBITION/GenArt721CoreV3_Engine_Flex_PROHIBITION.sol +1 -1
  213. package/contracts/engine/V3/forks/PROHIBITION/interfaces/IGenArt721CoreContractV3_Engine_Flex_PROHIBITION.sol +2 -2
  214. package/contracts/generator/AddressChunks.sol +106 -0
  215. package/contracts/generator/GenArt721GeneratorV0.sol +1094 -0
  216. package/contracts/generator/scripty-support/Scripty.sol +5 -0
  217. package/contracts/interfaces/v0.8.x/IAdminACLV0_Extended.sol +20 -0
  218. package/contracts/interfaces/v0.8.x/IBytecodeStorageReader.sol +34 -36
  219. package/contracts/interfaces/v0.8.x/IBytecodeStorageReaderV2.sol +25 -0
  220. package/contracts/interfaces/v0.8.x/IBytecodeStorageReader_Base.sol +20 -0
  221. package/contracts/interfaces/v0.8.x/ICoreRegistryV1.sol +5 -0
  222. package/contracts/interfaces/v0.8.x/IDependencyRegistryV0.sol +141 -45
  223. package/contracts/interfaces/v0.8.x/IEngineFactoryV0.sol +124 -0
  224. package/contracts/interfaces/v0.8.x/IFilteredMinterDAExpSettlementV0.sol +1 -3
  225. package/contracts/interfaces/v0.8.x/IFilteredMinterDAExpSettlementV1.sol +1 -3
  226. package/contracts/interfaces/v0.8.x/IFilteredMinterDAExpV1.sol +1 -3
  227. package/contracts/interfaces/v0.8.x/IFilteredMinterDALinV1.sol +1 -3
  228. package/contracts/interfaces/v0.8.x/IFilteredMinterHolderV2.sol +1 -3
  229. package/contracts/interfaces/v0.8.x/IFilteredMinterMerkleV2.sol +1 -3
  230. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Base.sol +126 -11
  231. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine.sol +86 -8
  232. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex.sol +26 -8
  233. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex_PreV3p2.sol +141 -0
  234. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_PreV3p2.sol +78 -0
  235. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_ProjectFinance.sol +47 -0
  236. package/contracts/interfaces/v0.8.x/IGenArt721CoreProjectScriptV0.sol +22 -0
  237. package/contracts/interfaces/v0.8.x/IGenArt721CoreProjectScriptV1.sol +23 -0
  238. package/contracts/interfaces/v0.8.x/IGenArt721CoreTokenHashProviderV0.sol +11 -0
  239. package/contracts/interfaces/v0.8.x/IGenArt721CoreTokenHashProviderV1.sol +9 -0
  240. package/contracts/interfaces/v0.8.x/IGenArt721GeneratorV0.sol +14 -0
  241. package/contracts/interfaces/v0.8.x/IGenArt721Minter_PBAB.sol +91 -0
  242. package/contracts/interfaces/v0.8.x/IOwnedCreate2FactoryV0.sol +40 -0
  243. package/contracts/interfaces/v0.8.x/IPseudorandomAtomic.sol +1 -3
  244. package/contracts/interfaces/v0.8.x/ISeaDropShimForContract.sol +19 -0
  245. package/contracts/interfaces/v0.8.x/ISharedMinterDAExpSettlementV0.sol +19 -0
  246. package/contracts/interfaces/v0.8.x/ISharedMinterMinPriceV0.sol +22 -0
  247. package/contracts/interfaces/v0.8.x/ISharedMinterRAMV0.sol +23 -0
  248. package/contracts/interfaces/v0.8.x/ISharedMinterRequired.sol +26 -0
  249. package/contracts/interfaces/v0.8.x/ISharedMinterSEAV0.sol +1 -4
  250. package/contracts/interfaces/v0.8.x/ISharedMinterV0.sol +12 -6
  251. package/contracts/interfaces/v0.8.x/ISplitAtomicFactoryV0.sol +81 -0
  252. package/contracts/interfaces/v0.8.x/ISplitAtomicV0.sol +72 -0
  253. package/contracts/interfaces/v0.8.x/ISplitProviderV0.sol +49 -0
  254. package/contracts/interfaces/v0.8.x/IUniversalBytecodeStorageReader.sol +28 -0
  255. package/contracts/interfaces/v0.8.x/integration-refs/OpenSea/ERC721SeaDropStructsErrorsAndEvents.sol +58 -0
  256. package/contracts/interfaces/v0.8.x/integration-refs/OpenSea/INonFungibleSeaDropToken.sol +186 -0
  257. package/contracts/interfaces/v0.8.x/integration-refs/OpenSea/ISeaDrop.sol +337 -0
  258. package/contracts/interfaces/v0.8.x/integration-refs/OpenSea/ISeaDropTokenContractMetadata.sol +152 -0
  259. package/contracts/interfaces/v0.8.x/integration-refs/OpenSea/SeaDropErrorsAndEvents.sol +320 -0
  260. package/contracts/interfaces/v0.8.x/integration-refs/OpenSea/SeaDropStructs.sol +146 -0
  261. package/contracts/interfaces/v0.8.x/integration-refs/splits-0x-v2/ISplitFactoryV2.sol +62 -0
  262. package/contracts/libs/v0.8.x/ABHelpers.sol +18 -4
  263. package/contracts/libs/v0.8.x/BitMap.sol +112 -0
  264. package/contracts/libs/v0.8.x/BytecodeStorageV2.sol +593 -0
  265. package/contracts/libs/v0.8.x/Bytes32Strings.sol +20 -0
  266. package/contracts/libs/v0.8.x/DependencyRegistryStorageLib.sol +98 -0
  267. package/contracts/libs/v0.8.x/ERC721_PackedHashSeedV1.sol +591 -0
  268. package/contracts/libs/v0.8.x/JsonStatic.sol +373 -0
  269. package/contracts/libs/v0.8.x/PackedBools.sol +42 -0
  270. package/contracts/libs/v0.8.x/V3FlexLib.sol +597 -0
  271. package/contracts/libs/v0.8.x/minter-libs/DAExpLib.sol +10 -12
  272. package/contracts/libs/v0.8.x/minter-libs/DALinLib.sol +4 -9
  273. package/contracts/libs/v0.8.x/minter-libs/GenericMinterEventsLib.sol +44 -44
  274. package/contracts/libs/v0.8.x/minter-libs/MaxInvocationsLib.sol +64 -63
  275. package/contracts/libs/v0.8.x/minter-libs/MerkleLib.sol +14 -10
  276. package/contracts/libs/v0.8.x/minter-libs/MinPriceLib.sol +64 -0
  277. package/contracts/libs/v0.8.x/minter-libs/RAMLib.sol +2927 -0
  278. package/contracts/libs/v0.8.x/minter-libs/SEALib.sol +60 -62
  279. package/contracts/libs/v0.8.x/minter-libs/SetPriceLib.sol +4 -8
  280. package/contracts/libs/v0.8.x/minter-libs/SettlementExpLib.sol +92 -89
  281. package/contracts/libs/v0.8.x/minter-libs/SplitFundsLib.sol +128 -15
  282. package/contracts/libs/v0.8.x/minter-libs/TokenHolderLib.sol +5 -4
  283. package/contracts/minter-suite/MinterFilter/MinterFilterV2.sol +16 -10
  284. package/contracts/minter-suite/Minters/MinterDAExpHolderV5.sol +2 -2
  285. package/contracts/minter-suite/Minters/MinterDAExpSettlementV3.sol +19 -15
  286. package/contracts/minter-suite/Minters/MinterDAExpV5.sol +2 -2
  287. package/contracts/minter-suite/Minters/MinterDALinHolderV5.sol +2 -2
  288. package/contracts/minter-suite/Minters/MinterDALinV5.sol +2 -2
  289. package/contracts/minter-suite/Minters/MinterMinPriceMerkleV0.sol +765 -0
  290. package/contracts/minter-suite/Minters/MinterMinPriceV0.sol +462 -0
  291. package/contracts/minter-suite/Minters/MinterRAMV0.sol +1205 -0
  292. package/contracts/minter-suite/Minters/MinterSEAV1.sol +21 -32
  293. package/contracts/minter-suite/Minters/MinterSetPriceERC20V5.sol +17 -8
  294. package/contracts/minter-suite/Minters/MinterSetPriceHolderV5.sol +2 -2
  295. package/contracts/minter-suite/Minters/MinterSetPriceMerkleV5.sol +2 -2
  296. package/contracts/minter-suite/Minters/MinterSetPricePolyptychERC20V5.sol +23 -9
  297. package/contracts/minter-suite/Minters/MinterSetPricePolyptychV5.sol +2 -2
  298. package/contracts/minter-suite/Minters/MinterSetPriceV5.sol +2 -2
  299. package/contracts/minter-suite/Minters/one-off/MinterSetPriceV5_SingleCore.sol +446 -0
  300. package/contracts/minter-suite/Minters/one-off/SeaDropXArtBlocksShim.sol +869 -0
  301. package/contracts/mock/BytecodeV2LibCallsMock.sol +128 -0
  302. package/contracts/mock/BytecodeV2TextCR_DMock.sol +316 -0
  303. package/contracts/mock/ERC20MockAltDecimals.sol +31 -0
  304. package/contracts/mock/ForceSendMock.sol +22 -0
  305. package/contracts/mock/Mock0xSplitsV2PullFactory.sol +75 -0
  306. package/contracts/mock/Mock0xSplitsV2Splitter.sol +47 -0
  307. package/contracts/mock/MockAdminACLV0.sol +21 -0
  308. package/contracts/mock/MockAdminACLV0_PROHIBITION.sol +21 -0
  309. package/contracts/mock/MockFileStore.sol +22 -0
  310. package/contracts/mock/ReentrancyGenArt721MinterMock.sol +47 -0
  311. package/contracts/mock/ReentrancySplitterMocks.sol +67 -0
  312. package/contracts/randomizer/primitive/PseudorandomAtomicBasic.sol +1 -1
  313. package/contracts/randomizer/shared/SharedRandomizerV0.sol +1 -1
  314. package/contracts/split/SplitAtomicFactoryV0.sol +121 -0
  315. package/contracts/split/SplitAtomicV0.sol +265 -0
  316. package/contracts/split/split-provider/SplitProviderV0.sol +201 -0
  317. package/package.json +66 -36
  318. package/artifacts/contracts/GenArt721CoreV3.sol/GenArt721CoreV3.json +0 -1965
  319. package/artifacts/contracts/explorations/GenArt721CoreV3_Explorations.sol/GenArt721CoreV3_Explorations.json +0 -1939
  320. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceERC20V4.sol/MinterSetPriceERC20V4.json +0 -768
  321. package/artifacts/contracts/royalty-registry/GenArt721RoyaltyOverride.sol/GenArt721RoyaltyOverride.json +0 -208
  322. package/artifacts/contracts/royalty-registry/GenArt721RoyaltyOverride_PBAB.sol/GenArt721RoyaltyOverride_PBAB.json +0 -301
  323. package/contracts/archive/readme.md +0 -16
  324. package/contracts/engine/README.md +0 -21
  325. package/contracts/royalty-registry/GenArt721RoyaltyOverride.sol +0 -168
  326. package/contracts/royalty-registry/GenArt721RoyaltyOverride_PBAB.sol +0 -221
@@ -1,18 +1,23 @@
1
1
  // SPDX-License-Identifier: LGPL-3.0-only
2
- pragma solidity 0.8.19;
2
+ pragma solidity 0.8.22;
3
3
 
4
4
  // Created By: Art Blocks Inc.
5
5
 
6
6
  import "../../interfaces/v0.8.x/IRandomizer_V3CoreBase.sol";
7
- import "../../interfaces/v0.8.x/IAdminACLV0.sol";
7
+ import "../../interfaces/v0.8.x/IAdminACLV0_Extended.sol";
8
8
  import "../../interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex.sol";
9
+ import {IGenArt721CoreContractV3_ProjectFinance} from "../../interfaces/v0.8.x/IGenArt721CoreContractV3_ProjectFinance.sol";
9
10
  import "../../interfaces/v0.8.x/IGenArt721CoreContractExposesHashSeed.sol";
10
11
  import "../../interfaces/v0.8.x/IDependencyRegistryCompatibleV0.sol";
11
- import "../../interfaces/v0.8.x/IManifold.sol";
12
-
13
- import "@openzeppelin-4.7/contracts/access/Ownable.sol";
14
- import "../../libs/v0.8.x/ERC721_PackedHashSeed.sol";
15
- import "../../libs/v0.8.x/BytecodeStorageV1.sol";
12
+ import {ISplitProviderV0} from "../../interfaces/v0.8.x/ISplitProviderV0.sol";
13
+ import {IBytecodeStorageReader_Base} from "../../interfaces/v0.8.x/IBytecodeStorageReader_Base.sol";
14
+
15
+ import "@openzeppelin-5.0/contracts/utils/Strings.sol";
16
+ import "@openzeppelin-5.0/contracts/access/Ownable.sol";
17
+ import {IERC2981} from "@openzeppelin-5.0/contracts/interfaces/IERC2981.sol";
18
+ import "../../libs/v0.8.x/ERC721_PackedHashSeedV1.sol";
19
+ import {BytecodeStorageWriter, BytecodeStorageReader} from "../../libs/v0.8.x/BytecodeStorageV2.sol";
20
+ import {V3FlexLib} from "../../libs/v0.8.x/V3FlexLib.sol";
16
21
  import "../../libs/v0.8.x/Bytes32Strings.sol";
17
22
 
18
23
  /**
@@ -32,24 +37,30 @@ import "../../libs/v0.8.x/Bytes32Strings.sol";
32
37
  * ----------------------------------------------------------------------------
33
38
  * The following functions are restricted to the Admin ACL contract:
34
39
  * - updateArtblocksDependencyRegistryAddress
40
+ * - updateArtblocksOnChainGeneratorAddress
41
+ * - updateNextCoreContract
35
42
  * - updateProviderSalesAddresses
36
43
  * - updateProviderPrimarySalesPercentages (up to 100%)
37
- * - updateProviderSecondarySalesBPS (up to 100%)
44
+ * - updateProviderDefaultSecondarySalesBPS (up to 100%)
45
+ * - syncProviderSecondaryForProjectToDefaults
38
46
  * - updateMinterContract
39
47
  * - updateRandomizerAddress
40
- * - toggleProjectIsActive
48
+ * - toggleProjectIsActive (note: artist may be configured to activate projects)
41
49
  * - addProject
42
50
  * - forbidNewProjects (forever forbidding new projects)
43
51
  * - updateDefaultBaseURI (used to initialize new project base URIs)
52
+ * - updateSplitProvider
53
+ * - updateBytecodeStorageReaderContract
44
54
  * - updateIPFSGateway
45
55
  * - updateArweaveGateway
46
56
  * ----------------------------------------------------------------------------
47
- * The following functions are restricted to either the the Artist address or
57
+ * The following functions are restricted to either the Artist address or
48
58
  * the Admin ACL contract, only when the project is not locked:
49
59
  * - updateProjectName
50
60
  * - updateProjectArtistName
51
61
  * - updateProjectLicense
52
- * - Change project script via addProjectScript, updateProjectScript,
62
+ * - Change project script via addProjectScript, addProjectScriptCompressed,
63
+ * updateProjectScript, updateProjectScriptCompressed,
53
64
  * and removeProjectLastScript
54
65
  * - updateProjectScriptType
55
66
  * - updateProjectAspectRatio
@@ -85,8 +96,12 @@ import "../../libs/v0.8.x/Bytes32Strings.sol";
85
96
  * to projects with external asset dependencies that are unlocked:
86
97
  * - lockProjectExternalAssetDependencies
87
98
  * - updateProjectExternalAssetDependency
99
+ * - updateProjectExternalAssetDependencyOnChainCompressed
100
+ * - updateProjectAssetDependencyOnChainAtAddress
88
101
  * - removeProjectExternalAssetDependency
89
102
  * - addProjectExternalAssetDependency
103
+ * - addProjectExternalAssetDependencyOnChainCompressed
104
+ * - addProjectAssetDependencyOnChainAtAddress
90
105
  * ----------------------------------------------------------------------------
91
106
  * The following function is restricted to owner calling directly:
92
107
  * - transferOwnership
@@ -100,15 +115,19 @@ import "../../libs/v0.8.x/Bytes32Strings.sol";
100
115
  * registries, and other contracts that may interact with this core contract.
101
116
  */
102
117
  contract GenArt721CoreV3_Engine_Flex is
103
- ERC721_PackedHashSeed,
118
+ ERC721_PackedHashSeedV1,
104
119
  Ownable,
120
+ IERC2981,
105
121
  IDependencyRegistryCompatibleV0,
106
- IManifold,
107
122
  IGenArt721CoreContractV3_Engine_Flex,
123
+ IGenArt721CoreContractV3_ProjectFinance,
108
124
  IGenArt721CoreContractExposesHashSeed
109
125
  {
110
126
  using BytecodeStorageWriter for string;
127
+ using BytecodeStorageWriter for bytes;
111
128
  using Bytes32Strings for bytes32;
129
+ using Strings for uint256;
130
+ using Strings for address;
112
131
  uint256 constant ONE_HUNDRED = 100;
113
132
  uint256 constant ONE_MILLION = 1_000_000;
114
133
  uint24 constant ONE_MILLION_UINT24 = 1_000_000;
@@ -119,49 +138,16 @@ contract GenArt721CoreV3_Engine_Flex is
119
138
  uint256 constant MAX_PROVIDER_SECONDARY_SALES_BPS = 10000; // 10_000 BPS = 100%
120
139
  uint256 constant ARTIST_MAX_SECONDARY_ROYALTY_PERCENTAGE = 95; // 95%
121
140
 
122
- // This contract emits generic events that contain fields that indicate
123
- // which parameter has been updated. This is sufficient for application
124
- // state management, while also simplifying the contract and indexing code.
125
- // This was done as an alternative to having custom events that emit what
126
- // field-values have changed for each event, given that changed values can
127
- // be introspected by indexers due to the design of this smart contract
128
- // exposing these state changes via publicly viewable fields.
129
- //
130
- // The following fields are used to indicate which contract-level parameter
131
- // has been updated in the `PlatformUpdated` event:
132
- bytes32 constant FIELD_NEXT_PROJECT_ID = "nextProjectId";
133
- bytes32 constant FIELD_NEW_PROJECTS_FORBIDDEN = "newProjectsForbidden";
134
- bytes32 constant FIELD_DEFAULT_BASE_URI = "defaultBaseURI";
135
- bytes32 constant FIELD_RANDOMIZER_ADDRESS = "randomizerAddress";
136
- bytes32 constant FIELD_ARTBLOCKS_DEPENDENCY_REGISTRY_ADDRESS =
137
- "dependencyRegistryAddress";
138
- bytes32 constant FIELD_PROVIDER_SALES_ADDRESSES = "providerSalesAddresses";
139
- bytes32 constant FIELD_PROVIDER_PRIMARY_SALES_PERCENTAGES =
140
- "providerPrimaryPercentages";
141
- bytes32 constant FIELD_PROVIDER_SECONDARY_SALES_BPS =
142
- "providerSecondaryBPS";
143
- // The following fields are used to indicate which project-level parameter
144
- // has been updated in the `ProjectUpdated` event:
145
- bytes32 constant FIELD_PROJECT_COMPLETED = "completed";
146
- bytes32 constant FIELD_PROJECT_ACTIVE = "active";
147
- bytes32 constant FIELD_PROJECT_ARTIST_ADDRESS = "artistAddress";
148
- bytes32 constant FIELD_PROJECT_PAUSED = "paused";
149
- bytes32 constant FIELD_PROJECT_CREATED = "created";
150
- bytes32 constant FIELD_PROJECT_NAME = "name";
151
- bytes32 constant FIELD_PROJECT_ARTIST_NAME = "artistName";
152
- bytes32 constant FIELD_PROJECT_SECONDARY_MARKET_ROYALTY_PERCENTAGE =
153
- "royaltyPercentage";
154
- bytes32 constant FIELD_PROJECT_DESCRIPTION = "description";
155
- bytes32 constant FIELD_PROJECT_WEBSITE = "website";
156
- bytes32 constant FIELD_PROJECT_LICENSE = "license";
157
- bytes32 constant FIELD_PROJECT_MAX_INVOCATIONS = "maxInvocations";
158
- bytes32 constant FIELD_PROJECT_SCRIPT = "script";
159
- bytes32 constant FIELD_PROJECT_SCRIPT_TYPE = "scriptType";
160
- bytes32 constant FIELD_PROJECT_ASPECT_RATIO = "aspectRatio";
161
- bytes32 constant FIELD_PROJECT_BASE_URI = "baseURI";
141
+ /// pointer to next core contract associated with this contract
142
+ address public nextCoreContract;
162
143
 
163
144
  /// Dependency registry managed by Art Blocks
164
145
  address public artblocksDependencyRegistryAddress;
146
+ /// On chain generator managed by Art Blocks
147
+ address public artblocksOnChainGeneratorAddress;
148
+
149
+ /// ensure initialization can only be performed once
150
+ bool private _initialized;
165
151
 
166
152
  /// current randomizer contract
167
153
  IRandomizer_V3CoreBase public randomizerContract;
@@ -191,30 +177,14 @@ contract GenArt721CoreV3_Engine_Flex is
191
177
  string aspectRatio;
192
178
  // mapping from script index to address storing script in bytecode
193
179
  mapping(uint256 => address) scriptBytecodeAddresses;
194
- bool externalAssetDependenciesLocked;
195
- uint24 externalAssetDependencyCount;
196
- mapping(uint256 => ExternalAssetDependency) externalAssetDependencies;
197
180
  }
198
181
 
199
182
  mapping(uint256 => Project) projects;
200
183
 
201
- string public preferredIPFSGateway;
202
- string public preferredArweaveGateway;
203
-
204
- /// packed struct containing project financial information
205
- struct ProjectFinance {
206
- address payable additionalPayeePrimarySales;
207
- // packed uint: max of 95, max uint8 = 255
208
- uint8 secondaryMarketRoyaltyPercentage;
209
- address payable additionalPayeeSecondarySales;
210
- // packed uint: max of 100, max uint8 = 255
211
- uint8 additionalPayeeSecondarySalesPercentage;
212
- address payable artistAddress;
213
- // packed uint: max of 100, max uint8 = 255
214
- uint8 additionalPayeePrimarySalesPercentage;
215
- }
216
- // Project financials mapping
217
- mapping(uint256 => ProjectFinance) projectIdToFinancials;
184
+ /// private mapping from project ID to project financial information. See
185
+ /// `projectIdToFinancials` getter for public access.
186
+ mapping(uint256 _projectId => ProjectFinance)
187
+ private _projectIdToFinancials;
218
188
 
219
189
  /// hash of artist's proposed payment updates to be approved by admin
220
190
  mapping(uint256 => bytes32) public proposedArtistAddressesAndSplitsHash;
@@ -225,33 +195,54 @@ contract GenArt721CoreV3_Engine_Flex is
225
195
  /// Percentage of primary sales revenue allocated to the render provider
226
196
  /// (packed)
227
197
  // packed uint: max of 100, max uint8 = 255
228
- uint8 private _renderProviderPrimarySalesPercentage = 10;
198
+ uint8 private _renderProviderPrimarySalesPercentage;
229
199
  /// The platform provider payment address for all primary sales revenues
230
200
  /// (packed)
231
201
  address payable public platformProviderPrimarySalesAddress;
232
202
  /// Percentage of primary sales revenue allocated to the platform provider
233
203
  /// (packed)
234
204
  // packed uint: max of 100, max uint8 = 255
235
- uint8 private _platformProviderPrimarySalesPercentage = 10;
236
-
237
- /// The render provider payment address for all secondary sales royalty
238
- /// revenues
239
- address payable public renderProviderSecondarySalesAddress;
240
- /// Basis Points of secondary sales royalties allocated to the
241
- /// render provider
242
- uint256 public renderProviderSecondarySalesBPS = 250;
243
- /// The platform provider payment address for all secondary sales royalty
244
- /// revenues
245
- address payable public platformProviderSecondarySalesAddress;
246
- /// Basis Points of secondary sales royalties allocated to the
247
- /// platform provider
248
- uint256 public platformProviderSecondarySalesBPS = 250;
205
+ uint8 private _platformProviderPrimarySalesPercentage;
206
+
207
+ /// @dev Note on "default" provider secondary values - the only way these can
208
+ /// be different on a per project basis is if admin updates these and then
209
+ /// does not call syncProviderSecondaryForProjectToDefaults for the project.
210
+ /// -----------------------------------------------------------------------
211
+ /// The default render provider payment address for all secondary sales royalty
212
+ /// revenues, for all new projects. Individual project payment info is defined
213
+ /// in each project's ProjectFinance struct.
214
+ /// Projects can be updated to this value by calling the
215
+ /// `syncProviderSecondaryForProjectToDefaults` function for each project.
216
+ address payable public defaultRenderProviderSecondarySalesAddress;
217
+ /// The default basis points allocated to render provider for all secondary
218
+ /// sales royalty revenues, for all new projects. Individual project
219
+ /// payment info is defined in each project's ProjectFinance struct.
220
+ /// Projects can be updated to this value by calling the
221
+ /// `syncProviderSecondaryForProjectToDefaults` function for each project.
222
+ uint256 public defaultRenderProviderSecondarySalesBPS;
223
+ /// The default platform provider payment address for all secondary sales royalty
224
+ /// revenues, for all new projects. Individual project payment info is defined
225
+ /// in each project's ProjectFinance struct.
226
+ /// Projects can be updated to this value by calling the
227
+ /// `syncProviderSecondaryForProjectToDefaults` function for each project.
228
+ address payable public defaultPlatformProviderSecondarySalesAddress;
229
+ /// The default basis points allocated to platform provider for all secondary
230
+ /// sales royalty revenues, for all new projects. Individual project
231
+ /// payment info is defined in each project's ProjectFinance struct.
232
+ /// Projects can be updated to this value by calling the
233
+ /// `syncProviderSecondaryForProjectToDefaults` function for each project.
234
+ uint256 public defaultPlatformProviderSecondarySalesBPS;
235
+ /// -----------------------------------------------------------------------
249
236
 
250
237
  /// single minter allowed for this core contract
251
238
  address public minterContract;
252
239
 
253
- /// starting (initial) project ID on this contract
254
- uint256 public immutable startingProjectId;
240
+ /// starting (initial) project ID on this contract configured
241
+ /// at time of deployment and intended to be immutable after initialization.
242
+ /// Not marked as immutable due to initialization requirements
243
+ /// under the ERC-1167 minimal proxy pattern, which necessitates
244
+ /// setting this value post-deployment.
245
+ uint256 public startingProjectId;
255
246
 
256
247
  /// next project ID to be created
257
248
  uint248 private _nextProjectId;
@@ -260,19 +251,39 @@ contract GenArt721CoreV3_Engine_Flex is
260
251
  /// default behavior is to allow new projects
261
252
  bool public newProjectsForbidden;
262
253
 
263
- /// configuration variable (determined at time of deployment)
264
- /// that determines whether or not admin approval^ should be required
265
- /// to accept artist address change proposals, or if these proposals
266
- /// should always auto-approve, as determined by the business process
267
- /// requirements of the Engine partner using this contract.
254
+ /// configuration variable set at time of deployment, intended to be
255
+ /// immutable after initialization, that determines whether or not
256
+ /// admin approval^ should be required to accept artist address change
257
+ /// proposals, or if these proposals should always auto-approve, as
258
+ /// determined by the business process requirements of the Engine
259
+ /// partner using this contract.
268
260
  ///
269
261
  /// ^does not apply in the case where contract-ownership itself is revoked
270
- bool public immutable autoApproveArtistSplitProposals;
262
+ /// Not marked as immutable due to initialization requirements
263
+ /// under the ERC-1167 minimal proxy pattern, which necessitates
264
+ /// setting this value post-deployment.
265
+ bool public autoApproveArtistSplitProposals;
266
+
267
+ /// configuration variable set at time of deployment, intended to be
268
+ /// immutable after initialization, that determines if platform provider
269
+ /// fees and addresses are always required to be set to zero.
270
+ /// Not marked as immutable due to initialization requirements
271
+ /// under the ERC-1167 minimal proxy pattern, which necessitates
272
+ /// setting this value post-deployment.
273
+ bool public nullPlatformProvider;
274
+
275
+ /// configuration variable set at time of deployment, intended to be
276
+ /// immutable after initialization, that determines if artists are allowed
277
+ /// to activate their own projects.
278
+ /// Not marked as immutable due to initialization requirements
279
+ /// under the ERC-1167 minimal proxy pattern, which necessitates
280
+ /// setting this value post-deployment.
281
+ bool public allowArtistProjectActivation;
271
282
 
272
283
  /// version & type of this core contract
273
- bytes32 constant CORE_VERSION = "v3.1.4";
284
+ bytes32 constant CORE_VERSION = "v3.2.5";
274
285
 
275
- function coreVersion() external pure returns (string memory) {
286
+ function coreVersion() external pure virtual returns (string memory) {
276
287
  return CORE_VERSION.toString();
277
288
  }
278
289
 
@@ -285,63 +296,87 @@ contract GenArt721CoreV3_Engine_Flex is
285
296
  /// default base URI to initialize all new project projectBaseURI values to
286
297
  string public defaultBaseURI;
287
298
 
288
- function _onlyUnlockedProjectExternalAssetDependencies(
289
- uint256 _projectId
290
- ) internal view {
291
- require(
292
- !projects[_projectId].externalAssetDependenciesLocked,
293
- "External dependencies locked"
294
- );
295
- }
299
+ // ERC2981 royalty support and default royalty values
300
+ bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;
301
+ uint8 private constant _DEFAULT_ARTIST_SECONDARY_ROYALTY_PERCENTAGE = 5;
302
+
303
+ // royalty split provider
304
+ ISplitProviderV0 public splitProvider;
305
+
306
+ // bytecode storage reader contract; may be universal or specific version reader contract
307
+ IBytecodeStorageReader_Base public bytecodeStorageReaderContract;
308
+
309
+ /**
310
+ * @dev This constructor sets the owner to a non-functional address as a formality.
311
+ * It is only ever ran on the implementation contract. The `Ownable` constructor is
312
+ * called to satisfy the contract's inheritance requirements. This owner has no
313
+ * operational significance and should not be considered secure or meaningful.
314
+ * The true ownership will be set in the `initialize` function post-deployment to
315
+ * ensure correct owner management in the proxy architecture.
316
+ * Explicitly setting the owner to '0xdead' to indicate non-operational use.
317
+ */
318
+ constructor() Ownable(0x000000000000000000000000000000000000dEaD) {}
296
319
 
297
320
  function _onlyNonZeroAddress(address _address) internal pure {
298
- require(_address != address(0), "Must input non-zero address");
321
+ if (_address == address(0)) {
322
+ revert GenArt721Error(ErrorCodes.OnlyNonZeroAddress);
323
+ }
299
324
  }
300
325
 
301
326
  function _onlyNonEmptyString(string memory _string) internal pure {
302
- require(bytes(_string).length != 0, "Must input non-empty string");
327
+ if (bytes(_string).length == 0) {
328
+ revert GenArt721Error(ErrorCodes.OnlyNonEmptyString);
329
+ }
330
+ }
331
+
332
+ function _onlyNonEmptyBytes(bytes memory _bytes) internal pure {
333
+ if (_bytes.length == 0) {
334
+ revert GenArt721Error(ErrorCodes.OnlyNonEmptyBytes);
335
+ }
303
336
  }
304
337
 
305
338
  function _onlyValidTokenId(uint256 _tokenId) internal view {
306
- require(_exists(_tokenId), "Token ID does not exist");
339
+ if (_ownerOf(_tokenId) == address(0)) {
340
+ revert GenArt721Error(ErrorCodes.TokenDoesNotExist);
341
+ }
307
342
  }
308
343
 
309
344
  function _onlyValidProjectId(uint256 _projectId) internal view {
310
- require(
311
- (_projectId >= startingProjectId) && (_projectId < _nextProjectId),
312
- "Project ID does not exist"
313
- );
345
+ if (_projectId < startingProjectId || _projectId >= _nextProjectId) {
346
+ revert GenArt721Error(ErrorCodes.ProjectDoesNotExist);
347
+ }
314
348
  }
315
349
 
316
350
  function _onlyUnlocked(uint256 _projectId) internal view {
317
351
  // Note: calling `_projectUnlocked` enforces that the `_projectId`
318
352
  // passed in is valid.`
319
- require(_projectUnlocked(_projectId), "Only if unlocked");
353
+ if (!_projectUnlocked(_projectId)) {
354
+ revert GenArt721Error(ErrorCodes.OnlyUnlockedProjects);
355
+ }
320
356
  }
321
357
 
322
358
  function _onlyAdminACL(bytes4 _selector) internal {
323
- require(
324
- adminACLAllowed(msg.sender, address(this), _selector),
325
- "Only Admin ACL allowed"
326
- );
359
+ if (!adminACLAllowed(msg.sender, address(this), _selector)) {
360
+ revert GenArt721Error(ErrorCodes.OnlyAdminACL);
361
+ }
327
362
  }
328
363
 
329
364
  function _onlyArtist(uint256 _projectId) internal view {
330
- require(
331
- msg.sender == projectIdToFinancials[_projectId].artistAddress,
332
- "Only artist"
333
- );
365
+ if (msg.sender != _projectIdToFinancials[_projectId].artistAddress) {
366
+ revert GenArt721Error(ErrorCodes.OnlyArtist);
367
+ }
334
368
  }
335
369
 
336
370
  function _onlyArtistOrAdminACL(
337
371
  uint256 _projectId,
338
372
  bytes4 _selector
339
373
  ) internal {
340
- require(
341
- msg.sender == projectIdToFinancials[_projectId].artistAddress ||
342
- adminACLAllowed(msg.sender, address(this), _selector),
343
- "Only artist or Admin ACL allowed"
344
- );
374
+ if (
375
+ !(msg.sender == _projectIdToFinancials[_projectId].artistAddress ||
376
+ adminACLAllowed(msg.sender, address(this), _selector))
377
+ ) {
378
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminACL);
379
+ }
345
380
  }
346
381
 
347
382
  /**
@@ -354,71 +389,50 @@ contract GenArt721CoreV3_Engine_Flex is
354
389
  uint256 _projectId,
355
390
  bytes4 _selector
356
391
  ) internal {
357
- require(
358
- adminACLAllowed(msg.sender, address(this), _selector) ||
359
- (owner() == address(0) &&
360
- msg.sender ==
361
- projectIdToFinancials[_projectId].artistAddress),
362
- "Only Admin ACL allowed, or artist if owner has renounced"
363
- );
392
+ // check if Admin ACL is allowed to call this function
393
+ if (adminACLAllowed(msg.sender, address(this), _selector)) {
394
+ return;
395
+ }
396
+ // check if the owner has renounced ownership and the caller is the
397
+ // artist of the project
398
+ if (
399
+ owner() == address(0) &&
400
+ msg.sender == _projectIdToFinancials[_projectId].artistAddress
401
+ ) {
402
+ return;
403
+ }
404
+ // neither of the above conditions were met, revert
405
+ revert GenArt721Error(ErrorCodes.OnlyAdminACLOrRenouncedArtist);
364
406
  }
365
407
 
366
408
  /**
367
- * @notice Initializes contract.
368
- * @param _tokenName Name of token.
369
- * @param _tokenSymbol Token symbol.
370
- * @param _randomizerContract Randomizer contract.
371
- * @param _adminACLContract Address of admin access control contract, to be
409
+ * @notice Initializes the contract with the provided `engineConfiguration`.
410
+ * This function should be called atomically, immediately after deployment.
411
+ * Only callable once. Validation on `engineConfiguration` is performed by caller.
412
+ * @dev This function is intentionally unpermissioned to allow for the
413
+ * initialization of the contract post-deployment. It is expected that this
414
+ * function will be called atomically by the factory contract that deploys this
415
+ * contract, after which it will be initialized and uncallable.
416
+ * @param engineConfiguration EngineConfiguration to configure the contract with.
417
+ * note: parameter `engineConfiguration.newSuperAdminAddress` is not used or operated on in this contract.
418
+ * @param adminACLContract_ Address of admin access control contract, to be
372
419
  * set as contract owner.
373
- * @param _startingProjectId The initial next project ID.
374
- * @param _autoApproveArtistSplitProposals Whether or not to always
375
- * auto-approve proposed artist split updates.
376
- * @dev _startingProjectId should be set to a value much, much less than
377
- * max(uint248), but an explicit input type of `uint248` is used as it is
378
- * safer to cast up to `uint256` than it is to cast down for the purposes
379
- * of setting `_nextProjectId`.
380
- */
381
- constructor(
382
- string memory _tokenName,
383
- string memory _tokenSymbol,
384
- address _renderProviderAddress,
385
- address _platformProviderAddress,
386
- address _randomizerContract,
387
- address _adminACLContract,
388
- uint248 _startingProjectId,
389
- bool _autoApproveArtistSplitProposals
390
- ) ERC721_PackedHashSeed(_tokenName, _tokenSymbol) {
391
- _onlyNonZeroAddress(_renderProviderAddress);
392
- _onlyNonZeroAddress(_platformProviderAddress);
393
- _onlyNonZeroAddress(_randomizerContract);
394
- _onlyNonZeroAddress(_adminACLContract);
395
- // setup immutable `autoApproveArtistSplitProposals` config
396
- autoApproveArtistSplitProposals = _autoApproveArtistSplitProposals;
397
- // record contracts starting project ID
398
- // casting-up is safe
399
- startingProjectId = uint256(_startingProjectId);
400
- _updateProviderSalesAddresses(
401
- _renderProviderAddress,
402
- _renderProviderAddress,
403
- _platformProviderAddress,
404
- _platformProviderAddress
405
- );
406
- _updateRandomizerAddress(_randomizerContract);
407
- // set AdminACL management contract as owner
408
- _transferOwnership(_adminACLContract);
409
- // initialize default base URI
410
- _updateDefaultBaseURI(
411
- string.concat(
412
- "https://token.artblocks.io/",
413
- toHexString(address(this)),
414
- "/"
415
- )
416
- );
417
- // initialize next project ID
418
- _nextProjectId = _startingProjectId;
419
- emit PlatformUpdated(FIELD_NEXT_PROJECT_ID);
420
- // @dev follow-on action: This contract does not self-register. A core
421
- // registry owner must register contract in a subsequent call.
420
+ * @param defaultBaseURIHost Base URI prefix to initialize default base URI with.
421
+ * @param bytecodeStorageReaderContract_ Address of the bytecode storage reader contract.
422
+ */
423
+ function initialize(
424
+ EngineConfiguration memory engineConfiguration,
425
+ address adminACLContract_,
426
+ string memory defaultBaseURIHost,
427
+ address bytecodeStorageReaderContract_
428
+ ) external virtual {
429
+ // @dev internal function call so derived contracts have access to initialization logic
430
+ _initialize({
431
+ engineConfiguration: engineConfiguration,
432
+ adminACLContract_: adminACLContract_,
433
+ defaultBaseURIHost: defaultBaseURIHost,
434
+ bytecodeStorageReaderContract_: bytecodeStorageReaderContract_
435
+ });
422
436
  }
423
437
 
424
438
  /**
@@ -426,8 +440,7 @@ contract GenArt721CoreV3_Engine_Flex is
426
440
  */
427
441
  function updateIPFSGateway(string calldata _gateway) public {
428
442
  _onlyAdminACL(this.updateIPFSGateway.selector);
429
- preferredIPFSGateway = _gateway;
430
- emit GatewayUpdated(ExternalAssetDependencyType.IPFS, _gateway);
443
+ V3FlexLib.updateIPFSGateway({_gateway: _gateway});
431
444
  }
432
445
 
433
446
  /**
@@ -435,32 +448,34 @@ contract GenArt721CoreV3_Engine_Flex is
435
448
  */
436
449
  function updateArweaveGateway(string calldata _gateway) public {
437
450
  _onlyAdminACL(this.updateArweaveGateway.selector);
438
- preferredArweaveGateway = _gateway;
439
- emit GatewayUpdated(ExternalAssetDependencyType.ARWEAVE, _gateway);
451
+ V3FlexLib.updateArweaveGateway({_gateway: _gateway});
440
452
  }
441
453
 
442
454
  /**
443
455
  * @notice Locks external asset dependencies for project `_projectId`.
444
456
  */
445
457
  function lockProjectExternalAssetDependencies(uint256 _projectId) external {
446
- _onlyUnlockedProjectExternalAssetDependencies(_projectId);
447
458
  _onlyArtistOrAdminACL(
448
459
  _projectId,
449
460
  this.lockProjectExternalAssetDependencies.selector
450
461
  );
451
- projects[_projectId].externalAssetDependenciesLocked = true;
452
- emit ProjectExternalAssetDependenciesLocked(_projectId);
462
+ V3FlexLib.lockProjectExternalAssetDependencies({
463
+ _projectId: _projectId
464
+ });
453
465
  }
454
466
 
455
467
  /**
456
468
  * @notice Updates external asset dependency for project `_projectId`.
457
469
  * @param _projectId Project to be updated.
458
470
  * @param _index Asset index.
459
- * @param _cidOrData Asset cid (Content identifier) or data string to be translated into bytecode.
471
+ * @param _cidOrData Field that contains the CID of the dependency if IPFS or ARWEAVE,
472
+ * empty string of ONCHAIN, or a string representation of the Art Blocks Dependency
473
+ * Registry's `dependencyNameAndVersion` if ART_BLOCKS_DEPENDENCY_REGISTRY.
460
474
  * @param _dependencyType Asset dependency type.
461
475
  * 0 - IPFS
462
476
  * 1 - ARWEAVE
463
477
  * 2 - ONCHAIN
478
+ * 3 - ART_BLOCKS_DEPENDENCY_REGISTRY
464
479
  */
465
480
  function updateProjectExternalAssetDependency(
466
481
  uint256 _projectId,
@@ -468,51 +483,73 @@ contract GenArt721CoreV3_Engine_Flex is
468
483
  string memory _cidOrData,
469
484
  ExternalAssetDependencyType _dependencyType
470
485
  ) external {
471
- _onlyUnlockedProjectExternalAssetDependencies(_projectId);
472
486
  _onlyArtistOrAdminACL(
473
487
  _projectId,
474
488
  this.updateProjectExternalAssetDependency.selector
475
489
  );
476
- uint24 assetCount = projects[_projectId].externalAssetDependencyCount;
477
- require(_index < assetCount, "Asset index out of range");
478
- ExternalAssetDependency storage _oldDependency = projects[_projectId]
479
- .externalAssetDependencies[_index];
480
- ExternalAssetDependencyType _oldDependencyType = _oldDependency
481
- .dependencyType;
482
- projects[_projectId]
483
- .externalAssetDependencies[_index]
484
- .dependencyType = _dependencyType;
485
- // if the incoming dependency type is onchain, we need to write the data to bytecode
486
- if (_dependencyType == ExternalAssetDependencyType.ONCHAIN) {
487
- if (_oldDependencyType != ExternalAssetDependencyType.ONCHAIN) {
488
- // we only need to set the cid to an empty string if we are replacing an offchain asset
489
- // an onchain asset will already have an empty cid
490
- projects[_projectId].externalAssetDependencies[_index].cid = "";
491
- }
490
+ V3FlexLib.updateProjectExternalAssetDependency({
491
+ _projectId: _projectId,
492
+ _index: _index,
493
+ _cidOrData: _cidOrData,
494
+ _dependencyType: _dependencyType
495
+ });
496
+ }
492
497
 
493
- projects[_projectId]
494
- .externalAssetDependencies[_index]
495
- .bytecodeAddress = _cidOrData.writeToBytecode();
496
- // we don't want to emit data, so we emit the cid as an empty string
497
- _cidOrData = "";
498
- } else {
499
- projects[_projectId]
500
- .externalAssetDependencies[_index]
501
- .cid = _cidOrData;
502
- }
503
- emit ExternalAssetDependencyUpdated(
498
+ /**
499
+ * @notice Updates external asset dependency for project `_projectId` of type
500
+ * ONCHAIN using on-chain compression. The string should be compressed using
501
+ * `getCompressed`.
502
+ * This function stores the string in a compressed format on-chain.
503
+ * For reads, the compressed script is decompressed on-chain, ensuring the
504
+ * original text is reconstructed without external dependencies.
505
+ * @dev _compressedString in memory to minimize bytecode size.
506
+ * @param _projectId Project to be updated.
507
+ * @param _index Asset index.
508
+ * @param _compressedString Pre-compressed string asset to be added.
509
+ */
510
+ function updateProjectExternalAssetDependencyOnChainCompressed(
511
+ uint256 _projectId,
512
+ uint256 _index,
513
+ bytes memory _compressedString
514
+ ) external {
515
+ _onlyArtistOrAdminACL(
504
516
  _projectId,
505
- _index,
506
- _cidOrData,
507
- _dependencyType,
508
- assetCount
517
+ this.updateProjectExternalAssetDependencyOnChainCompressed.selector
509
518
  );
519
+ V3FlexLib.updateProjectExternalAssetDependencyOnChainCompressed({
520
+ _projectId: _projectId,
521
+ _index: _index,
522
+ _compressedString: _compressedString
523
+ });
524
+ }
525
+
526
+ /**
527
+ * @notice Updates external asset dependency for project `_projectId` at
528
+ * index `_index`, with data at BytecodeStorage-compatible address
529
+ * `_assetAddress`.
530
+ * @param _projectId Project to be updated.
531
+ * @param _index Asset index.
532
+ * @param _assetAddress Address of the on-chain asset.
533
+ */
534
+ function updateProjectAssetDependencyOnChainAtAddress(
535
+ uint256 _projectId,
536
+ uint256 _index,
537
+ address _assetAddress
538
+ ) external {
539
+ _onlyArtistOrAdminACL(
540
+ _projectId,
541
+ this.updateProjectAssetDependencyOnChainAtAddress.selector
542
+ );
543
+ V3FlexLib.updateProjectAssetDependencyOnChainAtAddress({
544
+ _projectId: _projectId,
545
+ _index: _index,
546
+ _assetAddress: _assetAddress
547
+ });
510
548
  }
511
549
 
512
550
  /**
513
551
  * @notice Removes external asset dependency for project `_projectId` at index `_index`.
514
- * Removal is done by swapping the element to be removed with the last element in the array, then deleting this last element.
515
- * Assets with indices higher than `_index` can have their indices adjusted as a result of this operation.
552
+ * As of v3.2, only allow removal of dependency at last index, for UX purposes.
516
553
  * @param _projectId Project to be updated.
517
554
  * @param _index Asset index
518
555
  */
@@ -520,70 +557,88 @@ contract GenArt721CoreV3_Engine_Flex is
520
557
  uint256 _projectId,
521
558
  uint256 _index
522
559
  ) external {
523
- _onlyUnlockedProjectExternalAssetDependencies(_projectId);
524
560
  _onlyArtistOrAdminACL(
525
561
  _projectId,
526
562
  this.removeProjectExternalAssetDependency.selector
527
563
  );
528
- uint24 assetCount = projects[_projectId].externalAssetDependencyCount;
529
- require(_index < assetCount, "Asset index out of range");
530
-
531
- uint24 lastElementIndex = assetCount - 1;
532
-
533
- // copy last element to index of element to be removed
534
- projects[_projectId].externalAssetDependencies[_index] = projects[
535
- _projectId
536
- ].externalAssetDependencies[lastElementIndex];
537
-
538
- delete projects[_projectId].externalAssetDependencies[lastElementIndex];
539
-
540
- projects[_projectId].externalAssetDependencyCount = lastElementIndex;
541
-
542
- emit ExternalAssetDependencyRemoved(_projectId, _index);
564
+ V3FlexLib.removeProjectExternalAssetDependency({
565
+ _projectId: _projectId,
566
+ _index: _index
567
+ });
543
568
  }
544
569
 
545
570
  /**
546
571
  * @notice Adds external asset dependency for project `_projectId`.
547
572
  * @param _projectId Project to be updated.
548
- * @param _cidOrData Asset cid (Content identifier) or data string to be translated into bytecode.
573
+ * @param _cidOrData Field that contains the CID of the dependency if IPFS or ARWEAVE,
574
+ * empty string of ONCHAIN, or a string representation of the Art Blocks Dependency
575
+ * Registry's `dependencyNameAndVersion` if ART_BLOCKS_DEPENDENCY_REGISTRY.
549
576
  * @param _dependencyType Asset dependency type.
550
577
  * 0 - IPFS
551
578
  * 1 - ARWEAVE
552
579
  * 2 - ONCHAIN
580
+ * 3 - ART_BLOCKS_DEPENDENCY_REGISTRY
553
581
  */
554
582
  function addProjectExternalAssetDependency(
555
583
  uint256 _projectId,
556
584
  string memory _cidOrData,
557
585
  ExternalAssetDependencyType _dependencyType
558
586
  ) external {
559
- _onlyUnlockedProjectExternalAssetDependencies(_projectId);
560
587
  _onlyArtistOrAdminACL(
561
588
  _projectId,
562
589
  this.addProjectExternalAssetDependency.selector
563
590
  );
564
- uint24 assetCount = projects[_projectId].externalAssetDependencyCount;
565
- address _bytecodeAddress = address(0);
566
- // if the incoming dependency type is onchain, we need to write the data to bytecode
567
- if (_dependencyType == ExternalAssetDependencyType.ONCHAIN) {
568
- _bytecodeAddress = _cidOrData.writeToBytecode();
569
- // we don't want to emit data, so we emit the cid as an empty string
570
- _cidOrData = "";
571
- }
572
- ExternalAssetDependency memory asset = ExternalAssetDependency({
573
- cid: _cidOrData,
574
- dependencyType: _dependencyType,
575
- bytecodeAddress: _bytecodeAddress
591
+ V3FlexLib.addProjectExternalAssetDependency({
592
+ _projectId: _projectId,
593
+ _cidOrData: _cidOrData,
594
+ _dependencyType: _dependencyType
576
595
  });
577
- projects[_projectId].externalAssetDependencies[assetCount] = asset;
578
- projects[_projectId].externalAssetDependencyCount = assetCount + 1;
596
+ }
579
597
 
580
- emit ExternalAssetDependencyUpdated(
598
+ /**
599
+ * @notice Adds external asset dependency for project `_projectId` of type
600
+ * ONCHAIN using on-chain compression. The string should be compressed using
601
+ * `getCompressed`.
602
+ * This function stores the string in a compressed format on-chain.
603
+ * For reads, the compressed script is decompressed on-chain, ensuring the
604
+ * original text is reconstructed without external dependencies.
605
+ * @dev _compressedString in memory to minimize bytecode size.
606
+ * @param _projectId Project to be updated.
607
+ * @param _compressedString Pre-compressed string asset to be added.
608
+ */
609
+ function addProjectExternalAssetDependencyOnChainCompressed(
610
+ uint256 _projectId,
611
+ bytes memory _compressedString
612
+ ) external {
613
+ _onlyArtistOrAdminACL(
614
+ _projectId,
615
+ this.addProjectExternalAssetDependencyOnChainCompressed.selector
616
+ );
617
+ V3FlexLib.addProjectExternalAssetDependencyOnChainCompressed({
618
+ _projectId: _projectId,
619
+ _compressedString: _compressedString
620
+ });
621
+ }
622
+
623
+ /**
624
+ * @notice Adds an on-chain external asset dependency for project
625
+ * `_projectId`, with data at BytecodeStorage-compatible address
626
+ * `_assetAddress`.
627
+ * @param _projectId Project to be updated.
628
+ * @param _assetAddress Address of the BytecodeStorageReader-compatible on-chain asset.
629
+ */
630
+ function addProjectAssetDependencyOnChainAtAddress(
631
+ uint256 _projectId,
632
+ address _assetAddress
633
+ ) external {
634
+ _onlyArtistOrAdminACL(
581
635
  _projectId,
582
- assetCount,
583
- _cidOrData,
584
- _dependencyType,
585
- assetCount + 1
636
+ this.addProjectAssetDependencyOnChainAtAddress.selector
586
637
  );
638
+ V3FlexLib.addProjectAssetDependencyOnChainAtAddress({
639
+ _projectId: _projectId,
640
+ _assetAddress: _assetAddress
641
+ });
587
642
  }
588
643
 
589
644
  /**
@@ -603,7 +658,9 @@ contract GenArt721CoreV3_Engine_Flex is
603
658
  address _by
604
659
  ) external returns (uint256 _tokenId) {
605
660
  // CHECKS
606
- require(msg.sender == minterContract, "Must mint from minter contract");
661
+ if (msg.sender != minterContract) {
662
+ revert GenArt721Error(ErrorCodes.OnlyMinterContract);
663
+ }
607
664
  Project storage project = projects[_projectId];
608
665
  // load invocations into memory
609
666
  uint24 invocationsBefore = project.invocations;
@@ -614,21 +671,21 @@ contract GenArt721CoreV3_Engine_Flex is
614
671
  invocationsAfter = invocationsBefore + 1;
615
672
  }
616
673
  uint24 maxInvocations = project.maxInvocations;
617
-
618
- require(
619
- invocationsBefore < maxInvocations,
620
- "Must not exceed max invocations"
621
- );
622
- require(
623
- project.active ||
624
- _by == projectIdToFinancials[_projectId].artistAddress,
625
- "Project must exist and be active"
626
- );
627
- require(
628
- !project.paused ||
629
- _by == projectIdToFinancials[_projectId].artistAddress,
630
- "Purchases are paused."
631
- );
674
+ if (invocationsBefore >= maxInvocations) {
675
+ revert GenArt721Error(ErrorCodes.MaxInvocationsReached);
676
+ }
677
+ if (
678
+ !(project.active ||
679
+ _by == _projectIdToFinancials[_projectId].artistAddress)
680
+ ) {
681
+ revert GenArt721Error(ErrorCodes.ProjectMustExistAndBeActive);
682
+ }
683
+ if (
684
+ project.paused &&
685
+ _by != _projectIdToFinancials[_projectId].artistAddress
686
+ ) {
687
+ revert GenArt721Error(ErrorCodes.PurchasesPaused);
688
+ }
632
689
 
633
690
  // EFFECTS
634
691
  // increment project's invocations
@@ -680,15 +737,15 @@ contract GenArt721CoreV3_Engine_Flex is
680
737
  OwnerAndHashSeed storage ownerAndHashSeed = _ownersAndHashSeeds[
681
738
  _tokenId
682
739
  ];
683
- require(
684
- msg.sender == address(randomizerContract),
685
- "Only randomizer may set"
686
- );
687
- require(
688
- ownerAndHashSeed.hashSeed == bytes12(0),
689
- "Token hash already set"
690
- );
691
- require(_hashSeed != bytes12(0), "No zero hash seed");
740
+ if (msg.sender != address(randomizerContract)) {
741
+ revert GenArt721Error(ErrorCodes.OnlyRandomizer);
742
+ }
743
+ if (ownerAndHashSeed.hashSeed != bytes12(0)) {
744
+ revert GenArt721Error(ErrorCodes.TokenHashAlreadySet);
745
+ }
746
+ if (_hashSeed == bytes12(0)) {
747
+ revert GenArt721Error(ErrorCodes.NoZeroHashSeed);
748
+ }
692
749
  ownerAndHashSeed.hashSeed = bytes12(_hashSeed);
693
750
  }
694
751
 
@@ -719,6 +776,18 @@ contract GenArt721CoreV3_Engine_Flex is
719
776
  Ownable.renounceOwnership();
720
777
  }
721
778
 
779
+ /**
780
+ * @notice Updates reference to next core contract, associated with this contract.
781
+ * @param _nextCoreContract Address of the next core contract
782
+ */
783
+ function updateNextCoreContract(address _nextCoreContract) external {
784
+ _onlyAdminACL(this.updateNextCoreContract.selector);
785
+ nextCoreContract = _nextCoreContract;
786
+ emit PlatformUpdated(
787
+ bytes32(uint256(PlatformUpdatedFields.FIELD_NEXT_CORE_CONTRACT))
788
+ );
789
+ }
790
+
722
791
  /**
723
792
  * @notice Updates reference to Art Blocks Dependency Registry contract.
724
793
  * @param _artblocksDependencyRegistryAddress Address of new Dependency
@@ -730,43 +799,74 @@ contract GenArt721CoreV3_Engine_Flex is
730
799
  _onlyAdminACL(this.updateArtblocksDependencyRegistryAddress.selector);
731
800
  _onlyNonZeroAddress(_artblocksDependencyRegistryAddress);
732
801
  artblocksDependencyRegistryAddress = _artblocksDependencyRegistryAddress;
733
- emit PlatformUpdated(FIELD_ARTBLOCKS_DEPENDENCY_REGISTRY_ADDRESS);
802
+ emit PlatformUpdated(
803
+ bytes32(
804
+ uint256(
805
+ PlatformUpdatedFields
806
+ .FIELD_ARTBLOCKS_DEPENDENCY_REGISTRY_ADDRESS
807
+ )
808
+ )
809
+ );
810
+ }
811
+
812
+ /**
813
+ * @notice Updates reference to Art Blocks On Chain Generator contract.
814
+ * @param _artblocksOnChainGeneratorAddress Address of new on chain generator.
815
+ */
816
+ function updateArtblocksOnChainGeneratorAddress(
817
+ address _artblocksOnChainGeneratorAddress
818
+ ) external {
819
+ _onlyAdminACL(this.updateArtblocksOnChainGeneratorAddress.selector);
820
+ _onlyNonZeroAddress(_artblocksOnChainGeneratorAddress);
821
+ artblocksOnChainGeneratorAddress = _artblocksOnChainGeneratorAddress;
822
+ emit PlatformUpdated(
823
+ bytes32(
824
+ uint256(
825
+ PlatformUpdatedFields
826
+ .FIELD_ARTBLOCKS_ON_CHAIN_GENERATOR_ADDRESS
827
+ )
828
+ )
829
+ );
734
830
  }
735
831
 
736
832
  /**
737
833
  * @notice Updates sales addresses for the platform and render providers to
738
834
  * the input parameters.
835
+ * note: This does not update splitter contracts for all projects on
836
+ * this core contract. If updated splitter contracts are desired, they must be
837
+ * updated after this update via the `syncProviderSecondaryForProjectToDefaults` function.
739
838
  * @param _renderProviderPrimarySalesAddress Address of new primary sales
740
839
  * payment address.
741
- * @param _renderProviderSecondarySalesAddress Address of new secondary sales
840
+ * @param _defaultRenderProviderSecondarySalesAddress Default address of new secondary sales
742
841
  * payment address.
743
842
  * @param _platformProviderPrimarySalesAddress Address of new primary sales
744
843
  * payment address.
745
- * @param _platformProviderSecondarySalesAddress Address of new secondary sales
844
+ * @param _defaultPlatformProviderSecondarySalesAddress Default address of new secondary sales
746
845
  * payment address.
747
846
  */
748
847
  function updateProviderSalesAddresses(
749
848
  address payable _renderProviderPrimarySalesAddress,
750
- address payable _renderProviderSecondarySalesAddress,
849
+ address payable _defaultRenderProviderSecondarySalesAddress,
751
850
  address payable _platformProviderPrimarySalesAddress,
752
- address payable _platformProviderSecondarySalesAddress
851
+ address payable _defaultPlatformProviderSecondarySalesAddress
753
852
  ) external {
754
853
  _onlyAdminACL(this.updateProviderSalesAddresses.selector);
755
854
  _onlyNonZeroAddress(_renderProviderPrimarySalesAddress);
756
- _onlyNonZeroAddress(_renderProviderSecondarySalesAddress);
757
- _onlyNonZeroAddress(_platformProviderPrimarySalesAddress);
758
- _onlyNonZeroAddress(_platformProviderSecondarySalesAddress);
855
+ _onlyNonZeroAddress(_defaultRenderProviderSecondarySalesAddress);
856
+ // @dev checks on platform provider addresses performed in _updateProviderSalesAddresses
759
857
  _updateProviderSalesAddresses(
760
858
  _renderProviderPrimarySalesAddress,
761
- _renderProviderSecondarySalesAddress,
859
+ _defaultRenderProviderSecondarySalesAddress,
762
860
  _platformProviderPrimarySalesAddress,
763
- _platformProviderSecondarySalesAddress
861
+ _defaultPlatformProviderSecondarySalesAddress
764
862
  );
765
863
  }
766
864
 
767
865
  /**
768
866
  * @notice Updates the render and platform provider primary sales revenue percentage to
769
867
  * the provided inputs.
868
+ * If contract is configured to have a null platform provider, the platform provider
869
+ * primary sales percentage must be set to zero.
770
870
  * @param renderProviderPrimarySalesPercentage_ New primary sales revenue % for the render provider
771
871
  * @param platformProviderPrimarySalesPercentage_ New primary sales revenue % for the platform provider
772
872
  * percentage.
@@ -776,13 +876,20 @@ contract GenArt721CoreV3_Engine_Flex is
776
876
  uint256 platformProviderPrimarySalesPercentage_
777
877
  ) external {
778
878
  _onlyAdminACL(this.updateProviderPrimarySalesPercentages.selector);
879
+ // require no platform provider payment if null platform provider
880
+ if (
881
+ nullPlatformProvider && platformProviderPrimarySalesPercentage_ != 0
882
+ ) {
883
+ revert GenArt721Error(ErrorCodes.OnlyNullPlatformProvider);
884
+ }
779
885
 
780
886
  // Validate that the sum of the proposed %s, does not exceed 100%.
781
- require(
887
+ if (
782
888
  (renderProviderPrimarySalesPercentage_ +
783
- platformProviderPrimarySalesPercentage_) <= ONE_HUNDRED,
784
- "Max sum of ONE_HUNDRED %"
785
- );
889
+ platformProviderPrimarySalesPercentage_) > ONE_HUNDRED
890
+ ) {
891
+ revert GenArt721Error(ErrorCodes.OverMaxSumOfPercentages);
892
+ }
786
893
  // Casting to `uint8` here is safe due check above, which does not allow
787
894
  // overflow as of solidity version ^0.8.0.
788
895
  _renderProviderPrimarySalesPercentage = uint8(
@@ -791,15 +898,27 @@ contract GenArt721CoreV3_Engine_Flex is
791
898
  _platformProviderPrimarySalesPercentage = uint8(
792
899
  platformProviderPrimarySalesPercentage_
793
900
  );
794
- emit PlatformUpdated(FIELD_PROVIDER_PRIMARY_SALES_PERCENTAGES);
901
+ emit PlatformUpdated(
902
+ bytes32(
903
+ uint256(
904
+ PlatformUpdatedFields
905
+ .FIELD_PROVIDER_PRIMARY_SALES_PERCENTAGES
906
+ )
907
+ )
908
+ );
795
909
  }
796
910
 
797
911
  /**
798
- * @notice Updates render and platform provider secondary sales royalty Basis Points to
799
- * the provided inputs.
800
- * @param _renderProviderSecondarySalesBPS New secondary sales royalty Basis
912
+ * @notice Updates default render and platform provider secondary sales royalty
913
+ * Basis Points to the provided inputs.
914
+ * If contract is configured to have a null platform provider, the platform provider
915
+ * secondary sales BPS must be set to zero.
916
+ * note: This does not update splitter contracts for all projects on
917
+ * this core contract. If updated splitter contracts are desired, they must be
918
+ * updated after this update via the `syncProviderSecondaryForProjectToDefaults` function.
919
+ * @param _defaultRenderProviderSecondarySalesBPS New default secondary sales royalty Basis
801
920
  * points.
802
- * @param _platformProviderSecondarySalesBPS New secondary sales royalty Basis
921
+ * @param _defaultPlatformProviderSecondarySalesBPS New default secondary sales royalty Basis
803
922
  * points.
804
923
  * @dev Due to secondary royalties being ultimately enforced via social
805
924
  * consensus, no hard upper limit is imposed on the BPS value, other than
@@ -807,21 +926,35 @@ contract GenArt721CoreV3_Engine_Flex is
807
926
  * changing this value is expected to either never occur, or be a rare
808
927
  * occurrence.
809
928
  */
810
- function updateProviderSecondarySalesBPS(
811
- uint256 _renderProviderSecondarySalesBPS,
812
- uint256 _platformProviderSecondarySalesBPS
929
+ function updateProviderDefaultSecondarySalesBPS(
930
+ uint256 _defaultRenderProviderSecondarySalesBPS,
931
+ uint256 _defaultPlatformProviderSecondarySalesBPS
813
932
  ) external {
814
- _onlyAdminACL(this.updateProviderSecondarySalesBPS.selector);
933
+ _onlyAdminACL(this.updateProviderDefaultSecondarySalesBPS.selector);
934
+ // require no platform provider payment if null platform provider
935
+ if (
936
+ nullPlatformProvider &&
937
+ _defaultPlatformProviderSecondarySalesBPS != 0
938
+ ) {
939
+ revert GenArt721Error(ErrorCodes.OnlyNullPlatformProvider);
940
+ }
815
941
  // Validate that the sum of the proposed provider BPS, does not exceed 10_000 BPS.
816
- require(
817
- (_renderProviderSecondarySalesBPS +
818
- _platformProviderSecondarySalesBPS) <=
819
- MAX_PROVIDER_SECONDARY_SALES_BPS,
820
- "Over max sum of BPS"
942
+ if (
943
+ _defaultRenderProviderSecondarySalesBPS +
944
+ _defaultPlatformProviderSecondarySalesBPS >
945
+ MAX_PROVIDER_SECONDARY_SALES_BPS
946
+ ) {
947
+ revert GenArt721Error(ErrorCodes.OverMaxSumOfBPS);
948
+ }
949
+ defaultRenderProviderSecondarySalesBPS = _defaultRenderProviderSecondarySalesBPS;
950
+ defaultPlatformProviderSecondarySalesBPS = _defaultPlatformProviderSecondarySalesBPS;
951
+ emit PlatformUpdated(
952
+ bytes32(
953
+ uint256(
954
+ PlatformUpdatedFields.FIELD_PROVIDER_SECONDARY_SALES_BPS
955
+ )
956
+ )
821
957
  );
822
- renderProviderSecondarySalesBPS = _renderProviderSecondarySalesBPS;
823
- platformProviderSecondarySalesBPS = _platformProviderSecondarySalesBPS;
824
- emit PlatformUpdated(FIELD_PROVIDER_SECONDARY_SALES_BPS);
825
958
  }
826
959
 
827
960
  /**
@@ -831,8 +964,7 @@ contract GenArt721CoreV3_Engine_Flex is
831
964
  function updateMinterContract(address _address) external {
832
965
  _onlyAdminACL(this.updateMinterContract.selector);
833
966
  _onlyNonZeroAddress(_address);
834
- minterContract = _address;
835
- emit MinterUpdated(_address);
967
+ _updateMinterContract(_address);
836
968
  }
837
969
 
838
970
  /**
@@ -845,15 +977,51 @@ contract GenArt721CoreV3_Engine_Flex is
845
977
  _updateRandomizerAddress(_randomizerAddress);
846
978
  }
847
979
 
980
+ /**
981
+ * @notice Updates split provider address to `_splitProviderAddress`.
982
+ * Reverts if `_splitProviderAddress` is zero address.
983
+ * @param _splitProviderAddress New split provider address.
984
+ */
985
+ function updateSplitProvider(address _splitProviderAddress) external {
986
+ _onlyAdminACL(this.updateSplitProvider.selector);
987
+ _updateSplitProvider(_splitProviderAddress);
988
+ }
989
+
990
+ /**
991
+ * @notice Updates bytecode storage reader contract to `_bytecodeStorageReaderContract`.
992
+ * Reverts if `_bytecodeStorageReaderContract` is zero address.
993
+ * Updating the active Bytecode Storage Reader contract may affect the ability to read
994
+ * data related to existing projects. Care should be taken to ensure that the new
995
+ * contract is compatible with the existing project data.
996
+ * @param _bytecodeStorageReaderContract New bytecode storage reader contract address.
997
+ */
998
+ function updateBytecodeStorageReaderContract(
999
+ address _bytecodeStorageReaderContract
1000
+ ) external {
1001
+ _onlyAdminACL(this.updateBytecodeStorageReaderContract.selector);
1002
+ _onlyNonZeroAddress(_bytecodeStorageReaderContract);
1003
+ _updateBytecodeStorageReaderContract(_bytecodeStorageReaderContract);
1004
+ }
1005
+
848
1006
  /**
849
1007
  * @notice Toggles project `_projectId` as active/inactive.
850
1008
  * @param _projectId Project ID to be toggled.
851
1009
  */
852
1010
  function toggleProjectIsActive(uint256 _projectId) external {
853
- _onlyAdminACL(this.toggleProjectIsActive.selector);
1011
+ if (allowArtistProjectActivation) {
1012
+ _onlyArtistOrAdminACL(
1013
+ _projectId,
1014
+ this.toggleProjectIsActive.selector
1015
+ );
1016
+ } else {
1017
+ _onlyAdminACL(this.toggleProjectIsActive.selector);
1018
+ }
854
1019
  _onlyValidProjectId(_projectId);
855
1020
  projects[_projectId].active = !projects[_projectId].active;
856
- emit ProjectUpdated(_projectId, FIELD_PROJECT_ACTIVE);
1021
+ emit ProjectUpdated(
1022
+ _projectId,
1023
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_ACTIVE))
1024
+ );
857
1025
  }
858
1026
 
859
1027
  /**
@@ -898,25 +1066,28 @@ contract GenArt721CoreV3_Engine_Flex is
898
1066
  _onlyValidProjectId(_projectId);
899
1067
  _onlyArtist(_projectId);
900
1068
  _onlyNonZeroAddress(_artistAddress);
901
- ProjectFinance storage projectFinance = projectIdToFinancials[
1069
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
902
1070
  _projectId
903
1071
  ];
904
1072
  // checks
905
- require(
906
- _additionalPayeePrimarySalesPercentage <= ONE_HUNDRED &&
907
- _additionalPayeeSecondarySalesPercentage <= ONE_HUNDRED,
908
- "Max of 100%"
909
- );
910
- require(
911
- _additionalPayeePrimarySalesPercentage == 0 ||
912
- _additionalPayeePrimarySales != address(0),
913
- "Primary payee is zero address"
914
- );
915
- require(
916
- _additionalPayeeSecondarySalesPercentage == 0 ||
917
- _additionalPayeeSecondarySales != address(0),
918
- "Secondary payee is zero address"
919
- );
1073
+ if (
1074
+ _additionalPayeePrimarySalesPercentage > ONE_HUNDRED ||
1075
+ _additionalPayeeSecondarySalesPercentage > ONE_HUNDRED
1076
+ ) {
1077
+ revert GenArt721Error(ErrorCodes.MaxOf100Percent);
1078
+ }
1079
+ if (
1080
+ _additionalPayeePrimarySalesPercentage > 0 &&
1081
+ _additionalPayeePrimarySales == address(0)
1082
+ ) {
1083
+ revert GenArt721Error(ErrorCodes.PrimaryPayeeIsZeroAddress);
1084
+ }
1085
+ if (
1086
+ _additionalPayeeSecondarySalesPercentage > 0 &&
1087
+ _additionalPayeeSecondarySales == address(0)
1088
+ ) {
1089
+ revert GenArt721Error(ErrorCodes.SecondaryPayeeIsZeroAddress);
1090
+ }
920
1091
  // effects
921
1092
  // emit event for off-chain indexing
922
1093
  // note: always emit a proposal event, even in the pathway of
@@ -952,6 +1123,7 @@ contract GenArt721CoreV3_Engine_Flex is
952
1123
  if (automaticAccept) {
953
1124
  // clear any previously proposed values
954
1125
  proposedArtistAddressesAndSplitsHash[_projectId] = bytes32(0);
1126
+
955
1127
  // update storage
956
1128
  // artist address can change during automatic accept if
957
1129
  // autoApproveArtistSplitProposals is true
@@ -968,6 +1140,11 @@ contract GenArt721CoreV3_Engine_Flex is
968
1140
  projectFinance.additionalPayeeSecondarySalesPercentage = uint8(
969
1141
  _additionalPayeeSecondarySalesPercentage
970
1142
  );
1143
+
1144
+ // assign project's splitter
1145
+ // @dev only call after all previous storage updates
1146
+ _assignSplitter(_projectId);
1147
+
971
1148
  // emit event for off-chain indexing
972
1149
  emit AcceptedArtistAddressesAndSplits(_projectId);
973
1150
  } else {
@@ -1023,21 +1200,22 @@ contract GenArt721CoreV3_Engine_Flex is
1023
1200
  );
1024
1201
  _onlyNonZeroAddress(_artistAddress);
1025
1202
  // checks
1026
- require(
1027
- proposedArtistAddressesAndSplitsHash[_projectId] ==
1028
- keccak256(
1029
- abi.encode(
1030
- _artistAddress,
1031
- _additionalPayeePrimarySales,
1032
- _additionalPayeePrimarySalesPercentage,
1033
- _additionalPayeeSecondarySales,
1034
- _additionalPayeeSecondarySalesPercentage
1035
- )
1036
- ),
1037
- "Must match artist proposal"
1038
- );
1203
+ if (
1204
+ proposedArtistAddressesAndSplitsHash[_projectId] !=
1205
+ keccak256(
1206
+ abi.encode(
1207
+ _artistAddress,
1208
+ _additionalPayeePrimarySales,
1209
+ _additionalPayeePrimarySalesPercentage,
1210
+ _additionalPayeeSecondarySales,
1211
+ _additionalPayeeSecondarySalesPercentage
1212
+ )
1213
+ )
1214
+ ) {
1215
+ revert GenArt721Error(ErrorCodes.MustMatchArtistProposal);
1216
+ }
1039
1217
  // effects
1040
- ProjectFinance storage projectFinance = projectIdToFinancials[
1218
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
1041
1219
  _projectId
1042
1220
  ];
1043
1221
  projectFinance.artistAddress = _artistAddress;
@@ -1053,6 +1231,11 @@ contract GenArt721CoreV3_Engine_Flex is
1053
1231
  );
1054
1232
  // clear proposed values
1055
1233
  proposedArtistAddressesAndSplitsHash[_projectId] = bytes32(0);
1234
+
1235
+ // assign project's splitter
1236
+ // @dev only call after all previous storage updates
1237
+ _assignSplitter(_projectId);
1238
+
1056
1239
  // emit event for off-chain indexing
1057
1240
  emit AcceptedArtistAddressesAndSplits(_projectId);
1058
1241
  }
@@ -1074,8 +1257,17 @@ contract GenArt721CoreV3_Engine_Flex is
1074
1257
  this.updateProjectArtistAddress.selector
1075
1258
  );
1076
1259
  _onlyNonZeroAddress(_artistAddress);
1077
- projectIdToFinancials[_projectId].artistAddress = _artistAddress;
1078
- emit ProjectUpdated(_projectId, FIELD_PROJECT_ARTIST_ADDRESS);
1260
+
1261
+ _projectIdToFinancials[_projectId].artistAddress = _artistAddress;
1262
+
1263
+ // assign project's splitter
1264
+ // @dev only call after all previous storage updates
1265
+ _assignSplitter(_projectId);
1266
+
1267
+ emit ProjectUpdated(
1268
+ _projectId,
1269
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_ARTIST_ADDRESS))
1270
+ );
1079
1271
  }
1080
1272
 
1081
1273
  /**
@@ -1085,7 +1277,10 @@ contract GenArt721CoreV3_Engine_Flex is
1085
1277
  function toggleProjectIsPaused(uint256 _projectId) external {
1086
1278
  _onlyArtist(_projectId);
1087
1279
  projects[_projectId].paused = !projects[_projectId].paused;
1088
- emit ProjectUpdated(_projectId, FIELD_PROJECT_PAUSED);
1280
+ emit ProjectUpdated(
1281
+ _projectId,
1282
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_PAUSED))
1283
+ );
1089
1284
  }
1090
1285
 
1091
1286
  /**
@@ -1101,16 +1296,44 @@ contract GenArt721CoreV3_Engine_Flex is
1101
1296
  _onlyAdminACL(this.addProject.selector);
1102
1297
  _onlyNonEmptyString(_projectName);
1103
1298
  _onlyNonZeroAddress(_artistAddress);
1104
- require(!newProjectsForbidden, "New projects forbidden");
1299
+ if (newProjectsForbidden) {
1300
+ revert GenArt721Error(ErrorCodes.NewProjectsForbidden);
1301
+ }
1105
1302
  uint256 projectId = _nextProjectId;
1106
- projectIdToFinancials[projectId].artistAddress = _artistAddress;
1303
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
1304
+ projectId
1305
+ ];
1306
+ projectFinance.artistAddress = _artistAddress;
1107
1307
  projects[projectId].name = _projectName;
1108
1308
  projects[projectId].paused = true;
1109
1309
  projects[projectId].maxInvocations = ONE_MILLION_UINT24;
1110
1310
  projects[projectId].projectBaseURI = defaultBaseURI;
1311
+ // assign default artist royalty to artist
1312
+ projectFinance
1313
+ .secondaryMarketRoyaltyPercentage = _DEFAULT_ARTIST_SECONDARY_ROYALTY_PERCENTAGE;
1314
+ // copy default platform and render provider royalties to ProjectFinance
1315
+ projectFinance
1316
+ .platformProviderSecondarySalesAddress = defaultPlatformProviderSecondarySalesAddress;
1317
+ projectFinance.platformProviderSecondarySalesBPS = uint16(
1318
+ defaultPlatformProviderSecondarySalesBPS
1319
+ );
1320
+ projectFinance
1321
+ .renderProviderSecondarySalesAddress = defaultRenderProviderSecondarySalesAddress;
1322
+ projectFinance.renderProviderSecondarySalesBPS = uint16(
1323
+ defaultRenderProviderSecondarySalesBPS
1324
+ );
1111
1325
 
1112
1326
  _nextProjectId = uint248(projectId) + 1;
1113
- emit ProjectUpdated(projectId, FIELD_PROJECT_CREATED);
1327
+
1328
+ // @dev emit initial project created event before splitter event
1329
+ emit ProjectUpdated(
1330
+ projectId,
1331
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_CREATED))
1332
+ );
1333
+
1334
+ // assign project's splitter
1335
+ // @dev only call after all previous storage updates
1336
+ _assignSplitter(projectId);
1114
1337
  }
1115
1338
 
1116
1339
  /**
@@ -1118,7 +1341,9 @@ contract GenArt721CoreV3_Engine_Flex is
1118
1341
  */
1119
1342
  function forbidNewProjects() external {
1120
1343
  _onlyAdminACL(this.forbidNewProjects.selector);
1121
- require(!newProjectsForbidden, "Already forbidden");
1344
+ if (newProjectsForbidden) {
1345
+ revert GenArt721Error(ErrorCodes.NewProjectsAlreadyForbidden);
1346
+ }
1122
1347
  _forbidNewProjects();
1123
1348
  }
1124
1349
 
@@ -1135,12 +1360,17 @@ contract GenArt721CoreV3_Engine_Flex is
1135
1360
  _onlyArtistOrAdminACL(_projectId, this.updateProjectName.selector);
1136
1361
  _onlyNonEmptyString(_projectName);
1137
1362
  projects[_projectId].name = _projectName;
1138
- emit ProjectUpdated(_projectId, FIELD_PROJECT_NAME);
1363
+ emit ProjectUpdated(
1364
+ _projectId,
1365
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_NAME))
1366
+ );
1139
1367
  }
1140
1368
 
1141
1369
  /**
1142
1370
  * @notice Updates artist name for project `_projectId` to be
1143
1371
  * `_projectArtistName`.
1372
+ * @dev allows admin to update after project is locked, due to our
1373
+ * experiences of artist name changes being requested post-lock.
1144
1374
  * @param _projectId Project ID.
1145
1375
  * @param _projectArtistName New artist name.
1146
1376
  */
@@ -1148,42 +1378,111 @@ contract GenArt721CoreV3_Engine_Flex is
1148
1378
  uint256 _projectId,
1149
1379
  string memory _projectArtistName
1150
1380
  ) external {
1151
- _onlyUnlocked(_projectId);
1152
- _onlyArtistOrAdminACL(
1153
- _projectId,
1154
- this.updateProjectArtistName.selector
1155
- );
1381
+ // if unlocked, only artist may update, if locked, only admin may update
1382
+ // @dev valid project checked in _projectUnlocked function
1383
+ if (_projectUnlocked(_projectId)) {
1384
+ if (
1385
+ msg.sender != _projectIdToFinancials[_projectId].artistAddress
1386
+ ) {
1387
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1388
+ }
1389
+ } else {
1390
+ if (
1391
+ !adminACLAllowed(
1392
+ msg.sender,
1393
+ address(this),
1394
+ this.updateProjectArtistName.selector
1395
+ )
1396
+ ) {
1397
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1398
+ }
1399
+ }
1156
1400
  _onlyNonEmptyString(_projectArtistName);
1157
1401
  projects[_projectId].artist = _projectArtistName;
1158
- emit ProjectUpdated(_projectId, FIELD_PROJECT_ARTIST_NAME);
1402
+ emit ProjectUpdated(
1403
+ _projectId,
1404
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_ARTIST_NAME))
1405
+ );
1159
1406
  }
1160
1407
 
1161
1408
  /**
1162
1409
  * @notice Updates artist secondary market royalties for project
1163
- * `_projectId` to be `_secondMarketRoyalty` percent.
1410
+ * `_projectId` to be `_secondaryMarketRoyalty` percent.
1411
+ * This deploys a new splitter contract if needed.
1164
1412
  * This DOES NOT include the secondary market royalty percentages collected
1165
1413
  * by the issuing platform; it is only the total percentage of royalties
1166
1414
  * that will be split to artist and additionalSecondaryPayee.
1167
1415
  * @param _projectId Project ID.
1168
- * @param _secondMarketRoyalty Percent of secondary sales revenue that will
1416
+ * @param _secondaryMarketRoyalty Percent of secondary sales revenue that will
1169
1417
  * be split to artist and additionalSecondaryPayee. This must be less than
1170
1418
  * or equal to ARTIST_MAX_SECONDARY_ROYALTY_PERCENTAGE percent.
1171
1419
  */
1172
1420
  function updateProjectSecondaryMarketRoyaltyPercentage(
1173
1421
  uint256 _projectId,
1174
- uint256 _secondMarketRoyalty
1422
+ uint256 _secondaryMarketRoyalty
1175
1423
  ) external {
1176
1424
  _onlyArtist(_projectId);
1177
- require(
1178
- _secondMarketRoyalty <= ARTIST_MAX_SECONDARY_ROYALTY_PERCENTAGE,
1179
- "Over max percent"
1425
+ if (_secondaryMarketRoyalty > ARTIST_MAX_SECONDARY_ROYALTY_PERCENTAGE) {
1426
+ revert GenArt721Error(ErrorCodes.OverMaxSecondaryRoyaltyPercentage);
1427
+ }
1428
+ _projectIdToFinancials[_projectId]
1429
+ .secondaryMarketRoyaltyPercentage = uint8(_secondaryMarketRoyalty);
1430
+
1431
+ // assign project's splitter
1432
+ // @dev only call after all previous storage updates
1433
+ _assignSplitter(_projectId);
1434
+
1435
+ emit ProjectUpdated(
1436
+ _projectId,
1437
+ bytes32(
1438
+ uint256(
1439
+ ProjectUpdatedFields
1440
+ .FIELD_PROJECT_SECONDARY_MARKET_ROYALTY_PERCENTAGE
1441
+ )
1442
+ )
1443
+ );
1444
+ }
1445
+
1446
+ /**
1447
+ * @notice Updates platform and render provider secondary market royalty addresses
1448
+ * and BPS to the contract-level default values for project `_projectId`.
1449
+ * This updates the splitter parameters on the existing splitter for the project.
1450
+ * Reverts if called by a non-admin address.
1451
+ * @param _projectId Project ID.
1452
+ */
1453
+ function syncProviderSecondaryForProjectToDefaults(
1454
+ uint256 _projectId
1455
+ ) external {
1456
+ _onlyAdminACL(this.syncProviderSecondaryForProjectToDefaults.selector);
1457
+ _onlyValidProjectId(_projectId);
1458
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
1459
+ _projectId
1460
+ ];
1461
+ // update project finance for project in storage
1462
+ projectFinance
1463
+ .platformProviderSecondarySalesAddress = defaultPlatformProviderSecondarySalesAddress;
1464
+ projectFinance.platformProviderSecondarySalesBPS = uint16(
1465
+ defaultPlatformProviderSecondarySalesBPS
1466
+ );
1467
+ projectFinance
1468
+ .renderProviderSecondarySalesAddress = defaultRenderProviderSecondarySalesAddress;
1469
+ projectFinance.renderProviderSecondarySalesBPS = uint16(
1470
+ defaultRenderProviderSecondarySalesBPS
1180
1471
  );
1181
- projectIdToFinancials[_projectId]
1182
- .secondaryMarketRoyaltyPercentage = uint8(_secondMarketRoyalty);
1472
+
1183
1473
  emit ProjectUpdated(
1184
1474
  _projectId,
1185
- FIELD_PROJECT_SECONDARY_MARKET_ROYALTY_PERCENTAGE
1475
+ bytes32(
1476
+ uint256(
1477
+ ProjectUpdatedFields
1478
+ .FIELD_PROJECT_PROVIDER_SECONDARY_FINANCIALS
1479
+ )
1480
+ )
1186
1481
  );
1482
+
1483
+ // assign project's splitter
1484
+ // @dev only call after all previous storage updates
1485
+ _assignSplitter(_projectId);
1187
1486
  }
1188
1487
 
1189
1488
  /**
@@ -1204,22 +1503,33 @@ contract GenArt721CoreV3_Engine_Flex is
1204
1503
  string memory _projectDescription
1205
1504
  ) external {
1206
1505
  // checks
1207
- require(
1208
- _projectUnlocked(_projectId)
1209
- ? msg.sender == projectIdToFinancials[_projectId].artistAddress
1210
- : adminACLAllowed(
1506
+ // if unlocked, only artist may update, if locked, only admin may update
1507
+ if (_projectUnlocked(_projectId)) {
1508
+ if (
1509
+ msg.sender != _projectIdToFinancials[_projectId].artistAddress
1510
+ ) {
1511
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1512
+ }
1513
+ } else {
1514
+ if (
1515
+ !adminACLAllowed(
1211
1516
  msg.sender,
1212
1517
  address(this),
1213
1518
  this.updateProjectDescription.selector
1214
- ),
1215
- "Only artist when unlocked, owner when locked"
1216
- );
1519
+ )
1520
+ ) {
1521
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1522
+ }
1523
+ }
1217
1524
  // effects
1218
1525
  // store description in contract bytecode, replacing reference address from
1219
1526
  // the old storage description with the newly created one
1220
1527
  projects[_projectId].descriptionAddress = _projectDescription
1221
1528
  .writeToBytecode();
1222
- emit ProjectUpdated(_projectId, FIELD_PROJECT_DESCRIPTION);
1529
+ emit ProjectUpdated(
1530
+ _projectId,
1531
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_DESCRIPTION))
1532
+ );
1223
1533
  }
1224
1534
 
1225
1535
  /**
@@ -1234,7 +1544,10 @@ contract GenArt721CoreV3_Engine_Flex is
1234
1544
  ) external {
1235
1545
  _onlyArtist(_projectId);
1236
1546
  projects[_projectId].website = _projectWebsite;
1237
- emit ProjectUpdated(_projectId, FIELD_PROJECT_WEBSITE);
1547
+ emit ProjectUpdated(
1548
+ _projectId,
1549
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_WEBSITE))
1550
+ );
1238
1551
  }
1239
1552
 
1240
1553
  /**
@@ -1250,7 +1563,10 @@ contract GenArt721CoreV3_Engine_Flex is
1250
1563
  _onlyArtistOrAdminACL(_projectId, this.updateProjectLicense.selector);
1251
1564
  _onlyNonEmptyString(_projectLicense);
1252
1565
  projects[_projectId].license = _projectLicense;
1253
- emit ProjectUpdated(_projectId, FIELD_PROJECT_LICENSE);
1566
+ emit ProjectUpdated(
1567
+ _projectId,
1568
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_LICENSE))
1569
+ );
1254
1570
  }
1255
1571
 
1256
1572
  /**
@@ -1270,14 +1586,18 @@ contract GenArt721CoreV3_Engine_Flex is
1270
1586
  // CHECKS
1271
1587
  Project storage project = projects[_projectId];
1272
1588
  uint256 _invocations = project.invocations;
1273
- require(
1274
- (_maxInvocations < project.maxInvocations),
1275
- "Only maxInvocations decrease"
1276
- );
1277
- require(_maxInvocations >= _invocations, "Only gte invocations");
1589
+ if (_maxInvocations >= project.maxInvocations) {
1590
+ revert GenArt721Error(ErrorCodes.OnlyMaxInvocationsDecrease);
1591
+ }
1592
+ if (_maxInvocations < _invocations) {
1593
+ revert GenArt721Error(ErrorCodes.OnlyGteInvocations);
1594
+ }
1278
1595
  // EFFECTS
1279
1596
  project.maxInvocations = _maxInvocations;
1280
- emit ProjectUpdated(_projectId, FIELD_PROJECT_MAX_INVOCATIONS);
1597
+ emit ProjectUpdated(
1598
+ _projectId,
1599
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_MAX_INVOCATIONS))
1600
+ );
1281
1601
 
1282
1602
  // register completed timestamp if action completed the project
1283
1603
  if (_maxInvocations == _invocations) {
@@ -1303,7 +1623,41 @@ contract GenArt721CoreV3_Engine_Flex is
1303
1623
  project.scriptBytecodeAddresses[project.scriptCount] = _script
1304
1624
  .writeToBytecode();
1305
1625
  project.scriptCount = project.scriptCount + 1;
1306
- emit ProjectUpdated(_projectId, FIELD_PROJECT_SCRIPT);
1626
+ emit ProjectUpdated(
1627
+ _projectId,
1628
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT))
1629
+ );
1630
+ }
1631
+
1632
+ /**
1633
+ * @notice Adds a pre-compressed script to project `_projectId`. The script
1634
+ * should be compressed using `getCompressed`. This function stores the script
1635
+ * in a compressed format on-chain. For reads, the compressed script is
1636
+ * decompressed on-chain, ensuring the original text is reconstructed without
1637
+ * external dependencies.
1638
+ * @param _projectId Project to be updated.
1639
+ * @param _compressedScript Pre-compressed script to be added.
1640
+ * Required to be non-empty, but no further validation is performed.
1641
+ */
1642
+ function addProjectScriptCompressed(
1643
+ uint256 _projectId,
1644
+ bytes memory _compressedScript
1645
+ ) external {
1646
+ _onlyUnlocked(_projectId);
1647
+ _onlyArtistOrAdminACL(
1648
+ _projectId,
1649
+ this.addProjectScriptCompressed.selector
1650
+ );
1651
+ _onlyNonEmptyBytes(_compressedScript);
1652
+ Project storage project = projects[_projectId];
1653
+ // store compressed script in contract bytecode
1654
+ project.scriptBytecodeAddresses[project.scriptCount] = _compressedScript
1655
+ .writeToBytecodeCompressed();
1656
+ project.scriptCount = project.scriptCount + 1;
1657
+ emit ProjectUpdated(
1658
+ _projectId,
1659
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT))
1660
+ );
1307
1661
  }
1308
1662
 
1309
1663
  /**
@@ -1322,11 +1676,52 @@ contract GenArt721CoreV3_Engine_Flex is
1322
1676
  _onlyArtistOrAdminACL(_projectId, this.updateProjectScript.selector);
1323
1677
  _onlyNonEmptyString(_script);
1324
1678
  Project storage project = projects[_projectId];
1325
- require(_scriptId < project.scriptCount, "scriptId out of range");
1679
+ if (_scriptId >= project.scriptCount) {
1680
+ revert GenArt721Error(ErrorCodes.ScriptIdOutOfRange);
1681
+ }
1326
1682
  // store script in contract bytecode, replacing reference address from
1327
1683
  // the old storage contract with the newly created one
1328
1684
  project.scriptBytecodeAddresses[_scriptId] = _script.writeToBytecode();
1329
- emit ProjectUpdated(_projectId, FIELD_PROJECT_SCRIPT);
1685
+ emit ProjectUpdated(
1686
+ _projectId,
1687
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT))
1688
+ );
1689
+ }
1690
+
1691
+ /**
1692
+ * @notice Updates script for project `_projectId` at script ID `_scriptId`
1693
+ * with a pre-compressed script. The script should be compressed using
1694
+ * `getCompressed`. This function stores the script in a compressed format
1695
+ * on-chain. For reads, the compressed script is decompressed on-chain, ensuring
1696
+ * the original text is reconstructed without external dependencies.
1697
+ * @param _projectId Project to be updated.
1698
+ * @param _scriptId Script ID to be updated.
1699
+ * @param _compressedScript The updated pre-compressed script value.
1700
+ * Required to be non-empty, but no further validation is performed.
1701
+ */
1702
+ function updateProjectScriptCompressed(
1703
+ uint256 _projectId,
1704
+ uint256 _scriptId,
1705
+ bytes memory _compressedScript
1706
+ ) external {
1707
+ _onlyUnlocked(_projectId);
1708
+ _onlyArtistOrAdminACL(
1709
+ _projectId,
1710
+ this.updateProjectScriptCompressed.selector
1711
+ );
1712
+ _onlyNonEmptyBytes(_compressedScript);
1713
+ Project storage project = projects[_projectId];
1714
+ if (_scriptId >= project.scriptCount) {
1715
+ revert GenArt721Error(ErrorCodes.ScriptIdOutOfRange);
1716
+ }
1717
+ // store script in contract bytecode, replacing reference address from
1718
+ // the old storage contract with the newly created one
1719
+ project.scriptBytecodeAddresses[_scriptId] = _compressedScript
1720
+ .writeToBytecodeCompressed();
1721
+ emit ProjectUpdated(
1722
+ _projectId,
1723
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT))
1724
+ );
1330
1725
  }
1331
1726
 
1332
1727
  /**
@@ -1340,13 +1735,18 @@ contract GenArt721CoreV3_Engine_Flex is
1340
1735
  this.removeProjectLastScript.selector
1341
1736
  );
1342
1737
  Project storage project = projects[_projectId];
1343
- require(project.scriptCount > 0, "No scripts to remove");
1738
+ if (project.scriptCount == 0) {
1739
+ revert GenArt721Error(ErrorCodes.NoScriptsToRemove);
1740
+ }
1344
1741
  // delete reference to old storage contract address
1345
1742
  delete project.scriptBytecodeAddresses[project.scriptCount - 1];
1346
1743
  unchecked {
1347
1744
  project.scriptCount = project.scriptCount - 1;
1348
1745
  }
1349
- emit ProjectUpdated(_projectId, FIELD_PROJECT_SCRIPT);
1746
+ emit ProjectUpdated(
1747
+ _projectId,
1748
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT))
1749
+ );
1350
1750
  }
1351
1751
 
1352
1752
  /**
@@ -1366,15 +1766,19 @@ contract GenArt721CoreV3_Engine_Flex is
1366
1766
  );
1367
1767
  Project storage project = projects[_projectId];
1368
1768
  // require exactly one @ symbol in _scriptTypeAndVersion
1369
- require(
1370
- _scriptTypeAndVersion.containsExactCharacterQty(
1769
+ if (
1770
+ !_scriptTypeAndVersion.containsExactCharacterQty(
1371
1771
  AT_CHARACTER_CODE,
1372
1772
  uint8(1)
1373
- ),
1374
- "must contain exactly one @"
1375
- );
1773
+ )
1774
+ ) {
1775
+ revert GenArt721Error(ErrorCodes.ScriptTypeAndVersionFormat);
1776
+ }
1376
1777
  project.scriptTypeAndVersion = _scriptTypeAndVersion;
1377
- emit ProjectUpdated(_projectId, FIELD_PROJECT_SCRIPT_TYPE);
1778
+ emit ProjectUpdated(
1779
+ _projectId,
1780
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT_TYPE))
1781
+ );
1378
1782
  }
1379
1783
 
1380
1784
  /**
@@ -1397,7 +1801,9 @@ contract GenArt721CoreV3_Engine_Flex is
1397
1801
  // Perform more detailed input validation for aspect ratio.
1398
1802
  bytes memory aspectRatioBytes = bytes(_aspectRatio);
1399
1803
  uint256 bytesLength = aspectRatioBytes.length;
1400
- require(bytesLength <= 11, "Aspect ratio format too long");
1804
+ if (bytesLength > 11) {
1805
+ revert GenArt721Error(ErrorCodes.AspectRatioTooLong);
1806
+ }
1401
1807
  bool hasSeenDecimalSeparator = false;
1402
1808
  bool hasSeenNumber = false;
1403
1809
  for (uint256 i; i < bytesLength; i++) {
@@ -1417,12 +1823,17 @@ contract GenArt721CoreV3_Engine_Flex is
1417
1823
  continue;
1418
1824
  }
1419
1825
  }
1420
- revert("Improperly formatted aspect ratio");
1826
+ revert GenArt721Error(ErrorCodes.AspectRatioImproperFormat);
1827
+ }
1828
+ if (!hasSeenNumber) {
1829
+ revert GenArt721Error(ErrorCodes.AspectRatioNoNumbers);
1421
1830
  }
1422
- require(hasSeenNumber, "Aspect ratio has no numbers");
1423
1831
 
1424
1832
  projects[_projectId].aspectRatio = _aspectRatio;
1425
- emit ProjectUpdated(_projectId, FIELD_PROJECT_ASPECT_RATIO);
1833
+ emit ProjectUpdated(
1834
+ _projectId,
1835
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_ASPECT_RATIO))
1836
+ );
1426
1837
  }
1427
1838
 
1428
1839
  /**
@@ -1440,7 +1851,10 @@ contract GenArt721CoreV3_Engine_Flex is
1440
1851
  _onlyArtist(_projectId);
1441
1852
  _onlyNonEmptyString(_newBaseURI);
1442
1853
  projects[_projectId].projectBaseURI = _newBaseURI;
1443
- emit ProjectUpdated(_projectId, FIELD_PROJECT_BASE_URI);
1854
+ emit ProjectUpdated(
1855
+ _projectId,
1856
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_BASE_URI))
1857
+ );
1444
1858
  }
1445
1859
 
1446
1860
  /**
@@ -1529,7 +1943,7 @@ contract GenArt721CoreV3_Engine_Flex is
1529
1943
  function projectIdToArtistAddress(
1530
1944
  uint256 _projectId
1531
1945
  ) external view returns (address payable) {
1532
- return projectIdToFinancials[_projectId].artistAddress;
1946
+ return _projectIdToFinancials[_projectId].artistAddress;
1533
1947
  }
1534
1948
 
1535
1949
  /**
@@ -1544,60 +1958,19 @@ contract GenArt721CoreV3_Engine_Flex is
1544
1958
  uint256 _projectId
1545
1959
  ) external view returns (uint256) {
1546
1960
  return
1547
- projectIdToFinancials[_projectId].secondaryMarketRoyaltyPercentage;
1548
- }
1549
-
1550
- /**
1551
- * @notice View function returning Artist's additional payee address for
1552
- * primary sales, for project `_projectId`.
1553
- * @param _projectId Project ID to be queried.
1554
- * @return address Artist's additional payee address for primary sales.
1555
- */
1556
- function projectIdToAdditionalPayeePrimarySales(
1557
- uint256 _projectId
1558
- ) external view returns (address payable) {
1559
- return projectIdToFinancials[_projectId].additionalPayeePrimarySales;
1560
- }
1561
-
1562
- /**
1563
- * @notice View function returning Artist's additional payee primary sales
1564
- * percentage, for project `_projectId`.
1565
- * @param _projectId Project ID to be queried.
1566
- * @return uint256 Artist's additional payee primary sales percentage.
1567
- */
1568
- function projectIdToAdditionalPayeePrimarySalesPercentage(
1569
- uint256 _projectId
1570
- ) external view returns (uint256) {
1571
- return
1572
- projectIdToFinancials[_projectId]
1573
- .additionalPayeePrimarySalesPercentage;
1961
+ _projectIdToFinancials[_projectId].secondaryMarketRoyaltyPercentage;
1574
1962
  }
1575
1963
 
1576
1964
  /**
1577
- * @notice View function returning Artist's additional payee address for
1578
- * secondary sales, for project `_projectId`.
1579
- * @param _projectId Project ID to be queried.
1580
- * @return address payable Artist's additional payee address for secondary
1581
- * sales.
1582
- */
1583
- function projectIdToAdditionalPayeeSecondarySales(
1584
- uint256 _projectId
1585
- ) external view returns (address payable) {
1586
- return projectIdToFinancials[_projectId].additionalPayeeSecondarySales;
1587
- }
1588
-
1589
- /**
1590
- * @notice View function returning Artist's additional payee secondary
1591
- * sales percentage, for project `_projectId`.
1965
+ * @notice View function returning project financial details for project
1966
+ * `_projectId`.
1592
1967
  * @param _projectId Project ID to be queried.
1593
- * @return uint256 Artist's additional payee secondary sales percentage.
1968
+ * @return ProjectFinance Project financial details.
1594
1969
  */
1595
- function projectIdToAdditionalPayeeSecondarySalesPercentage(
1970
+ function projectIdToFinancials(
1596
1971
  uint256 _projectId
1597
- ) external view returns (uint256) {
1598
- return
1599
- projectIdToFinancials[_projectId]
1600
- .additionalPayeeSecondarySalesPercentage;
1972
+ ) external view returns (ProjectFinance memory) {
1973
+ return _projectIdToFinancials[_projectId];
1601
1974
  }
1602
1975
 
1603
1976
  /**
@@ -1671,54 +2044,6 @@ contract GenArt721CoreV3_Engine_Flex is
1671
2044
  locked = !_projectUnlocked(_projectId);
1672
2045
  }
1673
2046
 
1674
- /**
1675
- * @notice Returns artist payment information for project `_projectId`.
1676
- * @param _projectId Project to be queried
1677
- * @return artistAddress Project Artist's address
1678
- * @return additionalPayeePrimarySales Additional payee address for primary
1679
- * sales
1680
- * @return additionalPayeePrimarySalesPercentage Percentage of artist revenue
1681
- * to be sent to the additional payee address for primary sales
1682
- * @return additionalPayeeSecondarySales Additional payee address for secondary
1683
- * sales royalties
1684
- * @return additionalPayeeSecondarySalesPercentage Percentage of artist revenue
1685
- * to be sent to the additional payee address for secondary sales royalties
1686
- * @return secondaryMarketRoyaltyPercentage Royalty percentage to be sent to
1687
- * combination of artist and additional payee. This does not include the
1688
- * platform's percentage of secondary sales royalties, which is defined as
1689
- * the sum of `renderProviderSecondarySalesBPS`
1690
- * and `platformProviderSecondarySalesBPS`.
1691
- */
1692
- function projectArtistPaymentInfo(
1693
- uint256 _projectId
1694
- )
1695
- external
1696
- view
1697
- returns (
1698
- address artistAddress,
1699
- address additionalPayeePrimarySales,
1700
- uint256 additionalPayeePrimarySalesPercentage,
1701
- address additionalPayeeSecondarySales,
1702
- uint256 additionalPayeeSecondarySalesPercentage,
1703
- uint256 secondaryMarketRoyaltyPercentage
1704
- )
1705
- {
1706
- ProjectFinance storage projectFinance = projectIdToFinancials[
1707
- _projectId
1708
- ];
1709
- artistAddress = projectFinance.artistAddress;
1710
- additionalPayeePrimarySales = projectFinance
1711
- .additionalPayeePrimarySales;
1712
- additionalPayeePrimarySalesPercentage = projectFinance
1713
- .additionalPayeePrimarySalesPercentage;
1714
- additionalPayeeSecondarySales = projectFinance
1715
- .additionalPayeeSecondarySales;
1716
- additionalPayeeSecondarySalesPercentage = projectFinance
1717
- .additionalPayeeSecondarySalesPercentage;
1718
- secondaryMarketRoyaltyPercentage = projectFinance
1719
- .secondaryMarketRoyaltyPercentage;
1720
- }
1721
-
1722
2047
  /**
1723
2048
  * @notice Returns script information for project `_projectId`.
1724
2049
  * @param _projectId Project to be queried.
@@ -1757,6 +2082,19 @@ contract GenArt721CoreV3_Engine_Flex is
1757
2082
  return projects[_projectId].scriptBytecodeAddresses[_index];
1758
2083
  }
1759
2084
 
2085
+ /**
2086
+ * @notice Returns the compressed form of a string in bytes using solady LibZip's flz compress algorithm. The bytes output from this function are intended to be used as input to `addProjectScriptCompressed` and `updateProjectScriptCompressed`.
2087
+ * @param _script Script to be compressed. Required to be a non-empty string, but no further validaton is performed.
2088
+ * @return bytes compressed bytes
2089
+ */
2090
+ function getCompressed(
2091
+ string memory _script
2092
+ ) external pure returns (bytes memory) {
2093
+ _onlyNonEmptyString(_script);
2094
+ // @dev want a potentially version-specific compression algorithm, so use version-specific library here
2095
+ return BytecodeStorageReader.getCompressed(_script);
2096
+ }
2097
+
1760
2098
  /**
1761
2099
  * @notice Returns script for project `_projectId` at script index `_index`.
1762
2100
  * @param _projectId Project to be queried.
@@ -1816,82 +2154,50 @@ contract GenArt721CoreV3_Engine_Flex is
1816
2154
  function getHistoricalRandomizerAt(
1817
2155
  uint256 _index
1818
2156
  ) external view returns (address) {
1819
- require(
1820
- _index < _historicalRandomizerAddresses.length,
1821
- "Index out of bounds"
1822
- );
2157
+ if (_index >= _historicalRandomizerAddresses.length) {
2158
+ revert GenArt721Error(ErrorCodes.IndexOutOfBounds);
2159
+ }
1823
2160
  return _historicalRandomizerAddresses[_index];
1824
2161
  }
1825
2162
 
1826
2163
  /**
1827
- * @notice Gets royalty Basis Points (BPS) for token ID `_tokenId`.
1828
- * This conforms to the IManifold interface designated in the Royalty
1829
- * Registry's RoyaltyEngineV1.sol contract.
1830
- * ref: https://github.com/manifoldxyz/royalty-registry-solidity
1831
- * @param _tokenId Token ID to be queried.
1832
- * @return recipients Array of royalty payment recipients
1833
- * @return bps Array of Basis Points (BPS) allocated to each recipient,
1834
- * aligned by index.
2164
+ * @notice Gets ERC-2981 royalty information for token with ID `_tokenId`
2165
+ * and sale price `_salePrice`.
2166
+ * @param _tokenId Token ID to be queried for royalty information
2167
+ * @param _salePrice the sale price of the NFT asset specified by _tokenId
2168
+ * @return receiver address that should be sent the royalty payment
2169
+ * @return royaltyAmount the royalty payment amount for `_salePrice
1835
2170
  * @dev reverts if invalid _tokenId
1836
- * @dev only returns recipients that have a non-zero BPS allocation
1837
2171
  */
1838
- function getRoyalties(
1839
- uint256 _tokenId
1840
- )
1841
- external
1842
- view
1843
- returns (address payable[] memory recipients, uint256[] memory bps)
1844
- {
2172
+ function royaltyInfo(
2173
+ uint256 _tokenId,
2174
+ uint256 _salePrice
2175
+ ) external view returns (address receiver, uint256 royaltyAmount) {
1845
2176
  _onlyValidTokenId(_tokenId);
1846
- // initialize arrays with maximum potential length
1847
- recipients = new address payable[](4);
1848
- bps = new uint256[](4);
1849
2177
 
2178
+ // populate receiver with project's royalty splitter
2179
+ // @dev royalty splitter created upon project creation, so will always exist
2180
+ // for valid token ID
1850
2181
  uint256 projectId = tokenIdToProjectId(_tokenId);
1851
- ProjectFinance storage projectFinance = projectIdToFinancials[
2182
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
1852
2183
  projectId
1853
2184
  ];
1854
- // load values into memory
1855
- uint256 royaltyPercentageForArtistAndAdditional = projectFinance
1856
- .secondaryMarketRoyaltyPercentage;
1857
- uint256 additionalPayeePercentage = projectFinance
1858
- .additionalPayeeSecondarySalesPercentage;
1859
- // calculate BPS = percentage * 100
1860
- uint256 artistBPS = (ONE_HUNDRED - additionalPayeePercentage) *
1861
- royaltyPercentageForArtistAndAdditional;
1862
-
1863
- uint256 additionalBPS = additionalPayeePercentage *
1864
- royaltyPercentageForArtistAndAdditional;
1865
- uint256 renderProviderBPS = renderProviderSecondarySalesBPS;
1866
- uint256 platformProviderBPS = platformProviderSecondarySalesBPS;
1867
- // populate arrays
1868
- uint256 payeeCount;
1869
- if (artistBPS > 0) {
1870
- recipients[payeeCount] = projectFinance.artistAddress;
1871
- bps[payeeCount++] = artistBPS;
1872
- }
1873
- if (additionalBPS > 0) {
1874
- recipients[payeeCount] = projectFinance
1875
- .additionalPayeeSecondarySales;
1876
- bps[payeeCount++] = additionalBPS;
1877
- }
1878
- if (renderProviderBPS > 0) {
1879
- recipients[payeeCount] = renderProviderSecondarySalesAddress;
1880
- bps[payeeCount++] = renderProviderBPS;
1881
- }
1882
- if (platformProviderBPS > 0) {
1883
- recipients[payeeCount] = platformProviderSecondarySalesAddress;
1884
- bps[payeeCount++] = platformProviderBPS;
1885
- }
1886
- // trim arrays if necessary
1887
- if (4 > payeeCount) {
1888
- assembly {
1889
- let decrease := sub(4, payeeCount)
1890
- mstore(recipients, sub(mload(recipients), decrease))
1891
- mstore(bps, sub(mload(bps), decrease))
1892
- }
2185
+ receiver = projectFinance.royaltySplitter;
2186
+
2187
+ // populate royaltyAmount with calculated royalty amount
2188
+ // @dev important to cast to uint256 before multiplying to avoid overflow
2189
+ uint256 totalRoyaltyBPS = (100 *
2190
+ uint256(projectFinance.secondaryMarketRoyaltyPercentage)) +
2191
+ projectFinance.platformProviderSecondarySalesBPS +
2192
+ projectFinance.renderProviderSecondarySalesBPS;
2193
+ // @dev totalRoyaltyBPS guaranteed to be <= 10,000,
2194
+ if (totalRoyaltyBPS > 10_000) {
2195
+ revert GenArt721Error(ErrorCodes.OverMaxSumOfBPS);
1893
2196
  }
1894
- return (recipients, bps);
2197
+ // @dev overflow automatically checked in solidity 0.8
2198
+ // @dev totalRoyaltyBPS guaranteed to be <= 10_000,
2199
+ // so overflow only possible with unreasonably high _salePrice values near uint256 max
2200
+ royaltyAmount = (_salePrice * totalRoyaltyBPS) / 10_000;
1895
2201
  }
1896
2202
 
1897
2203
  /**
@@ -1944,7 +2250,7 @@ contract GenArt721CoreV3_Engine_Flex is
1944
2250
  address payable additionalPayeePrimaryAddress_
1945
2251
  )
1946
2252
  {
1947
- ProjectFinance storage projectFinance = projectIdToFinancials[
2253
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
1948
2254
  _projectId
1949
2255
  ];
1950
2256
  // calculate revenues – this is a three-way split between the
@@ -1986,34 +2292,53 @@ contract GenArt721CoreV3_Engine_Flex is
1986
2292
  * If the dependencyType is ONCHAIN, the `data` field will contain the extrated bytecode data and `cid`
1987
2293
  * will be an empty string. Conversly, for any other dependencyType, the `data` field will be an empty string
1988
2294
  * and the `bytecodeAddress` will point to the zero address.
2295
+ * If the dependencyType is ART_BLOCKS_DEPENDENCY_REGISTRY, the `cid` field will contain the string
2296
+ * representation of the dependencyNameAndVersion bytes32 value stored in the dependency registry (
2297
+ * at public address `artblocksDependencyRegistryAddress`)
2298
+ * @param _projectId Project to be queried.
2299
+ * @param _index Index of external asset dependency to be queried.
2300
+ * @return ExternalAssetDependencyWithData External asset dependency for project `_projectId` at index `_index`.
1989
2301
  */
1990
2302
  function projectExternalAssetDependencyByIndex(
1991
2303
  uint256 _projectId,
1992
2304
  uint256 _index
1993
2305
  ) external view returns (ExternalAssetDependencyWithData memory) {
1994
- ExternalAssetDependency storage _dependency = projects[_projectId]
1995
- .externalAssetDependencies[_index];
1996
- address _bytecodeAddress = _dependency.bytecodeAddress;
1997
-
1998
2306
  return
1999
- ExternalAssetDependencyWithData({
2000
- dependencyType: _dependency.dependencyType,
2001
- cid: _dependency.cid,
2002
- bytecodeAddress: _bytecodeAddress,
2003
- data: (_dependency.dependencyType ==
2004
- ExternalAssetDependencyType.ONCHAIN)
2005
- ? _readFromBytecode(_bytecodeAddress)
2006
- : ""
2307
+ V3FlexLib.projectExternalAssetDependencyByIndex({
2308
+ _projectId: _projectId,
2309
+ _index: _index,
2310
+ _bytecodeStorageReaderContract: bytecodeStorageReaderContract
2007
2311
  });
2008
2312
  }
2009
2313
 
2010
2314
  /**
2011
2315
  * @notice Returns external asset dependency count for project `_projectId` at index `_index`.
2316
+ * @param _projectId Project to be queried.
2317
+ * @return uint256 Count of external asset dependencies for project `_projectId`.
2012
2318
  */
2013
2319
  function projectExternalAssetDependencyCount(
2014
2320
  uint256 _projectId
2015
2321
  ) external view returns (uint256) {
2016
- return uint256(projects[_projectId].externalAssetDependencyCount);
2322
+ return
2323
+ V3FlexLib.projectExternalAssetDependencyCount({
2324
+ _projectId: _projectId
2325
+ });
2326
+ }
2327
+
2328
+ /**
2329
+ * @notice Returns the preferred IPFS gateway for the platform.
2330
+ * @return string Preferred IPFS gateway for the platform.
2331
+ */
2332
+ function preferredIPFSGateway() external view returns (string memory) {
2333
+ return V3FlexLib.preferredIPFSGateway();
2334
+ }
2335
+
2336
+ /**
2337
+ * @notice Returns the preferred Arweave gateway for the platform.
2338
+ * @return string Preferred Arweave gateway for the platform.
2339
+ */
2340
+ function preferredArweaveGateway() external view returns (string memory) {
2341
+ return V3FlexLib.preferredArweaveGateway();
2017
2342
  }
2018
2343
 
2019
2344
  /**
@@ -2093,7 +2418,7 @@ contract GenArt721CoreV3_Engine_Flex is
2093
2418
  _onlyValidTokenId(_tokenId);
2094
2419
  string memory _projectBaseURI = projects[tokenIdToProjectId(_tokenId)]
2095
2420
  .projectBaseURI;
2096
- return string.concat(_projectBaseURI, toString(_tokenId));
2421
+ return string.concat(_projectBaseURI, _tokenId.toString());
2097
2422
  }
2098
2423
 
2099
2424
  /**
@@ -2101,9 +2426,15 @@ contract GenArt721CoreV3_Engine_Flex is
2101
2426
  */
2102
2427
  function supportsInterface(
2103
2428
  bytes4 interfaceId
2104
- ) public view virtual override returns (bool) {
2429
+ )
2430
+ public
2431
+ view
2432
+ virtual
2433
+ override(ERC721_PackedHashSeedV1, IERC165)
2434
+ returns (bool)
2435
+ {
2105
2436
  return
2106
- interfaceId == type(IManifold).interfaceId ||
2437
+ interfaceId == _INTERFACE_ID_ERC2981 ||
2107
2438
  super.supportsInterface(interfaceId);
2108
2439
  }
2109
2440
 
@@ -2115,7 +2446,11 @@ contract GenArt721CoreV3_Engine_Flex is
2115
2446
  function _forbidNewProjects() internal {
2116
2447
  if (!newProjectsForbidden) {
2117
2448
  newProjectsForbidden = true;
2118
- emit PlatformUpdated(FIELD_NEW_PROJECTS_FORBIDDEN);
2449
+ emit PlatformUpdated(
2450
+ bytes32(
2451
+ uint256(PlatformUpdatedFields.FIELD_NEW_PROJECTS_FORBIDDEN)
2452
+ )
2453
+ );
2119
2454
  }
2120
2455
  }
2121
2456
 
@@ -2135,37 +2470,65 @@ contract GenArt721CoreV3_Engine_Flex is
2135
2470
  /**
2136
2471
  * @notice Updates sales addresses for the platform and render providers to
2137
2472
  * the input parameters.
2473
+ * Reverts if invalid platform provider addresses are provided given the
2474
+ * contract's immutably configured nullPlatformProvider state.
2475
+ * Does not check render provider addresses in any way.
2138
2476
  * @param _renderProviderPrimarySalesAddress Address of new primary sales
2139
2477
  * payment address.
2140
- * @param _renderProviderSecondarySalesAddress Address of new secondary sales
2478
+ * @param _defaultRenderProviderSecondarySalesAddress Address of new secondary sales
2141
2479
  * payment address.
2142
2480
  * @param _platformProviderPrimarySalesAddress Address of new primary sales
2143
2481
  * payment address.
2144
- * @param _platformProviderSecondarySalesAddress Address of new secondary sales
2482
+ * @param _defaultPlatformProviderSecondarySalesAddress Address of new secondary sales
2145
2483
  * payment address.
2146
- * @dev Note that this method does not check that the input address is
2147
- * not `address(0)`, as it is expected that callers of this method should
2148
- * perform input validation where applicable.
2149
2484
  */
2150
2485
  function _updateProviderSalesAddresses(
2151
2486
  address _renderProviderPrimarySalesAddress,
2152
- address _renderProviderSecondarySalesAddress,
2487
+ address _defaultRenderProviderSecondarySalesAddress,
2153
2488
  address _platformProviderPrimarySalesAddress,
2154
- address _platformProviderSecondarySalesAddress
2489
+ address _defaultPlatformProviderSecondarySalesAddress
2155
2490
  ) internal {
2491
+ if (nullPlatformProvider) {
2492
+ // require null platform provider address
2493
+ if (
2494
+ _platformProviderPrimarySalesAddress != address(0) ||
2495
+ _defaultPlatformProviderSecondarySalesAddress != address(0)
2496
+ ) {
2497
+ revert GenArt721Error(ErrorCodes.OnlyNullPlatformProvider);
2498
+ }
2499
+ } else {
2500
+ _onlyNonZeroAddress(_platformProviderPrimarySalesAddress);
2501
+ _onlyNonZeroAddress(_defaultPlatformProviderSecondarySalesAddress);
2502
+ }
2156
2503
  platformProviderPrimarySalesAddress = payable(
2157
2504
  _platformProviderPrimarySalesAddress
2158
2505
  );
2159
- platformProviderSecondarySalesAddress = payable(
2160
- _platformProviderSecondarySalesAddress
2506
+ defaultPlatformProviderSecondarySalesAddress = payable(
2507
+ _defaultPlatformProviderSecondarySalesAddress
2161
2508
  );
2162
2509
  renderProviderPrimarySalesAddress = payable(
2163
2510
  _renderProviderPrimarySalesAddress
2164
2511
  );
2165
- renderProviderSecondarySalesAddress = payable(
2166
- _renderProviderSecondarySalesAddress
2512
+ defaultRenderProviderSecondarySalesAddress = payable(
2513
+ _defaultRenderProviderSecondarySalesAddress
2514
+ );
2515
+ emit PlatformUpdated(
2516
+ bytes32(
2517
+ uint256(PlatformUpdatedFields.FIELD_PROVIDER_SALES_ADDRESSES)
2518
+ )
2167
2519
  );
2168
- emit PlatformUpdated(FIELD_PROVIDER_SALES_ADDRESSES);
2520
+ }
2521
+
2522
+ /**
2523
+ * @notice Updates minter address to `_minterAddress`.
2524
+ * @param _minterAddress New minter address.
2525
+ * @dev Note that this method does not check that the input address is
2526
+ * not `address(0)`, as it is expected that callers of this method should
2527
+ * perform input validation where applicable.
2528
+ */
2529
+ function _updateMinterContract(address _minterAddress) internal {
2530
+ minterContract = _minterAddress;
2531
+ emit MinterUpdated(_minterAddress);
2169
2532
  }
2170
2533
 
2171
2534
  /**
@@ -2179,7 +2542,85 @@ contract GenArt721CoreV3_Engine_Flex is
2179
2542
  randomizerContract = IRandomizer_V3CoreBase(_randomizerAddress);
2180
2543
  // populate historical randomizer array
2181
2544
  _historicalRandomizerAddresses.push(_randomizerAddress);
2182
- emit PlatformUpdated(FIELD_RANDOMIZER_ADDRESS);
2545
+ emit PlatformUpdated(
2546
+ bytes32(uint256(PlatformUpdatedFields.FIELD_RANDOMIZER_ADDRESS))
2547
+ );
2548
+ }
2549
+
2550
+ /**
2551
+ * @notice Updates split provider address to `_splitProviderAddress`.
2552
+ * Reverts if `_splitProviderAddress` is the zero address.
2553
+ * @param _splitProviderAddress New split provider address.
2554
+ * @dev Note that this method does not check that the input address is
2555
+ * not `address(0)`, as it is expected that callers of this method should
2556
+ * perform input validation where applicable.
2557
+ */
2558
+ function _updateSplitProvider(address _splitProviderAddress) internal {
2559
+ // require non-zero split provider address
2560
+ _onlyNonZeroAddress(_splitProviderAddress);
2561
+ splitProvider = ISplitProviderV0(_splitProviderAddress);
2562
+ emit PlatformUpdated(
2563
+ bytes32(uint256(PlatformUpdatedFields.FIELD_SPLIT_PROVIDER))
2564
+ );
2565
+ }
2566
+
2567
+ /**
2568
+ * @notice Update the bytecode storage reader contract address, and emit corresponding event.
2569
+ * @param _bytecodeStorageReaderContract New bytecode storage reader contract address.
2570
+ */
2571
+ function _updateBytecodeStorageReaderContract(
2572
+ address _bytecodeStorageReaderContract
2573
+ ) internal {
2574
+ bytecodeStorageReaderContract = IBytecodeStorageReader_Base(
2575
+ _bytecodeStorageReaderContract
2576
+ );
2577
+ emit PlatformUpdated(
2578
+ bytes32(
2579
+ uint256(PlatformUpdatedFields.FIELD_BYTECODE_STORAGE_READER)
2580
+ )
2581
+ );
2582
+ }
2583
+
2584
+ /**
2585
+ * @notice internal function to update a splitter contract for a project,
2586
+ * based on the project's financials in this contract's storage.
2587
+ * @dev Warning: this function uses storage reads to get the project's
2588
+ * financials, so ensure storage has been updated before calling this
2589
+ * @dev This function includes a trusted interaction that is entrusted to
2590
+ * not reenter this contract.
2591
+ * @param projectId Project ID to be updated.
2592
+ */
2593
+ function _assignSplitter(uint256 projectId) internal {
2594
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
2595
+ projectId
2596
+ ];
2597
+ // assign project's royalty splitter
2598
+ // @dev loads values from storage, so need to ensure storage has been updated
2599
+ address royaltySplitter = splitProvider.getOrCreateSplitter(
2600
+ ISplitProviderV0.SplitInputs({
2601
+ platformProviderSecondarySalesAddress: projectFinance
2602
+ .platformProviderSecondarySalesAddress,
2603
+ platformProviderSecondarySalesBPS: projectFinance
2604
+ .platformProviderSecondarySalesBPS,
2605
+ renderProviderSecondarySalesAddress: projectFinance
2606
+ .renderProviderSecondarySalesAddress,
2607
+ renderProviderSecondarySalesBPS: projectFinance
2608
+ .renderProviderSecondarySalesBPS,
2609
+ artistTotalRoyaltyPercentage: projectFinance
2610
+ .secondaryMarketRoyaltyPercentage,
2611
+ artist: projectFinance.artistAddress,
2612
+ additionalPayee: projectFinance.additionalPayeeSecondarySales,
2613
+ additionalPayeePercentage: projectFinance
2614
+ .additionalPayeeSecondarySalesPercentage
2615
+ })
2616
+ );
2617
+
2618
+ projectFinance.royaltySplitter = royaltySplitter;
2619
+
2620
+ emit ProjectRoyaltySplitterUpdated({
2621
+ projectId: projectId,
2622
+ royaltySplitter: royaltySplitter
2623
+ });
2183
2624
  }
2184
2625
 
2185
2626
  /**
@@ -2193,7 +2634,9 @@ contract GenArt721CoreV3_Engine_Flex is
2193
2634
  */
2194
2635
  function _updateDefaultBaseURI(string memory _defaultBaseURI) internal {
2195
2636
  defaultBaseURI = _defaultBaseURI;
2196
- emit PlatformUpdated(FIELD_DEFAULT_BASE_URI);
2637
+ emit PlatformUpdated(
2638
+ bytes32(uint256(PlatformUpdatedFields.FIELD_DEFAULT_BASE_URI))
2639
+ );
2197
2640
  }
2198
2641
 
2199
2642
  /**
@@ -2202,7 +2645,92 @@ contract GenArt721CoreV3_Engine_Flex is
2202
2645
  */
2203
2646
  function _completeProject(uint256 _projectId) internal {
2204
2647
  projects[_projectId].completedTimestamp = uint64(block.timestamp);
2205
- emit ProjectUpdated(_projectId, FIELD_PROJECT_COMPLETED);
2648
+ emit ProjectUpdated(
2649
+ _projectId,
2650
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_COMPLETED))
2651
+ );
2652
+ }
2653
+
2654
+ /**
2655
+ * @notice Initializes the contract with the provided `engineConfiguration`.
2656
+ * This function should be called atomically, immediately after deployment.
2657
+ * Only callable once. Validation on `engineConfiguration` is performed by caller.
2658
+ * @param engineConfiguration EngineConfiguration to configure the contract with.
2659
+ * note: parameter `engineConfiguration.newSuperAdminAddress` is not used or operated on in this contract.
2660
+ * @param adminACLContract_ Address of admin access control contract, to be
2661
+ * set as contract owner.
2662
+ * @param defaultBaseURIHost Base URI prefix to initialize default base URI with.
2663
+ * @param bytecodeStorageReaderContract_ Address of bytecode storage reader contract.
2664
+ */
2665
+ function _initialize(
2666
+ EngineConfiguration memory engineConfiguration,
2667
+ address adminACLContract_,
2668
+ string memory defaultBaseURIHost,
2669
+ address bytecodeStorageReaderContract_
2670
+ ) internal {
2671
+ // can only be initialized once
2672
+ if (_initialized) {
2673
+ revert GenArt721Error(ErrorCodes.ContractInitialized);
2674
+ }
2675
+ // immediately mark as initialized
2676
+ _initialized = true;
2677
+ // @dev assume renderProviderAddress, randomizer, and AdminACL non-zero
2678
+ // checks on platform provider addresses performed in _updateProviderSalesAddresses
2679
+ // initialize default sales revenue percentages and basis points
2680
+ _renderProviderPrimarySalesPercentage = 10;
2681
+ defaultRenderProviderSecondarySalesBPS = 250;
2682
+ _platformProviderPrimarySalesPercentage = engineConfiguration
2683
+ .nullPlatformProvider
2684
+ ? 0
2685
+ : 10;
2686
+ defaultPlatformProviderSecondarySalesBPS = engineConfiguration
2687
+ .nullPlatformProvider
2688
+ ? 0
2689
+ : 250;
2690
+
2691
+ // set token name and token symbol
2692
+ ERC721_PackedHashSeedV1.initialize(
2693
+ engineConfiguration.tokenName,
2694
+ engineConfiguration.tokenSymbol
2695
+ );
2696
+ // update minter if populated
2697
+ if (engineConfiguration.minterFilterAddress != address(0)) {
2698
+ _updateMinterContract(engineConfiguration.minterFilterAddress);
2699
+ }
2700
+ _updateSplitProvider(engineConfiguration.splitProviderAddress);
2701
+ _updateBytecodeStorageReaderContract(bytecodeStorageReaderContract_);
2702
+ // setup immutable `autoApproveArtistSplitProposals` config
2703
+ autoApproveArtistSplitProposals = engineConfiguration
2704
+ .autoApproveArtistSplitProposals;
2705
+ // setup immutable `nullPlatformProvider` config
2706
+ nullPlatformProvider = engineConfiguration.nullPlatformProvider;
2707
+ // setup immutable `allowArtistProjectActivation` config
2708
+ allowArtistProjectActivation = engineConfiguration
2709
+ .allowArtistProjectActivation;
2710
+ // record contracts starting project ID
2711
+ // casting-up is safe
2712
+ startingProjectId = uint256(engineConfiguration.startingProjectId);
2713
+ // @dev nullPlatformProvider must be set before calling _updateProviderSalesAddresses
2714
+ _updateProviderSalesAddresses(
2715
+ engineConfiguration.renderProviderAddress,
2716
+ engineConfiguration.renderProviderAddress,
2717
+ engineConfiguration.platformProviderAddress,
2718
+ engineConfiguration.platformProviderAddress
2719
+ );
2720
+ _updateRandomizerAddress(engineConfiguration.randomizerContract);
2721
+ // set AdminACL management contract as owner
2722
+ _transferOwnership(adminACLContract_);
2723
+ // initialize default base URI
2724
+ _updateDefaultBaseURI(
2725
+ string.concat(defaultBaseURIHost, address(this).toHexString(), "/")
2726
+ );
2727
+ // initialize next project ID
2728
+ _nextProjectId = engineConfiguration.startingProjectId;
2729
+ emit PlatformUpdated(
2730
+ bytes32(uint256(PlatformUpdatedFields.FIELD_NEXT_PROJECT_ID))
2731
+ );
2732
+ // @dev This contract is registered on the core registry in a
2733
+ // subsequent call by the factory.
2206
2734
  }
2207
2735
 
2208
2736
  /**
@@ -2216,6 +2744,7 @@ contract GenArt721CoreV3_Engine_Flex is
2216
2744
  */
2217
2745
  function _projectUnlocked(uint256 _projectId) internal view returns (bool) {
2218
2746
  _onlyValidProjectId(_projectId);
2747
+
2219
2748
  uint256 projectCompletedTimestamp = projects[_projectId]
2220
2749
  .completedTimestamp;
2221
2750
  bool projectOpen = projectCompletedTimestamp == 0;
@@ -2226,67 +2755,12 @@ contract GenArt721CoreV3_Engine_Flex is
2226
2755
  }
2227
2756
 
2228
2757
  /**
2229
- * Helper for calling `BytecodeStorageReader` external library reader method,
2758
+ * @notice Helper for calling bytecodeStorageReaderContract reader method;
2230
2759
  * added for bytecode size reduction purposes.
2231
2760
  */
2232
2761
  function _readFromBytecode(
2233
2762
  address _address
2234
2763
  ) internal view returns (string memory) {
2235
- return BytecodeStorageReader.readFromBytecode(_address);
2236
- }
2237
-
2238
- // strings library from OpenZeppelin, modified for no constants
2239
-
2240
- bytes16 private _HEX_SYMBOLS = "0123456789abcdef";
2241
- uint8 private _ADDRESS_LENGTH = 20;
2242
-
2243
- /**
2244
- * @dev Converts a `uint256` to its ASCII `string` decimal representation.
2245
- */
2246
- function toString(uint256 value) internal pure returns (string memory) {
2247
- // Inspired by OraclizeAPI's implementation - MIT licence
2248
- // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
2249
-
2250
- if (value == 0) {
2251
- return "0";
2252
- }
2253
- uint256 temp = value;
2254
- uint256 digits;
2255
- while (temp != 0) {
2256
- digits++;
2257
- temp /= 10;
2258
- }
2259
- bytes memory buffer = new bytes(digits);
2260
- while (value != 0) {
2261
- digits -= 1;
2262
- buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
2263
- value /= 10;
2264
- }
2265
- return string(buffer);
2266
- }
2267
-
2268
- /**
2269
- * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
2270
- */
2271
- function toHexString(
2272
- uint256 value,
2273
- uint256 length
2274
- ) internal view returns (string memory) {
2275
- bytes memory buffer = new bytes(2 * length + 2);
2276
- buffer[0] = "0";
2277
- buffer[1] = "x";
2278
- for (uint256 i = 2 * length + 1; i > 1; --i) {
2279
- buffer[i] = _HEX_SYMBOLS[value & 0xf];
2280
- value >>= 4;
2281
- }
2282
- require(value == 0, "hex length insufficient");
2283
- return string(buffer);
2284
- }
2285
-
2286
- /**
2287
- * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
2288
- */
2289
- function toHexString(address addr) internal view returns (string memory) {
2290
- return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
2764
+ return bytecodeStorageReaderContract.readFromBytecode(_address);
2291
2765
  }
2292
2766
  }