@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,20 +1,21 @@
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.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";
12
+ import {ISplitProviderV0} from "../../interfaces/v0.8.x/ISplitProviderV0.sol";
13
13
 
14
- import "@openzeppelin-4.7/contracts/utils/Strings.sol";
15
- import "@openzeppelin-4.7/contracts/access/Ownable.sol";
16
- import "../../libs/v0.8.x/ERC721_PackedHashSeed.sol";
17
- import "../../libs/v0.8.x/BytecodeStorageV1.sol";
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";
18
19
  import "../../libs/v0.8.x/Bytes32Strings.sol";
19
20
 
20
21
  /**
@@ -34,22 +35,27 @@ import "../../libs/v0.8.x/Bytes32Strings.sol";
34
35
  * ----------------------------------------------------------------------------
35
36
  * The following functions are restricted to the Admin ACL contract:
36
37
  * - updateArtblocksDependencyRegistryAddress
38
+ * - updateArtblocksOnChainGeneratorAddress
39
+ * - updateNextCoreContract
37
40
  * - updateProviderSalesAddresses
38
41
  * - updateProviderPrimarySalesPercentages (up to 100%)
39
- * - updateProviderSecondarySalesBPS (up to 100%)
42
+ * - updateProviderDefaultSecondarySalesBPS (up to 100%)
43
+ * - syncProviderSecondaryForProjectToDefaults
40
44
  * - updateMinterContract
41
45
  * - updateRandomizerAddress
42
- * - toggleProjectIsActive
46
+ * - toggleProjectIsActive (note: artist may be configured to activate projects)
43
47
  * - addProject
44
48
  * - forbidNewProjects (forever forbidding new projects)
45
49
  * - updateDefaultBaseURI (used to initialize new project base URIs)
50
+ * - updateSplitProvider
46
51
  * ----------------------------------------------------------------------------
47
- * The following functions are restricted to either the the Artist address or
52
+ * The following functions are restricted to either the Artist address or
48
53
  * the Admin ACL contract, only when the project is not locked:
49
54
  * - updateProjectName
50
55
  * - updateProjectArtistName
51
56
  * - updateProjectLicense
52
- * - Change project script via addProjectScript, updateProjectScript,
57
+ * - Change project script via addProjectScript, addProjectScriptCompressed,
58
+ * updateProjectScript, updateProjectScriptCompressed,
53
59
  * and removeProjectLastScript
54
60
  * - updateProjectScriptType
55
61
  * - updateProjectAspectRatio
@@ -93,14 +99,16 @@ import "../../libs/v0.8.x/Bytes32Strings.sol";
93
99
  * registries, and other contracts that may interact with this core contract.
94
100
  */
95
101
  contract GenArt721CoreV3_Engine is
96
- ERC721_PackedHashSeed,
102
+ ERC721_PackedHashSeedV1,
97
103
  Ownable,
104
+ IERC2981,
98
105
  IDependencyRegistryCompatibleV0,
99
- IManifold,
100
106
  IGenArt721CoreContractV3_Engine,
107
+ IGenArt721CoreContractV3_ProjectFinance,
101
108
  IGenArt721CoreContractExposesHashSeed
