@artblocks/contracts 1.0.4 → 1.2.0

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