102
109
  {
103
110
  using BytecodeStorageWriter for string;
111
+ using BytecodeStorageWriter for bytes;
104
112
  using Bytes32Strings for bytes32;
105
113
  using Strings for uint256;
106
114
  using Strings for address;
@@ -114,49 +122,16 @@ contract GenArt721CoreV3_Engine is
114
122
  uint256 constant MAX_PROVIDER_SECONDARY_SALES_BPS = 10000; // 10_000 BPS = 100%
115
123
  uint256 constant ARTIST_MAX_SECONDARY_ROYALTY_PERCENTAGE = 95; // 95%
116
124
 
117
- // This contract emits generic events that contain fields that indicate
118
- // which parameter has been updated. This is sufficient for application
119
- // state management, while also simplifying the contract and indexing code.
120
- // This was done as an alternative to having custom events that emit what
121
- // field-values have changed for each event, given that changed values can
122
- // be introspected by indexers due to the design of this smart contract
123
- // exposing these state changes via publicly viewable fields.
124
- //
125
- // The following fields are used to indicate which contract-level parameter
126
- // has been updated in the `PlatformUpdated` event:
127
- bytes32 constant FIELD_NEXT_PROJECT_ID = "nextProjectId";
128
- bytes32 constant FIELD_NEW_PROJECTS_FORBIDDEN = "newProjectsForbidden";
129
- bytes32 constant FIELD_DEFAULT_BASE_URI = "defaultBaseURI";
130
- bytes32 constant FIELD_RANDOMIZER_ADDRESS = "randomizerAddress";
131
- bytes32 constant FIELD_ARTBLOCKS_DEPENDENCY_REGISTRY_ADDRESS =
132
- "dependencyRegistryAddress";
133
- bytes32 constant FIELD_PROVIDER_SALES_ADDRESSES = "providerSalesAddresses";
134
- bytes32 constant FIELD_PROVIDER_PRIMARY_SALES_PERCENTAGES =
135
- "providerPrimaryPercentages";
136
- bytes32 constant FIELD_PROVIDER_SECONDARY_SALES_BPS =
137
- "providerSecondaryBPS";
138
- // The following fields are used to indicate which project-level parameter
139
- // has been updated in the `ProjectUpdated` event:
140
- bytes32 constant FIELD_PROJECT_COMPLETED = "completed";
141
- bytes32 constant FIELD_PROJECT_ACTIVE = "active";
142
- bytes32 constant FIELD_PROJECT_ARTIST_ADDRESS = "artistAddress";
143
- bytes32 constant FIELD_PROJECT_PAUSED = "paused";
144
- bytes32 constant FIELD_PROJECT_CREATED = "created";
145
- bytes32 constant FIELD_PROJECT_NAME = "name";
146
- bytes32 constant FIELD_PROJECT_ARTIST_NAME = "artistName";
147
- bytes32 constant FIELD_PROJECT_SECONDARY_MARKET_ROYALTY_PERCENTAGE =
148
- "royaltyPercentage";
149
- bytes32 constant FIELD_PROJECT_DESCRIPTION = "description";
150
- bytes32 constant FIELD_PROJECT_WEBSITE = "website";
151
- bytes32 constant FIELD_PROJECT_LICENSE = "license";
152
- bytes32 constant FIELD_PROJECT_MAX_INVOCATIONS = "maxInvocations";
153
- bytes32 constant FIELD_PROJECT_SCRIPT = "script";
154
- bytes32 constant FIELD_PROJECT_SCRIPT_TYPE = "scriptType";
155
- bytes32 constant FIELD_PROJECT_ASPECT_RATIO = "aspectRatio";
156
- bytes32 constant FIELD_PROJECT_BASE_URI = "baseURI";
125
+ /// pointer to next core contract associated with this contract
126
+ address public nextCoreContract;
157
127
 
158
128
  /// Dependency registry managed by Art Blocks
159
129
  address public artblocksDependencyRegistryAddress;
130
+ /// On chain generator managed by Art Blocks
131
+ address public artblocksOnChainGeneratorAddress;
132
+
133
+ /// ensure initialization can only be performed once
134
+ bool private _initialized;
160
135
 
161
136
  /// current randomizer contract
162
137
  IRandomizer_V3CoreBase public randomizerContract;
@@ -190,20 +165,10 @@ contract GenArt721CoreV3_Engine is
190
165
 
191
166
  mapping(uint256 => Project) projects;
192
167
 
193
- /// packed struct containing project financial information
194
- struct ProjectFinance {
195
- address payable additionalPayeePrimarySales;
196
- // packed uint: max of 95, max uint8 = 255
197
- uint8 secondaryMarketRoyaltyPercentage;
198
- address payable additionalPayeeSecondarySales;
199
- // packed uint: max of 100, max uint8 = 255
200
- uint8 additionalPayeeSecondarySalesPercentage;
201
- address payable artistAddress;
202
- // packed uint: max of 100, max uint8 = 255
203
- uint8 additionalPayeePrimarySalesPercentage;
204
- }
205
- // Project financials mapping
206
- mapping(uint256 => ProjectFinance) projectIdToFinancials;
168
+ /// private mapping from project ID to project financial information. See
169
+ /// `projectIdToFinancials` getter for public access.
170
+ mapping(uint256 _projectId => ProjectFinance)
171
+ private _projectIdToFinancials;
207
172
 
208
173
  /// hash of artist's proposed payment updates to be approved by admin
209
174
  mapping(uint256 => bytes32) public proposedArtistAddressesAndSplitsHash;
@@ -214,33 +179,54 @@ contract GenArt721CoreV3_Engine is
214
179
  /// Percentage of primary sales revenue allocated to the render provider
215
180
  /// (packed)
216
181
  // packed uint: max of 100, max uint8 = 255
217
- uint8 private _renderProviderPrimarySalesPercentage = 10;
182
+ uint8 private _renderProviderPrimarySalesPercentage;
218
183
  /// The platform provider payment address for all primary sales revenues
219
184
  /// (packed)
220
185
  address payable public platformProviderPrimarySalesAddress;
221
186
  /// Percentage of primary sales revenue allocated to the platform provider
222
187
  /// (packed)
223
188
  // packed uint: max of 100, max uint8 = 255
224
- uint8 private _platformProviderPrimarySalesPercentage = 10;
225
-
226
- /// The render provider payment address for all secondary sales royalty
227
- /// revenues
228
- address payable public renderProviderSecondarySalesAddress;
229
- /// Basis Points of secondary sales royalties allocated to the
230
- /// render provider
231
- uint256 public renderProviderSecondarySalesBPS = 250;
232
- /// The platform provider payment address for all secondary sales royalty
233
- /// revenues
234
- address payable public platformProviderSecondarySalesAddress;
235
- /// Basis Points of secondary sales royalties allocated to the
236
- /// platform provider
237
- uint256 public platformProviderSecondarySalesBPS = 250;
189
+ uint8 private _platformProviderPrimarySalesPercentage;
190
+
191
+ /// @dev Note on "default" provider secondary values - the only way these can
192
+ /// be different on a per project basis is if admin updates these and then
193
+ /// does not call syncProviderSecondaryForProjectToDefaults for the project.
194
+ /// -----------------------------------------------------------------------
195
+ /// The default render provider payment address for all secondary sales royalty
196
+ /// revenues, for all new projects. Individual project payment info is defined
197
+ /// in each project's ProjectFinance struct.
198
+ /// Projects can be updated to this value by calling the
199
+ /// `syncProviderSecondaryForProjectToDefaults` function for each project.
200
+ address payable public defaultRenderProviderSecondarySalesAddress;
201
+ /// The default basis points allocated to render provider for all secondary
202
+ /// sales royalty revenues, for all new projects. Individual project
203
+ /// payment info is defined in each project's ProjectFinance struct.
204
+ /// Projects can be updated to this value by calling the
205
+ /// `syncProviderSecondaryForProjectToDefaults` function for each project.
206
+ uint256 public defaultRenderProviderSecondarySalesBPS;
207
+ /// The default platform provider payment address for all secondary sales royalty
208
+ /// revenues, for all new projects. Individual project payment info is defined
209
+ /// in each project's ProjectFinance struct.
210
+ /// Projects can be updated to this value by calling the
211
+ /// `syncProviderSecondaryForProjectToDefaults` function for each project.
212
+ address payable public defaultPlatformProviderSecondarySalesAddress;
213
+ /// The default basis points allocated to platform provider for all secondary
214
+ /// sales royalty revenues, for all new projects. Individual project
215
+ /// payment info is defined in each project's ProjectFinance struct.
216
+ /// Projects can be updated to this value by calling the
217
+ /// `syncProviderSecondaryForProjectToDefaults` function for each project.
218
+ uint256 public defaultPlatformProviderSecondarySalesBPS;
219
+ /// -----------------------------------------------------------------------
238
220
 
239
221
  /// single minter allowed for this core contract
240
222
  address public minterContract;
241
223
 
242
- /// starting (initial) project ID on this contract
243
- uint256 public immutable startingProjectId;
224
+ /// starting (initial) project ID on this contract configured
225
+ /// at time of deployment and intended to be immutable after initialization.
226
+ /// Not marked as immutable due to initialization requirements
227
+ /// under the ERC-1167 minimal proxy pattern, which necessitates
228
+ /// setting this value post-deployment.
229
+ uint256 public startingProjectId;
244
230
 
245
231
  /// next project ID to be created
246
232
  uint248 private _nextProjectId;
@@ -249,17 +235,37 @@ contract GenArt721CoreV3_Engine is
249
235
  /// default behavior is to allow new projects
250
236
  bool public newProjectsForbidden;
251
237
 
252
- /// configuration variable (determined at time of deployment)
253
- /// that determines whether or not admin approval^ should be required
254
- /// to accept artist address change proposals, or if these proposals
255
- /// should always auto-approve, as determined by the business process
256
- /// requirements of the Engine partner using this contract.
238
+ /// configuration variable set at time of deployment, intended to be
239
+ /// immutable after initialization, that determines whether or not
240
+ /// admin approval^ should be required to accept artist address change
241
+ /// proposals, or if these proposals should always auto-approve, as
242
+ /// determined by the business process requirements of the Engine
243
+ /// partner using this contract.
257
244
  ///
258
245
  /// ^does not apply in the case where contract-ownership itself is revoked
259
- bool public immutable autoApproveArtistSplitProposals;
246
+ /// Not marked as immutable due to initialization requirements
247
+ /// under the ERC-1167 minimal proxy pattern, which necessitates
248
+ /// setting this value post-deployment.
249
+ bool public autoApproveArtistSplitProposals;
250
+
251
+ /// configuration variable set at time of deployment, intended to be
252
+ /// immutable after initialization, that determines if platform provider
253
+ /// fees and addresses are always required to be set to zero.
254
+ /// Not marked as immutable due to initialization requirements
255
+ /// under the ERC-1167 minimal proxy pattern, which necessitates
256
+ /// setting this value post-deployment.
257
+ bool public nullPlatformProvider;
258
+
259
+ /// configuration variable set at time of deployment, intended to be
260
+ /// immutable after initialization, that determines if artists are allowed
261
+ /// to activate their own projects.
262
+ /// Not marked as immutable due to initialization requirements
263
+ /// under the ERC-1167 minimal proxy pattern, which necessitates
264
+ /// setting this value post-deployment.
265
+ bool public allowArtistProjectActivation;
260
266
 
261
267
  /// version & type of this core contract
262
- bytes32 constant CORE_VERSION = "v3.1.3";
268
+ bytes32 constant CORE_VERSION = "v3.2.2";
263
269
 
264
270
  function coreVersion() external pure returns (string memory) {
265
271
  return CORE_VERSION.toString();
@@ -274,54 +280,84 @@ contract GenArt721CoreV3_Engine is
274
280
  /// default base URI to initialize all new project projectBaseURI values to
275
281
  string public defaultBaseURI;
276
282
 
283
+ // ERC2981 royalty support and default royalty values
284
+ bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;
285
+ uint8 private constant _DEFAULT_ARTIST_SECONDARY_ROYALTY_PERCENTAGE = 5;
286
+
287
+ // royalty split provider
288
+ ISplitProviderV0 public splitProvider;
289
+
290
+ /**
291
+ * @dev This constructor sets the owner to a non-functional address as a formality.
292
+ * It is only ever ran on the implementation contract. The `Ownable` constructor is
293
+ * called to satisfy the contract's inheritance requirements. This owner has no
294
+ * operational significance and should not be considered secure or meaningful.
295
+ * The true ownership will be set in the `initialize` function post-deployment to
296
+ * ensure correct owner management in the proxy architecture.
297
+ * Explicitly setting the owner to '0xdead' to indicate non-operational use.
298
+ */
299
+ constructor() Ownable(0x000000000000000000000000000000000000dEaD) {}
300
+
277
301
  function _onlyNonZeroAddress(address _address) internal pure {
278
- require(_address != address(0), "Must input non-zero address");
302
+ if (_address == address(0)) {
303
+ revert GenArt721Error(ErrorCodes.OnlyNonZeroAddress);
304
+ }
279
305
  }
280
306
 
281
307
  function _onlyNonEmptyString(string memory _string) internal pure {
282
- require(bytes(_string).length != 0, "Must input non-empty string");
308
+ if (bytes(_string).length == 0) {
309
+ revert GenArt721Error(ErrorCodes.OnlyNonEmptyString);
310
+ }
311
+ }
312
+
313
+ function _onlyNonEmptyBytes(bytes memory _bytes) internal pure {
314
+ if (_bytes.length == 0) {
315
+ revert GenArt721Error(ErrorCodes.OnlyNonEmptyBytes);
316
+ }
283
317
  }
284
318
 
285
319
  function _onlyValidTokenId(uint256 _tokenId) internal view {
286
- require(_exists(_tokenId), "Token ID does not exist");
320
+ if (_ownerOf(_tokenId) == address(0)) {
321
+ revert GenArt721Error(ErrorCodes.TokenDoesNotExist);
322
+ }
287
323
  }
288
324
 
289
325
  function _onlyValidProjectId(uint256 _projectId) internal view {
290
- require(
291
- (_projectId >= startingProjectId) && (_projectId < _nextProjectId),
292
- "Project ID does not exist"
293
- );
326
+ if (_projectId < startingProjectId || _projectId >= _nextProjectId) {
327
+ revert GenArt721Error(ErrorCodes.ProjectDoesNotExist);
328
+ }
294
329
  }
295
330
 
296
331
  function _onlyUnlocked(uint256 _projectId) internal view {
297
332
  // Note: calling `_projectUnlocked` enforces that the `_projectId`
298
333
  // passed in is valid.`
299
- require(_projectUnlocked(_projectId), "Only if unlocked");
334
+ if (!_projectUnlocked(_projectId)) {
335
+ revert GenArt721Error(ErrorCodes.OnlyUnlockedProjects);
336
+ }
300
337
  }
301
338
 
302
339
  function _onlyAdminACL(bytes4 _selector) internal {
303
- require(
304
- adminACLAllowed(msg.sender, address(this), _selector),
305
- "Only Admin ACL allowed"
306
- );
340
+ if (!adminACLAllowed(msg.sender, address(this), _selector)) {
341
+ revert GenArt721Error(ErrorCodes.OnlyAdminACL);
342
+ }
307
343
  }
308
344
 
309
345
  function _onlyArtist(uint256 _projectId) internal view {
310
- require(
311
- msg.sender == projectIdToFinancials[_projectId].artistAddress,
312
- "Only artist"
313
- );
346
+ if (msg.sender != _projectIdToFinancials[_projectId].artistAddress) {
347
+ revert GenArt721Error(ErrorCodes.OnlyArtist);
348
+ }
314
349
  }
315
350
 
316
351
  function _onlyArtistOrAdminACL(
317
352
  uint256 _projectId,
318
353
  bytes4 _selector
319
354
  ) internal {
320
- require(
321
- msg.sender == projectIdToFinancials[_projectId].artistAddress ||
322
- adminACLAllowed(msg.sender, address(this), _selector),
323
- "Only artist or Admin ACL allowed"
324
- );
355
+ if (
356
+ !(msg.sender == _projectIdToFinancials[_projectId].artistAddress ||
357
+ adminACLAllowed(msg.sender, address(this), _selector))
358
+ ) {
359
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminACL);
360
+ }
325
361
  }
326
362
 
327
363
  /**
@@ -334,76 +370,102 @@ contract GenArt721CoreV3_Engine is
334
370
  uint256 _projectId,
335
371
  bytes4 _selector
336
372
  ) internal {
337
- require(
338
- adminACLAllowed(msg.sender, address(this), _selector) ||
339
- (owner() == address(0) &&
340
- msg.sender ==
341
- projectIdToFinancials[_projectId].artistAddress),
342
- "Only Admin ACL allowed, or artist if owner has renounced"
343
- );
373
+ // check if Admin ACL is allowed to call this function
374
+ if (adminACLAllowed(msg.sender, address(this), _selector)) {
375
+ return;
376
+ }
377
+ // check if the owner has renounced ownership and the caller is the
378
+ // artist of the project
379
+ if (
380
+ owner() == address(0) &&
381
+ msg.sender == _projectIdToFinancials[_projectId].artistAddress
382
+ ) {
383
+ return;
384
+ }
385
+ // neither of the above conditions were met, revert
386
+ revert GenArt721Error(ErrorCodes.OnlyAdminACLOrRenouncedArtist);
344
387
  }
345
388
 
346
389
  /**
347
- * @notice Initializes contract.
348
- * @param _tokenName Name of token.
349
- * @param _tokenSymbol Token symbol.
350
- * @param _randomizerContract Randomizer contract.
351
- * @param _adminACLContract Address of admin access control contract, to be
390
+ * @notice Initializes the contract with the provided `engineConfiguration`.
391
+ * This function should be called atomically, immediately after deployment.
392
+ * Only callable once. Validation on `engineConfiguration` is performed by caller.
393
+ * @dev This function is intentionally unpermissioned to allow for the
394
+ * initialization of the contract post-deployment. It is expected that this
395
+ * function will be called atomically by the factory contract that deploys this
396
+ * contract, after which it will be initialized and uncallable.
397
+ * @param engineConfiguration EngineConfiguration to configure the contract with.
398
+ * @param adminACLContract_ Address of admin access control contract, to be
352
399
  * set as contract owner.
353
- * @param _startingProjectId The initial next project ID.
354
- * @param _autoApproveArtistSplitProposals Whether or not to always
355
- * auto-approve proposed artist split updates.
356
- * @dev _startingProjectId should be set to a value much, much less than
357
- * max(uint248), but an explicit input type of `uint248` is used as it is
358
- * safer to cast up to `uint256` than it is to cast down for the purposes
359
- * of setting `_nextProjectId`.
360
- */
361
- constructor(
362
- string memory _tokenName,
363
- string memory _tokenSymbol,
364
- address _renderProviderAddress,
365
- address _platformProviderAddress,
366
- address _randomizerContract,
367
- address _adminACLContract,
368
- uint248 _startingProjectId,
369
- bool _autoApproveArtistSplitProposals,
370
- address _engineRegistryContract
371
- ) ERC721_PackedHashSeed(_tokenName, _tokenSymbol) {
372
- _onlyNonZeroAddress(_renderProviderAddress);
373
- _onlyNonZeroAddress(_platformProviderAddress);
374
- _onlyNonZeroAddress(_randomizerContract);
375
- _onlyNonZeroAddress(_adminACLContract);
400
+ * @param defaultBaseURIHost Base URI prefix to initialize default base URI with.
401
+ */
402
+ function initialize(
403
+ EngineConfiguration calldata engineConfiguration,
404
+ address adminACLContract_,
405
+ string memory defaultBaseURIHost
406
+ ) external {
407
+ // can only be initialized once
408
+ if (_initialized) {
409
+ revert GenArt721Error(ErrorCodes.ContractInitialized);
410
+ }
411
+ // immediately mark as initialized
412
+ _initialized = true;
413
+ // @dev assume renderProviderAddress, randomizer, and AdminACL non-zero
414
+ // checks on platform provider addresses performed in _updateProviderSalesAddresses
415
+ // initialize default sales revenue percentages and basis points
416
+ _renderProviderPrimarySalesPercentage = 10;
417
+ defaultRenderProviderSecondarySalesBPS = 250;
418
+ _platformProviderPrimarySalesPercentage = engineConfiguration
419
+ .nullPlatformProvider
420
+ ? 0
421
+ : 10;
422
+ defaultPlatformProviderSecondarySalesBPS = engineConfiguration
423
+ .nullPlatformProvider
424
+ ? 0
425
+ : 250;
426
+
427
+ // set token name and token symbol
428
+ ERC721_PackedHashSeedV1.initialize(
429
+ engineConfiguration.tokenName,
430
+ engineConfiguration.tokenSymbol
431
+ );
432
+ // update minter if populated
433
+ if (engineConfiguration.minterFilterAddress != address(0)) {
434
+ _updateMinterContract(engineConfiguration.minterFilterAddress);
435
+ }
436
+ _updateSplitProvider(engineConfiguration.splitProviderAddress);
376
437
  // setup immutable `autoApproveArtistSplitProposals` config
377
- autoApproveArtistSplitProposals = _autoApproveArtistSplitProposals;
438
+ autoApproveArtistSplitProposals = engineConfiguration
439
+ .autoApproveArtistSplitProposals;
440
+ // setup immutable `nullPlatformProvider` config
441
+ nullPlatformProvider = engineConfiguration.nullPlatformProvider;
442
+ // setup immutable `allowArtistProjectActivation` config
443
+ allowArtistProjectActivation = engineConfiguration
444
+ .allowArtistProjectActivation;
378
445
  // record contracts starting project ID
379
446
  // casting-up is safe
380
- startingProjectId = uint256(_startingProjectId);
447
+ startingProjectId = uint256(engineConfiguration.startingProjectId);
448
+ // @dev nullPlatformProvider must be set before calling _updateProviderSalesAddresses
381
449
  _updateProviderSalesAddresses(
382
- _renderProviderAddress,
383
- _renderProviderAddress,
384
- _platformProviderAddress,
385
- _platformProviderAddress
450
+ engineConfiguration.renderProviderAddress,
451
+ engineConfiguration.renderProviderAddress,
452
+ engineConfiguration.platformProviderAddress,
453
+ engineConfiguration.platformProviderAddress
386
454
  );
387
- _updateRandomizerAddress(_randomizerContract);
455
+ _updateRandomizerAddress(engineConfiguration.randomizerContract);
388
456
  // set AdminACL management contract as owner
389
- _transferOwnership(_adminACLContract);
457
+ _transferOwnership(adminACLContract_);
390
458
  // initialize default base URI
391
459
  _updateDefaultBaseURI(
392
- string.concat(
393
- "https://token.artblocks.io/",
394
- address(this).toHexString(),
395
- "/"
396
- )
460
+ string.concat(defaultBaseURIHost, address(this).toHexString(), "/")
397
461
  );
398
462
  // initialize next project ID
399
- _nextProjectId = _startingProjectId;
400
- emit PlatformUpdated(FIELD_NEXT_PROJECT_ID);
401
- // register contract as an Engine contract
402
- IEngineRegistryV0(_engineRegistryContract).registerContract(
403
- address(this),
404
- CORE_VERSION,
405
- CORE_TYPE
463
+ _nextProjectId = engineConfiguration.startingProjectId;
464
+ emit PlatformUpdated(
465
+ bytes32(uint256(PlatformUpdatedFields.FIELD_NEXT_PROJECT_ID))
406
466
  );
467
+ // @dev This contract is registered on the core registry in a
468
+ // subsequent call by the factory.
407
469
  }
408
470
 
409
471
  /**
@@ -423,7 +485,9 @@ contract GenArt721CoreV3_Engine is
423
485
  address _by
424
486
  ) external returns (uint256 _tokenId) {
425
487
  // CHECKS
426
- require(msg.sender == minterContract, "Must mint from minter contract");
488
+ if (msg.sender != minterContract) {
489
+ revert GenArt721Error(ErrorCodes.OnlyMinterContract);
490
+ }
427
491
  Project storage project = projects[_projectId];
428
492
  // load invocations into memory
429
493
  uint24 invocationsBefore = project.invocations;
@@ -434,21 +498,21 @@ contract GenArt721CoreV3_Engine is
434
498
  invocationsAfter = invocationsBefore + 1;
435
499
  }
436
500
  uint24 maxInvocations = project.maxInvocations;
437
-
438
- require(
439
- invocationsBefore < maxInvocations,
440
- "Must not exceed max invocations"
441
- );
442
- require(
443
- project.active ||
444
- _by == projectIdToFinancials[_projectId].artistAddress,
445
- "Project must exist and be active"
446
- );
447
- require(
448
- !project.paused ||
449
- _by == projectIdToFinancials[_projectId].artistAddress,
450
- "Purchases are paused."
451
- );
501
+ if (invocationsBefore >= maxInvocations) {
502
+ revert GenArt721Error(ErrorCodes.MaxInvocationsReached);
503
+ }
504
+ if (
505
+ !(project.active ||
506
+ _by == _projectIdToFinancials[_projectId].artistAddress)
507
+ ) {
508
+ revert GenArt721Error(ErrorCodes.ProjectMustExistAndBeActive);
509
+ }
510
+ if (
511
+ project.paused &&
512
+ _by != _projectIdToFinancials[_projectId].artistAddress
513
+ ) {
514
+ revert GenArt721Error(ErrorCodes.PurchasesPaused);
515
+ }
452
516
 
453
517
  // EFFECTS
454
518
  // increment project's invocations
@@ -500,15 +564,15 @@ contract GenArt721CoreV3_Engine is
500
564
  OwnerAndHashSeed storage ownerAndHashSeed = _ownersAndHashSeeds[
501
565
  _tokenId
502
566
  ];
503
- require(
504
- msg.sender == address(randomizerContract),
505
- "Only randomizer may set"
506
- );
507
- require(
508
- ownerAndHashSeed.hashSeed == bytes12(0),
509
- "Token hash already set"
510
- );
511
- require(_hashSeed != bytes12(0), "No zero hash seed");
567
+ if (msg.sender != address(randomizerContract)) {
568
+ revert GenArt721Error(ErrorCodes.OnlyRandomizer);
569
+ }
570
+ if (ownerAndHashSeed.hashSeed != bytes12(0)) {
571
+ revert GenArt721Error(ErrorCodes.TokenHashAlreadySet);
572
+ }
573
+ if (_hashSeed == bytes12(0)) {
574
+ revert GenArt721Error(ErrorCodes.NoZeroHashSeed);
575
+ }
512
576
  ownerAndHashSeed.hashSeed = bytes12(_hashSeed);
513
577
  }
514
578
 
@@ -539,6 +603,18 @@ contract GenArt721CoreV3_Engine is
539
603
  Ownable.renounceOwnership();
540
604
  }
541
605
 
606
+ /**
607
+ * @notice Updates reference to next core contract, associated with this contract.
608
+ * @param _nextCoreContract Address of the next core contract
609
+ */
610
+ function updateNextCoreContract(address _nextCoreContract) external {
611
+ _onlyAdminACL(this.updateNextCoreContract.selector);
612
+ nextCoreContract = _nextCoreContract;
613
+ emit PlatformUpdated(
614
+ bytes32(uint256(PlatformUpdatedFields.FIELD_NEXT_CORE_CONTRACT))
615
+ );
616
+ }
617
+
542
618
  /**
543
619
  * @notice Updates reference to Art Blocks Dependency Registry contract.
544
620
  * @param _artblocksDependencyRegistryAddress Address of new Dependency
@@ -550,43 +626,74 @@ contract GenArt721CoreV3_Engine is
550
626
  _onlyAdminACL(this.updateArtblocksDependencyRegistryAddress.selector);
551
627
  _onlyNonZeroAddress(_artblocksDependencyRegistryAddress);
552
628
  artblocksDependencyRegistryAddress = _artblocksDependencyRegistryAddress;
553
- emit PlatformUpdated(FIELD_ARTBLOCKS_DEPENDENCY_REGISTRY_ADDRESS);
629
+ emit PlatformUpdated(
630
+ bytes32(
631
+ uint256(
632
+ PlatformUpdatedFields
633
+ .FIELD_ARTBLOCKS_DEPENDENCY_REGISTRY_ADDRESS
634
+ )
635
+ )
636
+ );
637
+ }
638
+
639
+ /**
640
+ * @notice Updates reference to Art Blocks On Chain Generator contract.
641
+ * @param _artblocksOnChainGeneratorAddress Address of new on chain generator.
642
+ */
643
+ function updateArtblocksOnChainGeneratorAddress(
644
+ address _artblocksOnChainGeneratorAddress
645
+ ) external {
646
+ _onlyAdminACL(this.updateArtblocksOnChainGeneratorAddress.selector);
647
+ _onlyNonZeroAddress(_artblocksOnChainGeneratorAddress);
648
+ artblocksOnChainGeneratorAddress = _artblocksOnChainGeneratorAddress;
649
+ emit PlatformUpdated(
650
+ bytes32(
651
+ uint256(
652
+ PlatformUpdatedFields
653
+ .FIELD_ARTBLOCKS_ON_CHAIN_GENERATOR_ADDRESS
654
+ )
655
+ )
656
+ );
554
657
  }
555
658
 
556
659
  /**
557
660
  * @notice Updates sales addresses for the platform and render providers to
558
661
  * the input parameters.
662
+ * note: This does not update splitter contracts for all projects on
663
+ * this core contract. If updated splitter contracts are desired, they must be
664
+ * updated after this update via the `syncProviderSecondaryForProjectToDefaults` function.
559
665
  * @param _renderProviderPrimarySalesAddress Address of new primary sales
560
666
  * payment address.
561
- * @param _renderProviderSecondarySalesAddress Address of new secondary sales
667
+ * @param _defaultRenderProviderSecondarySalesAddress Default address of new secondary sales
562
668
  * payment address.
563
669
  * @param _platformProviderPrimarySalesAddress Address of new primary sales
564
670
  * payment address.
565
- * @param _platformProviderSecondarySalesAddress Address of new secondary sales
671
+ * @param _defaultPlatformProviderSecondarySalesAddress Default address of new secondary sales
566
672
  * payment address.
567
673
  */
568
674
  function updateProviderSalesAddresses(
569
675
  address payable _renderProviderPrimarySalesAddress,
570
- address payable _renderProviderSecondarySalesAddress,
676
+ address payable _defaultRenderProviderSecondarySalesAddress,
571
677
  address payable _platformProviderPrimarySalesAddress,
572
- address payable _platformProviderSecondarySalesAddress
678
+ address payable _defaultPlatformProviderSecondarySalesAddress
573
679
  ) external {
574
680
  _onlyAdminACL(this.updateProviderSalesAddresses.selector);
575
681
  _onlyNonZeroAddress(_renderProviderPrimarySalesAddress);
576
- _onlyNonZeroAddress(_renderProviderSecondarySalesAddress);
577
- _onlyNonZeroAddress(_platformProviderPrimarySalesAddress);
578
- _onlyNonZeroAddress(_platformProviderSecondarySalesAddress);
682
+ _onlyNonZeroAddress(_defaultRenderProviderSecondarySalesAddress);
683
+ // @dev checks on platform provider addresses performed in _updateProviderSalesAddresses
579
684
  _updateProviderSalesAddresses(
580
685
  _renderProviderPrimarySalesAddress,
581
- _renderProviderSecondarySalesAddress,
686
+ _defaultRenderProviderSecondarySalesAddress,
582
687
  _platformProviderPrimarySalesAddress,
583
- _platformProviderSecondarySalesAddress
688
+ _defaultPlatformProviderSecondarySalesAddress
584
689
  );
585
690
  }
586
691
 
587
692
  /**
588
693
  * @notice Updates the render and platform provider primary sales revenue percentage to
589
694
  * the provided inputs.
695
+ * If contract is configured to have a null platform provider, the platform provider
696
+ * primary sales percentage must be set to zero.
590
697
  * @param renderProviderPrimarySalesPercentage_ New primary sales revenue % for the render provider
591
698
  * @param platformProviderPrimarySalesPercentage_ New primary sales revenue % for the platform provider
592
699
  * percentage.
@@ -596,13 +703,20 @@ contract GenArt721CoreV3_Engine is
596
703
  uint256 platformProviderPrimarySalesPercentage_
597
704
  ) external {
598
705
  _onlyAdminACL(this.updateProviderPrimarySalesPercentages.selector);
706
+ // require no platform provider payment if null platform provider
707
+ if (
708
+ nullPlatformProvider && platformProviderPrimarySalesPercentage_ != 0
709
+ ) {
710
+ revert GenArt721Error(ErrorCodes.OnlyNullPlatformProvider);
711
+ }
599
712
 
600
713
  // Validate that the sum of the proposed %s, does not exceed 100%.
601
- require(
714
+ if (
602
715
  (renderProviderPrimarySalesPercentage_ +
603
- platformProviderPrimarySalesPercentage_) <= ONE_HUNDRED,
604
- "Max sum of ONE_HUNDRED %"
605
- );
716
+ platformProviderPrimarySalesPercentage_) > ONE_HUNDRED
717
+ ) {
718
+ revert GenArt721Error(ErrorCodes.OverMaxSumOfPercentages);
719
+ }
606
720
  // Casting to `uint8` here is safe due check above, which does not allow
607
721
  // overflow as of solidity version ^0.8.0.
608
722
  _renderProviderPrimarySalesPercentage = uint8(
@@ -611,15 +725,27 @@ contract GenArt721CoreV3_Engine is
611
725
  _platformProviderPrimarySalesPercentage = uint8(
612
726
  platformProviderPrimarySalesPercentage_
613
727
  );
614
- emit PlatformUpdated(FIELD_PROVIDER_PRIMARY_SALES_PERCENTAGES);
728
+ emit PlatformUpdated(
729
+ bytes32(
730
+ uint256(
731
+ PlatformUpdatedFields
732
+ .FIELD_PROVIDER_PRIMARY_SALES_PERCENTAGES
733
+ )
734
+ )
735
+ );
615
736
  }
616
737
 
617
738
  /**
618
- * @notice Updates render and platform provider secondary sales royalty Basis Points to
619
- * the provided inputs.
620
- * @param _renderProviderSecondarySalesBPS New secondary sales royalty Basis
739
+ * @notice Updates default render and platform provider secondary sales royalty
740
+ * Basis Points to the provided inputs.
741
+ * If contract is configured to have a null platform provider, the platform provider
742
+ * secondary sales BPS must be set to zero.
743
+ * note: This does not update splitter contracts for all projects on
744
+ * this core contract. If updated splitter contracts are desired, they must be
745
+ * updated after this update via the `syncProviderSecondaryForProjectToDefaults` function.
746
+ * @param _defaultRenderProviderSecondarySalesBPS New default secondary sales royalty Basis
621
747
  * points.
622
- * @param _platformProviderSecondarySalesBPS New secondary sales royalty Basis
748
+ * @param _defaultPlatformProviderSecondarySalesBPS New default secondary sales royalty Basis
623
749
  * points.
624
750
  * @dev Due to secondary royalties being ultimately enforced via social
625
751
  * consensus, no hard upper limit is imposed on the BPS value, other than
@@ -627,21 +753,35 @@ contract GenArt721CoreV3_Engine is
627
753
  * changing this value is expected to either never occur, or be a rare
628
754
  * occurrence.
629
755
  */
630
- function updateProviderSecondarySalesBPS(
631
- uint256 _renderProviderSecondarySalesBPS,
632
- uint256 _platformProviderSecondarySalesBPS
756
+ function updateProviderDefaultSecondarySalesBPS(
757
+ uint256 _defaultRenderProviderSecondarySalesBPS,
758
+ uint256 _defaultPlatformProviderSecondarySalesBPS
633
759
  ) external {
634
- _onlyAdminACL(this.updateProviderSecondarySalesBPS.selector);
760
+ _onlyAdminACL(this.updateProviderDefaultSecondarySalesBPS.selector);
761
+ // require no platform provider payment if null platform provider
762
+ if (
763
+ nullPlatformProvider &&
764
+ _defaultPlatformProviderSecondarySalesBPS != 0
765
+ ) {
766
+ revert GenArt721Error(ErrorCodes.OnlyNullPlatformProvider);
767
+ }
635
768
  // Validate that the sum of the proposed provider BPS, does not exceed 10_000 BPS.
636
- require(
637
- (_renderProviderSecondarySalesBPS +
638
- _platformProviderSecondarySalesBPS) <=
639
- MAX_PROVIDER_SECONDARY_SALES_BPS,
640
- "Over max sum of BPS"
769
+ if (
770
+ _defaultRenderProviderSecondarySalesBPS +
771
+ _defaultPlatformProviderSecondarySalesBPS >
772
+ MAX_PROVIDER_SECONDARY_SALES_BPS
773
+ ) {
774
+ revert GenArt721Error(ErrorCodes.OverMaxSumOfBPS);
775
+ }
776
+ defaultRenderProviderSecondarySalesBPS = _defaultRenderProviderSecondarySalesBPS;
777
+ defaultPlatformProviderSecondarySalesBPS = _defaultPlatformProviderSecondarySalesBPS;
778
+ emit PlatformUpdated(
779
+ bytes32(
780
+ uint256(
781
+ PlatformUpdatedFields.FIELD_PROVIDER_SECONDARY_SALES_BPS
782
+ )
783
+ )
641
784
  );
642
- renderProviderSecondarySalesBPS = _renderProviderSecondarySalesBPS;
643
- platformProviderSecondarySalesBPS = _platformProviderSecondarySalesBPS;
644
- emit PlatformUpdated(FIELD_PROVIDER_SECONDARY_SALES_BPS);
645
785
  }
646
786
 
647
787
  /**
@@ -651,8 +791,7 @@ contract GenArt721CoreV3_Engine is
651
791
  function updateMinterContract(address _address) external {
652
792
  _onlyAdminACL(this.updateMinterContract.selector);
653
793
  _onlyNonZeroAddress(_address);
654
- minterContract = _address;
655
- emit MinterUpdated(_address);
794
+ _updateMinterContract(_address);
656
795
  }
657
796
 
658
797
  /**
@@ -665,15 +804,35 @@ contract GenArt721CoreV3_Engine is
665
804
  _updateRandomizerAddress(_randomizerAddress);
666
805
  }
667
806
 
807
+ /**
808
+ * @notice Updates split provider address to `_splitProviderAddress`.
809
+ * Reverts if `_splitProviderAddress` is zero address.
810
+ * @param _splitProviderAddress New split provider address.
811
+ */
812
+ function updateSplitProvider(address _splitProviderAddress) external {
813
+ _onlyAdminACL(this.updateSplitProvider.selector);
814
+ _updateSplitProvider(_splitProviderAddress);
815
+ }
816
+
668
817
  /**
669
818
  * @notice Toggles project `_projectId` as active/inactive.
670
819
  * @param _projectId Project ID to be toggled.
671
820
  */
672
821
  function toggleProjectIsActive(uint256 _projectId) external {
673
- _onlyAdminACL(this.toggleProjectIsActive.selector);
822
+ if (allowArtistProjectActivation) {
823
+ _onlyArtistOrAdminACL(
824
+ _projectId,
825
+ this.toggleProjectIsActive.selector
826
+ );
827
+ } else {
828
+ _onlyAdminACL(this.toggleProjectIsActive.selector);
829
+ }
674
830
  _onlyValidProjectId(_projectId);
675
831
  projects[_projectId].active = !projects[_projectId].active;
676
- emit ProjectUpdated(_projectId, FIELD_PROJECT_ACTIVE);
832
+ emit ProjectUpdated(
833
+ _projectId,
834
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_ACTIVE))
835
+ );
677
836
  }
678
837
 
679
838
  /**
@@ -718,25 +877,28 @@ contract GenArt721CoreV3_Engine is
718
877
  _onlyValidProjectId(_projectId);
719
878
  _onlyArtist(_projectId);
720
879
  _onlyNonZeroAddress(_artistAddress);
721
- ProjectFinance storage projectFinance = projectIdToFinancials[
880
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
722
881
  _projectId
723
882
  ];
724
883
  // checks
725
- require(
726
- _additionalPayeePrimarySalesPercentage <= ONE_HUNDRED &&
727
- _additionalPayeeSecondarySalesPercentage <= ONE_HUNDRED,
728
- "Max of 100%"
729
- );
730
- require(
731
- _additionalPayeePrimarySalesPercentage == 0 ||
732
- _additionalPayeePrimarySales != address(0),
733
- "Primary payee is zero address"
734
- );
735
- require(
736
- _additionalPayeeSecondarySalesPercentage == 0 ||
737
- _additionalPayeeSecondarySales != address(0),
738
- "Secondary payee is zero address"
739
- );
884
+ if (
885
+ _additionalPayeePrimarySalesPercentage > ONE_HUNDRED ||
886
+ _additionalPayeeSecondarySalesPercentage > ONE_HUNDRED
887
+ ) {
888
+ revert GenArt721Error(ErrorCodes.MaxOf100Percent);
889
+ }
890
+ if (
891
+ _additionalPayeePrimarySalesPercentage > 0 &&
892
+ _additionalPayeePrimarySales == address(0)
893
+ ) {
894
+ revert GenArt721Error(ErrorCodes.PrimaryPayeeIsZeroAddress);
895
+ }
896
+ if (
897
+ _additionalPayeeSecondarySalesPercentage > 0 &&
898
+ _additionalPayeeSecondarySales == address(0)
899
+ ) {
900
+ revert GenArt721Error(ErrorCodes.SecondaryPayeeIsZeroAddress);
901
+ }
740
902
  // effects
741
903
  // emit event for off-chain indexing
742
904
  // note: always emit a proposal event, even in the pathway of
@@ -772,6 +934,7 @@ contract GenArt721CoreV3_Engine is
772
934
  if (automaticAccept) {
773
935
  // clear any previously proposed values
774
936
  proposedArtistAddressesAndSplitsHash[_projectId] = bytes32(0);
937
+
775
938
  // update storage
776
939
  // artist address can change during automatic accept if
777
940
  // autoApproveArtistSplitProposals is true
@@ -788,6 +951,11 @@ contract GenArt721CoreV3_Engine is
788
951
  projectFinance.additionalPayeeSecondarySalesPercentage = uint8(
789
952
  _additionalPayeeSecondarySalesPercentage
790
953
  );
954
+
955
+ // assign project's splitter
956
+ // @dev only call after all previous storage updates
957
+ _assignSplitter(_projectId);
958
+
791
959
  // emit event for off-chain indexing
792
960
  emit AcceptedArtistAddressesAndSplits(_projectId);
793
961
  } else {
@@ -843,21 +1011,22 @@ contract GenArt721CoreV3_Engine is
843
1011
  );
844
1012
  _onlyNonZeroAddress(_artistAddress);
845
1013
  // checks
846
- require(
847
- proposedArtistAddressesAndSplitsHash[_projectId] ==
848
- keccak256(
849
- abi.encode(
850
- _artistAddress,
851
- _additionalPayeePrimarySales,
852
- _additionalPayeePrimarySalesPercentage,
853
- _additionalPayeeSecondarySales,
854
- _additionalPayeeSecondarySalesPercentage
855
- )
856
- ),
857
- "Must match artist proposal"
858
- );
1014
+ if (
1015
+ proposedArtistAddressesAndSplitsHash[_projectId] !=
1016
+ keccak256(
1017
+ abi.encode(
1018
+ _artistAddress,
1019
+ _additionalPayeePrimarySales,
1020
+ _additionalPayeePrimarySalesPercentage,
1021
+ _additionalPayeeSecondarySales,
1022
+ _additionalPayeeSecondarySalesPercentage
1023
+ )
1024
+ )
1025
+ ) {
1026
+ revert GenArt721Error(ErrorCodes.MustMatchArtistProposal);
1027
+ }
859
1028
  // effects
860
- ProjectFinance storage projectFinance = projectIdToFinancials[
1029
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
861
1030
  _projectId
862
1031
  ];
863
1032
  projectFinance.artistAddress = _artistAddress;
@@ -873,6 +1042,11 @@ contract GenArt721CoreV3_Engine is
873
1042
  );
874
1043
  // clear proposed values
875
1044
  proposedArtistAddressesAndSplitsHash[_projectId] = bytes32(0);
1045
+
1046
+ // assign project's splitter
1047
+ // @dev only call after all previous storage updates
1048
+ _assignSplitter(_projectId);
1049
+
876
1050
  // emit event for off-chain indexing
877
1051
  emit AcceptedArtistAddressesAndSplits(_projectId);
878
1052
  }
@@ -894,8 +1068,17 @@ contract GenArt721CoreV3_Engine is
894
1068
  this.updateProjectArtistAddress.selector
895
1069
  );
896
1070
  _onlyNonZeroAddress(_artistAddress);
897
- projectIdToFinancials[_projectId].artistAddress = _artistAddress;
898
- emit ProjectUpdated(_projectId, FIELD_PROJECT_ARTIST_ADDRESS);
1071
+
1072
+ _projectIdToFinancials[_projectId].artistAddress = _artistAddress;
1073
+
1074
+ // assign project's splitter
1075
+ // @dev only call after all previous storage updates
1076
+ _assignSplitter(_projectId);
1077
+
1078
+ emit ProjectUpdated(
1079
+ _projectId,
1080
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_ARTIST_ADDRESS))
1081
+ );
899
1082
  }
900
1083
 
901
1084
  /**
@@ -905,7 +1088,10 @@ contract GenArt721CoreV3_Engine is
905
1088
  function toggleProjectIsPaused(uint256 _projectId) external {
906
1089
  _onlyArtist(_projectId);
907
1090
  projects[_projectId].paused = !projects[_projectId].paused;
908
- emit ProjectUpdated(_projectId, FIELD_PROJECT_PAUSED);
1091
+ emit ProjectUpdated(
1092
+ _projectId,
1093
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_PAUSED))
1094
+ );
909
1095
  }
910
1096
 
911
1097
  /**
@@ -921,16 +1107,44 @@ contract GenArt721CoreV3_Engine is
921
1107
  _onlyAdminACL(this.addProject.selector);
922
1108
  _onlyNonEmptyString(_projectName);
923
1109
  _onlyNonZeroAddress(_artistAddress);
924
- require(!newProjectsForbidden, "New projects forbidden");
1110
+ if (newProjectsForbidden) {
1111
+ revert GenArt721Error(ErrorCodes.NewProjectsForbidden);
1112
+ }
925
1113
  uint256 projectId = _nextProjectId;
926
- projectIdToFinancials[projectId].artistAddress = _artistAddress;
1114
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
1115
+ projectId
1116
+ ];
1117
+ projectFinance.artistAddress = _artistAddress;
927
1118
  projects[projectId].name = _projectName;
928
1119
  projects[projectId].paused = true;
929
1120
  projects[projectId].maxInvocations = ONE_MILLION_UINT24;
930
1121
  projects[projectId].projectBaseURI = defaultBaseURI;
1122
+ // assign default artist royalty to artist
1123
+ projectFinance
1124
+ .secondaryMarketRoyaltyPercentage = _DEFAULT_ARTIST_SECONDARY_ROYALTY_PERCENTAGE;
1125
+ // copy default platform and render provider royalties to ProjectFinance
1126
+ projectFinance
1127
+ .platformProviderSecondarySalesAddress = defaultPlatformProviderSecondarySalesAddress;
1128
+ projectFinance.platformProviderSecondarySalesBPS = uint16(
1129
+ defaultPlatformProviderSecondarySalesBPS
1130
+ );
1131
+ projectFinance
1132
+ .renderProviderSecondarySalesAddress = defaultRenderProviderSecondarySalesAddress;
1133
+ projectFinance.renderProviderSecondarySalesBPS = uint16(
1134
+ defaultRenderProviderSecondarySalesBPS
1135
+ );
931
1136
 
932
1137
  _nextProjectId = uint248(projectId) + 1;
933
- emit ProjectUpdated(projectId, FIELD_PROJECT_CREATED);
1138
+
1139
+ // @dev emit initial project created event before splitter event
1140
+ emit ProjectUpdated(
1141
+ projectId,
1142
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_CREATED))
1143
+ );
1144
+
1145
+ // assign project's splitter
1146
+ // @dev only call after all previous storage updates
1147
+ _assignSplitter(projectId);
934
1148
  }
935
1149
 
936
1150
  /**
@@ -938,7 +1152,9 @@ contract GenArt721CoreV3_Engine is
938
1152
  */
939
1153
  function forbidNewProjects() external {
940
1154
  _onlyAdminACL(this.forbidNewProjects.selector);
941
- require(!newProjectsForbidden, "Already forbidden");
1155
+ if (newProjectsForbidden) {
1156
+ revert GenArt721Error(ErrorCodes.NewProjectsAlreadyForbidden);
1157
+ }
942
1158
  _forbidNewProjects();
943
1159
  }
944
1160
 
@@ -955,12 +1171,17 @@ contract GenArt721CoreV3_Engine is
955
1171
  _onlyArtistOrAdminACL(_projectId, this.updateProjectName.selector);
956
1172
  _onlyNonEmptyString(_projectName);
957
1173
  projects[_projectId].name = _projectName;
958
- emit ProjectUpdated(_projectId, FIELD_PROJECT_NAME);
1174
+ emit ProjectUpdated(
1175
+ _projectId,
1176
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_NAME))
1177
+ );
959
1178
  }
960
1179
 
961
1180
  /**
962
1181
  * @notice Updates artist name for project `_projectId` to be
963
1182
  * `_projectArtistName`.
1183
+ * @dev allows admin to update after project is locked, due to our
1184
+ * experiences of artist name changes being requested post-lock.
964
1185
  * @param _projectId Project ID.
965
1186
  * @param _projectArtistName New artist name.
966
1187
  */
@@ -968,42 +1189,111 @@ contract GenArt721CoreV3_Engine is
968
1189
  uint256 _projectId,
969
1190
  string memory _projectArtistName
970
1191
  ) external {
971
- _onlyUnlocked(_projectId);
972
- _onlyArtistOrAdminACL(
973
- _projectId,
974
- this.updateProjectArtistName.selector
975
- );
1192
+ // if unlocked, only artist may update, if locked, only admin may update
1193
+ // @dev valid project checked in _projectUnlocked function
1194
+ if (_projectUnlocked(_projectId)) {
1195
+ if (
1196
+ msg.sender != _projectIdToFinancials[_projectId].artistAddress
1197
+ ) {
1198
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1199
+ }
1200
+ } else {
1201
+ if (
1202
+ !adminACLAllowed(
1203
+ msg.sender,
1204
+ address(this),
1205
+ this.updateProjectArtistName.selector
1206
+ )
1207
+ ) {
1208
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1209
+ }
1210
+ }
976
1211
  _onlyNonEmptyString(_projectArtistName);
977
1212
  projects[_projectId].artist = _projectArtistName;
978
- emit ProjectUpdated(_projectId, FIELD_PROJECT_ARTIST_NAME);
1213
+ emit ProjectUpdated(
1214
+ _projectId,
1215
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_ARTIST_NAME))
1216
+ );
979
1217
  }
980
1218
 
981
1219
  /**
982
1220
  * @notice Updates artist secondary market royalties for project
983
- * `_projectId` to be `_secondMarketRoyalty` percent.
1221
+ * `_projectId` to be `_secondaryMarketRoyalty` percent.
1222
+ * This deploys a new splitter contract if needed.
984
1223
  * This DOES NOT include the secondary market royalty percentages collected
985
1224
  * by the issuing platform; it is only the total percentage of royalties
986
1225
  * that will be split to artist and additionalSecondaryPayee.
987
1226
  * @param _projectId Project ID.
988
- * @param _secondMarketRoyalty Percent of secondary sales revenue that will
1227
+ * @param _secondaryMarketRoyalty Percent of secondary sales revenue that will
989
1228
  * be split to artist and additionalSecondaryPayee. This must be less than
990
1229
  * or equal to ARTIST_MAX_SECONDARY_ROYALTY_PERCENTAGE percent.
991
1230
  */
992
1231
  function updateProjectSecondaryMarketRoyaltyPercentage(
993
1232
  uint256 _projectId,
994
- uint256 _secondMarketRoyalty
1233
+ uint256 _secondaryMarketRoyalty
995
1234
  ) external {
996
1235
  _onlyArtist(_projectId);
997
- require(
998
- _secondMarketRoyalty <= ARTIST_MAX_SECONDARY_ROYALTY_PERCENTAGE,
999
- "Over max percent"
1236
+ if (_secondaryMarketRoyalty > ARTIST_MAX_SECONDARY_ROYALTY_PERCENTAGE) {
1237
+ revert GenArt721Error(ErrorCodes.OverMaxSecondaryRoyaltyPercentage);
1238
+ }
1239
+ _projectIdToFinancials[_projectId]
1240
+ .secondaryMarketRoyaltyPercentage = uint8(_secondaryMarketRoyalty);
1241
+
1242
+ // assign project's splitter
1243
+ // @dev only call after all previous storage updates
1244
+ _assignSplitter(_projectId);
1245
+
1246
+ emit ProjectUpdated(
1247
+ _projectId,
1248
+ bytes32(
1249
+ uint256(
1250
+ ProjectUpdatedFields
1251
+ .FIELD_PROJECT_SECONDARY_MARKET_ROYALTY_PERCENTAGE
1252
+ )
1253
+ )
1000
1254
  );
1001
- projectIdToFinancials[_projectId]
1002
- .secondaryMarketRoyaltyPercentage = uint8(_secondMarketRoyalty);
1255
+ }
1256
+
1257
+ /**
1258
+ * @notice Updates platform and render provider secondary market royalty addresses
1259
+ * and BPS to the contract-level default values for project `_projectId`.
1260
+ * This updates the splitter parameters on the existing splitter for the project.
1261
+ * Reverts if called by a non-admin address.
1262
+ * @param _projectId Project ID.
1263
+ */
1264
+ function syncProviderSecondaryForProjectToDefaults(
1265
+ uint256 _projectId
1266
+ ) external {
1267
+ _onlyAdminACL(this.syncProviderSecondaryForProjectToDefaults.selector);
1268
+ _onlyValidProjectId(_projectId);
1269
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
1270
+ _projectId
1271
+ ];
1272
+ // update project finance for project in storage
1273
+ projectFinance
1274
+ .platformProviderSecondarySalesAddress = defaultPlatformProviderSecondarySalesAddress;
1275
+ projectFinance.platformProviderSecondarySalesBPS = uint16(
1276
+ defaultPlatformProviderSecondarySalesBPS
1277
+ );
1278
+ projectFinance
1279
+ .renderProviderSecondarySalesAddress = defaultRenderProviderSecondarySalesAddress;
1280
+ projectFinance.renderProviderSecondarySalesBPS = uint16(
1281
+ defaultRenderProviderSecondarySalesBPS
1282
+ );
1283
+
1003
1284
  emit ProjectUpdated(
1004
1285
  _projectId,
1005
- FIELD_PROJECT_SECONDARY_MARKET_ROYALTY_PERCENTAGE
1286
+ bytes32(
1287
+ uint256(
1288
+ ProjectUpdatedFields
1289
+ .FIELD_PROJECT_PROVIDER_SECONDARY_FINANCIALS
1290
+ )
1291
+ )
1006
1292
  );
1293
+
1294
+ // assign project's splitter
1295
+ // @dev only call after all previous storage updates
1296
+ _assignSplitter(_projectId);
1007
1297
  }
1008
1298
 
1009
1299
  /**
@@ -1024,22 +1314,33 @@ contract GenArt721CoreV3_Engine is
1024
1314
  string memory _projectDescription
1025
1315
  ) external {
1026
1316
  // checks
1027
- require(
1028
- _projectUnlocked(_projectId)
1029
- ? msg.sender == projectIdToFinancials[_projectId].artistAddress
1030
- : adminACLAllowed(
1317
+ // if unlocked, only artist may update, if locked, only admin may update
1318
+ if (_projectUnlocked(_projectId)) {
1319
+ if (
1320
+ msg.sender != _projectIdToFinancials[_projectId].artistAddress
1321
+ ) {
1322
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1323
+ }
1324
+ } else {
1325
+ if (
1326
+ !adminACLAllowed(
1031
1327
  msg.sender,
1032
1328
  address(this),
1033
1329
  this.updateProjectDescription.selector
1034
- ),
1035
- "Only artist when unlocked, owner when locked"
1036
- );
1330
+ )
1331
+ ) {
1332
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1333
+ }
1334
+ }
1037
1335
  // effects
1038
1336
  // store description in contract bytecode, replacing reference address from
1039
1337
  // the old storage description with the newly created one
1040
1338
  projects[_projectId].descriptionAddress = _projectDescription
1041
1339
  .writeToBytecode();
1042
- emit ProjectUpdated(_projectId, FIELD_PROJECT_DESCRIPTION);
1340
+ emit ProjectUpdated(
1341
+ _projectId,
1342
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_DESCRIPTION))
1343
+ );
1043
1344
  }
1044
1345
 
1045
1346
  /**
@@ -1054,7 +1355,10 @@ contract GenArt721CoreV3_Engine is
1054
1355
  ) external {
1055
1356
  _onlyArtist(_projectId);
1056
1357
  projects[_projectId].website = _projectWebsite;
1057
- emit ProjectUpdated(_projectId, FIELD_PROJECT_WEBSITE);
1358
+ emit ProjectUpdated(
1359
+ _projectId,
1360
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_WEBSITE))
1361
+ );
1058
1362
  }
1059
1363
 
1060
1364
  /**
@@ -1070,7 +1374,10 @@ contract GenArt721CoreV3_Engine is
1070
1374
  _onlyArtistOrAdminACL(_projectId, this.updateProjectLicense.selector);
1071
1375
  _onlyNonEmptyString(_projectLicense);
1072
1376
  projects[_projectId].license = _projectLicense;
1073
- emit ProjectUpdated(_projectId, FIELD_PROJECT_LICENSE);
1377
+ emit ProjectUpdated(
1378
+ _projectId,
1379
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_LICENSE))
1380
+ );
1074
1381
  }
1075
1382
 
1076
1383
  /**
@@ -1090,14 +1397,18 @@ contract GenArt721CoreV3_Engine is
1090
1397
  // CHECKS
1091
1398
  Project storage project = projects[_projectId];
1092
1399
  uint256 _invocations = project.invocations;
1093
- require(
1094
- (_maxInvocations < project.maxInvocations),
1095
- "Only maxInvocations decrease"
1096
- );
1097
- require(_maxInvocations >= _invocations, "Only gte invocations");
1400
+ if (_maxInvocations >= project.maxInvocations) {
1401
+ revert GenArt721Error(ErrorCodes.OnlyMaxInvocationsDecrease);
1402
+ }
1403
+ if (_maxInvocations < _invocations) {
1404
+ revert GenArt721Error(ErrorCodes.OnlyGteInvocations);
1405
+ }
1098
1406
  // EFFECTS
1099
1407
  project.maxInvocations = _maxInvocations;
1100
- emit ProjectUpdated(_projectId, FIELD_PROJECT_MAX_INVOCATIONS);
1408
+ emit ProjectUpdated(
1409
+ _projectId,
1410
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_MAX_INVOCATIONS))
1411
+ );
1101
1412
 
1102
1413
  // register completed timestamp if action completed the project
1103
1414
  if (_maxInvocations == _invocations) {
@@ -1123,7 +1434,41 @@ contract GenArt721CoreV3_Engine is
1123
1434
  project.scriptBytecodeAddresses[project.scriptCount] = _script
1124
1435
  .writeToBytecode();
1125
1436
  project.scriptCount = project.scriptCount + 1;
1126
- emit ProjectUpdated(_projectId, FIELD_PROJECT_SCRIPT);
1437
+ emit ProjectUpdated(
1438
+ _projectId,
1439
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT))
1440
+ );
1441
+ }
1442
+
1443
+ /**
1444
+ * @notice Adds a pre-compressed script to project `_projectId`. The script
1445
+ * should be compressed using `getCompressed`. This function stores the script
1446
+ * in a compressed format on-chain. For reads, the compressed script is
1447
+ * decompressed on-chain, ensuring the original text is reconstructed without
1448
+ * external dependencies.
1449
+ * @param _projectId Project to be updated.
1450
+ * @param _compressedScript Pre-compressed script to be added.
1451
+ * Required to be non-empty, but no further validation is performed.
1452
+ */
1453
+ function addProjectScriptCompressed(
1454
+ uint256 _projectId,
1455
+ bytes memory _compressedScript
1456
+ ) external {
1457
+ _onlyUnlocked(_projectId);
1458
+ _onlyArtistOrAdminACL(
1459
+ _projectId,
1460
+ this.addProjectScriptCompressed.selector
1461
+ );
1462
+ _onlyNonEmptyBytes(_compressedScript);
1463
+ Project storage project = projects[_projectId];
1464
+ // store compressed script in contract bytecode
1465
+ project.scriptBytecodeAddresses[project.scriptCount] = _compressedScript
1466
+ .writeToBytecodeCompressed();
1467
+ project.scriptCount = project.scriptCount + 1;
1468
+ emit ProjectUpdated(
1469
+ _projectId,
1470
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT))
1471
+ );
1127
1472
  }
1128
1473
 
1129
1474
  /**
@@ -1142,11 +1487,52 @@ contract GenArt721CoreV3_Engine is
1142
1487
  _onlyArtistOrAdminACL(_projectId, this.updateProjectScript.selector);
1143
1488
  _onlyNonEmptyString(_script);
1144
1489
  Project storage project = projects[_projectId];
1145
- require(_scriptId < project.scriptCount, "scriptId out of range");
1490
+ if (_scriptId >= project.scriptCount) {
1491
+ revert GenArt721Error(ErrorCodes.ScriptIdOutOfRange);
1492
+ }
1146
1493
  // store script in contract bytecode, replacing reference address from
1147
1494
  // the old storage contract with the newly created one
1148
1495
  project.scriptBytecodeAddresses[_scriptId] = _script.writeToBytecode();
1149
- emit ProjectUpdated(_projectId, FIELD_PROJECT_SCRIPT);
1496
+ emit ProjectUpdated(
1497
+ _projectId,
1498
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT))
1499
+ );
1500
+ }
1501
+
1502
+ /**
1503
+ * @notice Updates script for project `_projectId` at script ID `_scriptId`
1504
+ * with a pre-compressed script. The script should be compressed using
1505
+ * `getCompressed`. This function stores the script in a compressed format
1506
+ * on-chain. For reads, the compressed script is decompressed on-chain, ensuring
1507
+ * the original text is reconstructed without external dependencies.
1508
+ * @param _projectId Project to be updated.
1509
+ * @param _scriptId Script ID to be updated.
1510
+ * @param _compressedScript The updated pre-compressed script value.
1511
+ * Required to be non-empty, but no further validation is performed.
1512
+ */
1513
+ function updateProjectScriptCompressed(
1514
+ uint256 _projectId,
1515
+ uint256 _scriptId,
1516
+ bytes memory _compressedScript
1517
+ ) external {
1518
+ _onlyUnlocked(_projectId);
1519
+ _onlyArtistOrAdminACL(
1520
+ _projectId,
1521
+ this.updateProjectScriptCompressed.selector
1522
+ );
1523
+ _onlyNonEmptyBytes(_compressedScript);
1524
+ Project storage project = projects[_projectId];
1525
+ if (_scriptId >= project.scriptCount) {
1526
+ revert GenArt721Error(ErrorCodes.ScriptIdOutOfRange);
1527
+ }
1528
+ // store script in contract bytecode, replacing reference address from
1529
+ // the old storage contract with the newly created one
1530
+ project.scriptBytecodeAddresses[_scriptId] = _compressedScript
1531
+ .writeToBytecodeCompressed();
1532
+ emit ProjectUpdated(
1533
+ _projectId,
1534
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT))
1535
+ );
1150
1536
  }
1151
1537
 
1152
1538
  /**
@@ -1160,13 +1546,18 @@ contract GenArt721CoreV3_Engine is
1160
1546
  this.removeProjectLastScript.selector
1161
1547
  );
1162
1548
  Project storage project = projects[_projectId];
1163
- require(project.scriptCount > 0, "No scripts to remove");
1549
+ if (project.scriptCount == 0) {
1550
+ revert GenArt721Error(ErrorCodes.NoScriptsToRemove);
1551
+ }
1164
1552
  // delete reference to old storage contract address
1165
1553
  delete project.scriptBytecodeAddresses[project.scriptCount - 1];
1166
1554
  unchecked {
1167
1555
  project.scriptCount = project.scriptCount - 1;
1168
1556
  }
1169
- emit ProjectUpdated(_projectId, FIELD_PROJECT_SCRIPT);
1557
+ emit ProjectUpdated(
1558
+ _projectId,
1559
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT))
1560
+ );
1170
1561
  }
1171
1562
 
1172
1563
  /**
@@ -1186,15 +1577,19 @@ contract GenArt721CoreV3_Engine is
1186
1577
  );
1187
1578
  Project storage project = projects[_projectId];
1188
1579
  // require exactly one @ symbol in _scriptTypeAndVersion
1189
- require(
1190
- _scriptTypeAndVersion.containsExactCharacterQty(
1580
+ if (
1581
+ !_scriptTypeAndVersion.containsExactCharacterQty(
1191
1582
  AT_CHARACTER_CODE,
1192
1583
  uint8(1)
1193
- ),
1194
- "must contain exactly one @"
1195
- );
1584
+ )
1585
+ ) {
1586
+ revert GenArt721Error(ErrorCodes.ScriptTypeAndVersionFormat);
1587
+ }
1196
1588
  project.scriptTypeAndVersion = _scriptTypeAndVersion;
1197
- emit ProjectUpdated(_projectId, FIELD_PROJECT_SCRIPT_TYPE);
1589
+ emit ProjectUpdated(
1590
+ _projectId,
1591
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT_TYPE))
1592
+ );
1198
1593
  }
1199
1594
 
1200
1595
  /**
@@ -1217,7 +1612,9 @@ contract GenArt721CoreV3_Engine is
1217
1612
  // Perform more detailed input validation for aspect ratio.
1218
1613
  bytes memory aspectRatioBytes = bytes(_aspectRatio);
1219
1614
  uint256 bytesLength = aspectRatioBytes.length;
1220
- require(bytesLength <= 11, "Aspect ratio format too long");
1615
+ if (bytesLength > 11) {
1616
+ revert GenArt721Error(ErrorCodes.AspectRatioTooLong);
1617
+ }
1221
1618
  bool hasSeenDecimalSeparator = false;
1222
1619
  bool hasSeenNumber = false;
1223
1620
  for (uint256 i; i < bytesLength; i++) {
@@ -1237,12 +1634,17 @@ contract GenArt721CoreV3_Engine is
1237
1634
  continue;
1238
1635
  }
1239
1636
  }
1240
- revert("Improperly formatted aspect ratio");
1637
+ revert GenArt721Error(ErrorCodes.AspectRatioImproperFormat);
1638
+ }
1639
+ if (!hasSeenNumber) {
1640
+ revert GenArt721Error(ErrorCodes.AspectRatioNoNumbers);
1241
1641
  }
1242
- require(hasSeenNumber, "Aspect ratio has no numbers");
1243
1642
 
1244
1643
  projects[_projectId].aspectRatio = _aspectRatio;
1245
- emit ProjectUpdated(_projectId, FIELD_PROJECT_ASPECT_RATIO);
1644
+ emit ProjectUpdated(
1645
+ _projectId,
1646
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_ASPECT_RATIO))
1647
+ );
1246
1648
  }
1247
1649
 
1248
1650
  /**
@@ -1260,7 +1662,10 @@ contract GenArt721CoreV3_Engine is
1260
1662
  _onlyArtist(_projectId);
1261
1663
  _onlyNonEmptyString(_newBaseURI);
1262
1664
  projects[_projectId].projectBaseURI = _newBaseURI;
1263
- emit ProjectUpdated(_projectId, FIELD_PROJECT_BASE_URI);
1665
+ emit ProjectUpdated(
1666
+ _projectId,
1667
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_BASE_URI))
1668
+ );
1264
1669
  }
1265
1670
 
1266
1671
  /**
@@ -1349,7 +1754,7 @@ contract GenArt721CoreV3_Engine is
1349
1754
  function projectIdToArtistAddress(
1350
1755
  uint256 _projectId
1351
1756
  ) external view returns (address payable) {
1352
- return projectIdToFinancials[_projectId].artistAddress;
1757
+ return _projectIdToFinancials[_projectId].artistAddress;
1353
1758
  }
1354
1759
 
1355
1760
  /**
@@ -1364,60 +1769,19 @@ contract GenArt721CoreV3_Engine is
1364
1769
  uint256 _projectId
1365
1770
  ) external view returns (uint256) {
1366
1771
  return
1367
- projectIdToFinancials[_projectId].secondaryMarketRoyaltyPercentage;
1368
- }
1369
-
1370
- /**
1371
- * @notice View function returning Artist's additional payee address for
1372
- * primary sales, for project `_projectId`.
1373
- * @param _projectId Project ID to be queried.
1374
- * @return address Artist's additional payee address for primary sales.
1375
- */
1376
- function projectIdToAdditionalPayeePrimarySales(
1377
- uint256 _projectId
1378
- ) external view returns (address payable) {
1379
- return projectIdToFinancials[_projectId].additionalPayeePrimarySales;
1380
- }
1381
-
1382
- /**
1383
- * @notice View function returning Artist's additional payee primary sales
1384
- * percentage, for project `_projectId`.
1385
- * @param _projectId Project ID to be queried.
1386
- * @return uint256 Artist's additional payee primary sales percentage.
1387
- */
1388
- function projectIdToAdditionalPayeePrimarySalesPercentage(
1389
- uint256 _projectId
1390
- ) external view returns (uint256) {
1391
- return
1392
- projectIdToFinancials[_projectId]
1393
- .additionalPayeePrimarySalesPercentage;
1772
+ _projectIdToFinancials[_projectId].secondaryMarketRoyaltyPercentage;
1394
1773
  }
1395
1774
 
1396
1775
  /**
1397
- * @notice View function returning Artist's additional payee address for
1398
- * secondary sales, for project `_projectId`.
1399
- * @param _projectId Project ID to be queried.
1400
- * @return address payable Artist's additional payee address for secondary
1401
- * sales.
1402
- */
1403
- function projectIdToAdditionalPayeeSecondarySales(
1404
- uint256 _projectId
1405
- ) external view returns (address payable) {
1406
- return projectIdToFinancials[_projectId].additionalPayeeSecondarySales;
1407
- }
1408
-
1409
- /**
1410
- * @notice View function returning Artist's additional payee secondary
1411
- * sales percentage, for project `_projectId`.
1776
+ * @notice View function returning project financial details for project
1777
+ * `_projectId`.
1412
1778
  * @param _projectId Project ID to be queried.
1413
- * @return uint256 Artist's additional payee secondary sales percentage.
1779
+ * @return ProjectFinance Project financial details.
1414
1780
  */
1415
- function projectIdToAdditionalPayeeSecondarySalesPercentage(
1781
+ function projectIdToFinancials(
1416
1782
  uint256 _projectId
1417
- ) external view returns (uint256) {
1418
- return
1419
- projectIdToFinancials[_projectId]
1420
- .additionalPayeeSecondarySalesPercentage;
1783
+ ) external view returns (ProjectFinance memory) {
1784
+ return _projectIdToFinancials[_projectId];
1421
1785
  }
1422
1786
 
1423
1787
  /**
@@ -1491,54 +1855,6 @@ contract GenArt721CoreV3_Engine is
1491
1855
  locked = !_projectUnlocked(_projectId);
1492
1856
  }
1493
1857
 
1494
- /**
1495
- * @notice Returns artist payment information for project `_projectId`.
1496
- * @param _projectId Project to be queried
1497
- * @return artistAddress Project Artist's address
1498
- * @return additionalPayeePrimarySales Additional payee address for primary
1499
- * sales
1500
- * @return additionalPayeePrimarySalesPercentage Percentage of artist revenue
1501
- * to be sent to the additional payee address for primary sales
1502
- * @return additionalPayeeSecondarySales Additional payee address for secondary
1503
- * sales royalties
1504
- * @return additionalPayeeSecondarySalesPercentage Percentage of artist revenue
1505
- * to be sent to the additional payee address for secondary sales royalties
1506
- * @return secondaryMarketRoyaltyPercentage Royalty percentage to be sent to
1507
- * combination of artist and additional payee. This does not include the
1508
- * platform's percentage of secondary sales royalties, which is defined as
1509
- * the sum of `renderProviderSecondarySalesBPS`
1510
- * and `platformProviderSecondarySalesBPS`.
1511
- */
1512
- function projectArtistPaymentInfo(
1513
- uint256 _projectId
1514
- )
1515
- external
1516
- view
1517
- returns (
1518
- address artistAddress,
1519
- address additionalPayeePrimarySales,
1520
- uint256 additionalPayeePrimarySalesPercentage,
1521
- address additionalPayeeSecondarySales,
1522
- uint256 additionalPayeeSecondarySalesPercentage,
1523
- uint256 secondaryMarketRoyaltyPercentage
1524
- )
1525
- {
1526
- ProjectFinance storage projectFinance = projectIdToFinancials[
1527
- _projectId
1528
- ];
1529
- artistAddress = projectFinance.artistAddress;
1530
- additionalPayeePrimarySales = projectFinance
1531
- .additionalPayeePrimarySales;
1532
- additionalPayeePrimarySalesPercentage = projectFinance
1533
- .additionalPayeePrimarySalesPercentage;
1534
- additionalPayeeSecondarySales = projectFinance
1535
- .additionalPayeeSecondarySales;
1536
- additionalPayeeSecondarySalesPercentage = projectFinance
1537
- .additionalPayeeSecondarySalesPercentage;
1538
- secondaryMarketRoyaltyPercentage = projectFinance
1539
- .secondaryMarketRoyaltyPercentage;
1540
- }
1541
-
1542
1858
  /**
1543
1859
  * @notice Returns script information for project `_projectId`.
1544
1860
  * @param _projectId Project to be queried.
@@ -1577,6 +1893,18 @@ contract GenArt721CoreV3_Engine is
1577
1893
  return projects[_projectId].scriptBytecodeAddresses[_index];
1578
1894
  }
1579
1895
 
1896
+ /**
1897
+ * @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`.
1898
+ * @param _script Script to be compressed. Required to be a non-empty string, but no further validaton is performed.
1899
+ * @return bytes compressed bytes
1900
+ */
1901
+ function getCompressed(
1902
+ string memory _script
1903
+ ) external pure returns (bytes memory) {
1904
+ _onlyNonEmptyString(_script);
1905
+ return BytecodeStorageReader.getCompressed(_script);
1906
+ }
1907
+
1580
1908
  /**
1581
1909
  * @notice Returns script for project `_projectId` at script index `_index`.
1582
1910
  * @param _projectId Project to be queried.
@@ -1636,82 +1964,50 @@ contract GenArt721CoreV3_Engine is
1636
1964
  function getHistoricalRandomizerAt(
1637
1965
  uint256 _index
1638
1966
  ) external view returns (address) {
1639
- require(
1640
- _index < _historicalRandomizerAddresses.length,
1641
- "Index out of bounds"
1642
- );
1967
+ if (_index >= _historicalRandomizerAddresses.length) {
1968
+ revert GenArt721Error(ErrorCodes.IndexOutOfBounds);
1969
+ }
1643
1970
  return _historicalRandomizerAddresses[_index];
1644
1971
  }
1645
1972
 
1646
1973
  /**
1647
- * @notice Gets royalty Basis Points (BPS) for token ID `_tokenId`.
1648
- * This conforms to the IManifold interface designated in the Royalty
1649
- * Registry's RoyaltyEngineV1.sol contract.
1650
- * ref: https://github.com/manifoldxyz/royalty-registry-solidity
1651
- * @param _tokenId Token ID to be queried.
1652
- * @return recipients Array of royalty payment recipients
1653
- * @return bps Array of Basis Points (BPS) allocated to each recipient,
1654
- * aligned by index.
1974
+ * @notice Gets ERC-2981 royalty information for token with ID `_tokenId`
1975
+ * and sale price `_salePrice`.
1976
+ * @param _tokenId Token ID to be queried for royalty information
1977
+ * @param _salePrice the sale price of the NFT asset specified by _tokenId
1978
+ * @return receiver address that should be sent the royalty payment
1979
+ * @return royaltyAmount the royalty payment amount for `_salePrice
1655
1980
  * @dev reverts if invalid _tokenId
1656
- * @dev only returns recipients that have a non-zero BPS allocation
1657
1981
  */
1658
- function getRoyalties(
1659
- uint256 _tokenId
1660
- )
1661
- external
1662
- view
1663
- returns (address payable[] memory recipients, uint256[] memory bps)
1664
- {
1982
+ function royaltyInfo(
1983
+ uint256 _tokenId,
1984
+ uint256 _salePrice
1985
+ ) external view returns (address receiver, uint256 royaltyAmount) {
1665
1986
  _onlyValidTokenId(_tokenId);
1666
- // initialize arrays with maximum potential length
1667
- recipients = new address payable[](4);
1668
- bps = new uint256[](4);
1669
1987
 
1988
+ // populate receiver with project's royalty splitter
1989
+ // @dev royalty splitter created upon project creation, so will always exist
1990
+ // for valid token ID
1670
1991
  uint256 projectId = tokenIdToProjectId(_tokenId);
1671
- ProjectFinance storage projectFinance = projectIdToFinancials[
1992
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
1672
1993
  projectId
1673
1994
  ];
1674
- // load values into memory
1675
- uint256 royaltyPercentageForArtistAndAdditional = projectFinance
1676
- .secondaryMarketRoyaltyPercentage;
1677
- uint256 additionalPayeePercentage = projectFinance
1678
- .additionalPayeeSecondarySalesPercentage;
1679
- // calculate BPS = percentage * 100
1680
- uint256 artistBPS = (ONE_HUNDRED - additionalPayeePercentage) *
1681
- royaltyPercentageForArtistAndAdditional;
1682
-
1683
- uint256 additionalBPS = additionalPayeePercentage *
1684
- royaltyPercentageForArtistAndAdditional;
1685
- uint256 renderProviderBPS = renderProviderSecondarySalesBPS;
1686
- uint256 platformProviderBPS = platformProviderSecondarySalesBPS;
1687
- // populate arrays
1688
- uint256 payeeCount;
1689
- if (artistBPS > 0) {
1690
- recipients[payeeCount] = projectFinance.artistAddress;
1691
- bps[payeeCount++] = artistBPS;
1692
- }
1693
- if (additionalBPS > 0) {
1694
- recipients[payeeCount] = projectFinance
1695
- .additionalPayeeSecondarySales;
1696
- bps[payeeCount++] = additionalBPS;
1697
- }
1698
- if (renderProviderBPS > 0) {
1699
- recipients[payeeCount] = renderProviderSecondarySalesAddress;
1700
- bps[payeeCount++] = renderProviderBPS;
1701
- }
1702
- if (platformProviderBPS > 0) {
1703
- recipients[payeeCount] = platformProviderSecondarySalesAddress;
1704
- bps[payeeCount++] = platformProviderBPS;
1705
- }
1706
- // trim arrays if necessary
1707
- if (4 > payeeCount) {
1708
- assembly {
1709
- let decrease := sub(4, payeeCount)
1710
- mstore(recipients, sub(mload(recipients), decrease))
1711
- mstore(bps, sub(mload(bps), decrease))
1712
- }
1995
+ receiver = projectFinance.royaltySplitter;
1996
+
1997
+ // populate royaltyAmount with calculated royalty amount
1998
+ // @dev important to cast to uint256 before multiplying to avoid overflow
1999
+ uint256 totalRoyaltyBPS = (100 *
2000
+ uint256(projectFinance.secondaryMarketRoyaltyPercentage)) +
2001
+ projectFinance.platformProviderSecondarySalesBPS +
2002
+ projectFinance.renderProviderSecondarySalesBPS;
2003
+ // @dev totalRoyaltyBPS guaranteed to be <= 10,000,
2004
+ if (totalRoyaltyBPS > 10_000) {
2005
+ revert GenArt721Error(ErrorCodes.OverMaxSumOfBPS);
1713
2006
  }
1714
- return (recipients, bps);
2007
+ // @dev overflow automatically checked in solidity 0.8
2008
+ // @dev totalRoyaltyBPS guaranteed to be <= 10_000,
2009
+ // so overflow only possible with unreasonably high _salePrice values near uint256 max
2010
+ royaltyAmount = (_salePrice * totalRoyaltyBPS) / 10_000;
1715
2011
  }
1716
2012
 
1717
2013
  /**
@@ -1764,7 +2060,7 @@ contract GenArt721CoreV3_Engine is
1764
2060
  address payable additionalPayeePrimaryAddress_
1765
2061
  )
1766
2062
  {
1767
- ProjectFinance storage projectFinance = projectIdToFinancials[
2063
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
1768
2064
  _projectId
1769
2065
  ];
1770
2066
  // calculate revenues – this is a three-way split between the
@@ -1886,9 +2182,15 @@ contract GenArt721CoreV3_Engine is
1886
2182
  */
1887
2183
  function supportsInterface(
1888
2184
  bytes4 interfaceId
1889
- ) public view virtual override returns (bool) {
2185
+ )
2186
+ public
2187
+ view
2188
+ virtual
2189
+ override(ERC721_PackedHashSeedV1, IERC165)
2190
+ returns (bool)
2191
+ {
1890
2192
  return
1891
- interfaceId == type(IManifold).interfaceId ||
2193
+ interfaceId == _INTERFACE_ID_ERC2981 ||
1892
2194
  super.supportsInterface(interfaceId);
1893
2195
  }
1894
2196
 
@@ -1900,7 +2202,11 @@ contract GenArt721CoreV3_Engine is
1900
2202
  function _forbidNewProjects() internal {
1901
2203
  if (!newProjectsForbidden) {
1902
2204
  newProjectsForbidden = true;
1903
- emit PlatformUpdated(FIELD_NEW_PROJECTS_FORBIDDEN);
2205
+ emit PlatformUpdated(
2206
+ bytes32(
2207
+ uint256(PlatformUpdatedFields.FIELD_NEW_PROJECTS_FORBIDDEN)
2208
+ )
2209
+ );
1904
2210
  }
1905
2211
  }
1906
2212
 
@@ -1920,37 +2226,65 @@ contract GenArt721CoreV3_Engine is
1920
2226
  /**
1921
2227
  * @notice Updates sales addresses for the platform and render providers to
1922
2228
  * the input parameters.
2229
+ * Reverts if invalid platform provider addresses are provided given the
2230
+ * contract's immutably configured nullPlatformProvider state.
2231
+ * Does not check render provider addresses in any way.
1923
2232
  * @param _renderProviderPrimarySalesAddress Address of new primary sales
1924
2233
  * payment address.
1925
- * @param _renderProviderSecondarySalesAddress Address of new secondary sales
2234
+ * @param _defaultRenderProviderSecondarySalesAddress Address of new secondary sales
1926
2235
  * payment address.
1927
2236
  * @param _platformProviderPrimarySalesAddress Address of new primary sales
1928
2237
  * payment address.
1929
- * @param _platformProviderSecondarySalesAddress Address of new secondary sales
2238
+ * @param _defaultPlatformProviderSecondarySalesAddress Address of new secondary sales
1930
2239
  * payment address.
1931
- * @dev Note that this method does not check that the input address is
1932
- * not `address(0)`, as it is expected that callers of this method should
1933
- * perform input validation where applicable.
1934
2240
  */
1935
2241
  function _updateProviderSalesAddresses(
1936
2242
  address _renderProviderPrimarySalesAddress,
1937
- address _renderProviderSecondarySalesAddress,
2243
+ address _defaultRenderProviderSecondarySalesAddress,
1938
2244
  address _platformProviderPrimarySalesAddress,
1939
- address _platformProviderSecondarySalesAddress
2245
+ address _defaultPlatformProviderSecondarySalesAddress
1940
2246
  ) internal {
2247
+ if (nullPlatformProvider) {
2248
+ // require null platform provider address
2249
+ if (
2250
+ _platformProviderPrimarySalesAddress != address(0) ||
2251
+ _defaultPlatformProviderSecondarySalesAddress != address(0)
2252
+ ) {
2253
+ revert GenArt721Error(ErrorCodes.OnlyNullPlatformProvider);
2254
+ }
2255
+ } else {
2256
+ _onlyNonZeroAddress(_platformProviderPrimarySalesAddress);
2257
+ _onlyNonZeroAddress(_defaultPlatformProviderSecondarySalesAddress);
2258
+ }
1941
2259
  platformProviderPrimarySalesAddress = payable(
1942
2260
  _platformProviderPrimarySalesAddress
1943
2261
  );
1944
- platformProviderSecondarySalesAddress = payable(
1945
- _platformProviderSecondarySalesAddress
2262
+ defaultPlatformProviderSecondarySalesAddress = payable(
2263
+ _defaultPlatformProviderSecondarySalesAddress
1946
2264
  );
1947
2265
  renderProviderPrimarySalesAddress = payable(
1948
2266
  _renderProviderPrimarySalesAddress
1949
2267
  );
1950
- renderProviderSecondarySalesAddress = payable(
1951
- _renderProviderSecondarySalesAddress
2268
+ defaultRenderProviderSecondarySalesAddress = payable(
2269
+ _defaultRenderProviderSecondarySalesAddress
2270
+ );
2271
+ emit PlatformUpdated(
2272
+ bytes32(
2273
+ uint256(PlatformUpdatedFields.FIELD_PROVIDER_SALES_ADDRESSES)
2274
+ )
1952
2275
  );
1953
- emit PlatformUpdated(FIELD_PROVIDER_SALES_ADDRESSES);
2276
+ }
2277
+
2278
+ /**
2279
+ * @notice Updates minter address to `_minterAddress`.
2280
+ * @param _minterAddress New minter address.
2281
+ * @dev Note that this method does not check that the input address is
2282
+ * not `address(0)`, as it is expected that callers of this method should
2283
+ * perform input validation where applicable.
2284
+ */
2285
+ function _updateMinterContract(address _minterAddress) internal {
2286
+ minterContract = _minterAddress;
2287
+ emit MinterUpdated(_minterAddress);
1954
2288
  }
1955
2289
 
1956
2290
  /**
@@ -1964,7 +2298,68 @@ contract GenArt721CoreV3_Engine is
1964
2298
  randomizerContract = IRandomizer_V3CoreBase(_randomizerAddress);
1965
2299
  // populate historical randomizer array
1966
2300
  _historicalRandomizerAddresses.push(_randomizerAddress);
1967
- emit PlatformUpdated(FIELD_RANDOMIZER_ADDRESS);
2301
+ emit PlatformUpdated(
2302
+ bytes32(uint256(PlatformUpdatedFields.FIELD_RANDOMIZER_ADDRESS))
2303
+ );
2304
+ }
2305
+
2306
+ /**
2307
+ * @notice Updates split provider address to `_splitProviderAddress`.
2308
+ * Reverts if `_splitProviderAddress` is the zero address.
2309
+ * @param _splitProviderAddress New split provider address.
2310
+ * @dev Note that this method does not check that the input address is
2311
+ * not `address(0)`, as it is expected that callers of this method should
2312
+ * perform input validation where applicable.
2313
+ */
2314
+ function _updateSplitProvider(address _splitProviderAddress) internal {
2315
+ // require non-zero split provider address
2316
+ _onlyNonZeroAddress(_splitProviderAddress);
2317
+ splitProvider = ISplitProviderV0(_splitProviderAddress);
2318
+ emit PlatformUpdated(
2319
+ bytes32(uint256(PlatformUpdatedFields.FIELD_SPLIT_PROVIDER))
2320
+ );
2321
+ }
2322
+
2323
+ /**
2324
+ * @notice internal function to update a splitter contract for a project,
2325
+ * based on the project's financials in this contract's storage.
2326
+ * @dev Warning: this function uses storage reads to get the project's
2327
+ * financials, so ensure storage has been updated before calling this
2328
+ * @dev This function includes a trusted interaction that is entrusted to
2329
+ * not reenter this contract.
2330
+ * @param projectId Project ID to be updated.
2331
+ */
2332
+ function _assignSplitter(uint256 projectId) internal {
2333
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
2334
+ projectId
2335
+ ];
2336
+ // assign project's royalty splitter
2337
+ // @dev loads values from storage, so need to ensure storage has been updated
2338
+ address royaltySplitter = splitProvider.getOrCreateSplitter(
2339
+ ISplitProviderV0.SplitInputs({
2340
+ platformProviderSecondarySalesAddress: projectFinance
2341
+ .platformProviderSecondarySalesAddress,
2342
+ platformProviderSecondarySalesBPS: projectFinance
2343
+ .platformProviderSecondarySalesBPS,
2344
+ renderProviderSecondarySalesAddress: projectFinance
2345
+ .renderProviderSecondarySalesAddress,
2346
+ renderProviderSecondarySalesBPS: projectFinance
2347
+ .renderProviderSecondarySalesBPS,
2348
+ artistTotalRoyaltyPercentage: projectFinance
2349
+ .secondaryMarketRoyaltyPercentage,
2350
+ artist: projectFinance.artistAddress,
2351
+ additionalPayee: projectFinance.additionalPayeeSecondarySales,
2352
+ additionalPayeePercentage: projectFinance
2353
+ .additionalPayeeSecondarySalesPercentage
2354
+ })
2355
+ );
2356
+
2357
+ projectFinance.royaltySplitter = royaltySplitter;
2358
+
2359
+ emit ProjectRoyaltySplitterUpdated({
2360
+ projectId: projectId,
2361
+ royaltySplitter: royaltySplitter
2362
+ });
1968
2363
  }
1969
2364
 
1970
2365
  /**
@@ -1978,7 +2373,9 @@ contract GenArt721CoreV3_Engine is
1978
2373
  */
1979
2374
  function _updateDefaultBaseURI(string memory _defaultBaseURI) internal {
1980
2375
  defaultBaseURI = _defaultBaseURI;
1981
- emit PlatformUpdated(FIELD_DEFAULT_BASE_URI);
2376
+ emit PlatformUpdated(
2377
+ bytes32(uint256(PlatformUpdatedFields.FIELD_DEFAULT_BASE_URI))
2378
+ );
1982
2379
  }
1983
2380
 
1984
2381
  /**
@@ -1987,7 +2384,10 @@ contract GenArt721CoreV3_Engine is
1987
2384
  */
1988
2385
  function _completeProject(uint256 _projectId) internal {
1989
2386
  projects[_projectId].completedTimestamp = uint64(block.timestamp);
1990
- emit ProjectUpdated(_projectId, FIELD_PROJECT_COMPLETED);
2387
+ emit ProjectUpdated(
2388
+ _projectId,
2389
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_COMPLETED))
2390
+ );
1991
2391
  }
1992
2392
 
1993
2393
  /**