@artblocks/contracts 1.1.0 → 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 (257) 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 +273 -155
  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/{minter-suite/Minters → archive/minter-suite/Minters/MinterDAExpSettlement}/MinterDAExpSettlementV2.sol/MinterDAExpSettlementV2.json +3 -3
  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 +567 -206
  41. package/artifacts/contracts/engine/V3/GenArt721CoreV3_Engine_Flex.sol/GenArt721CoreV3_Engine_Flex.json +787 -224
  42. package/artifacts/contracts/engine/V3/forks/GenArt721CoreV3_Engine_Flex_PROOF.sol/GenArt721CoreV3_Engine_Flex_PROOF.json +38 -8
  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 +38 -8
  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/interfaces/v0.8.x/IAdminACLV0_Extended.sol/IAdminACLV0_Extended.json +140 -0
  47. package/artifacts/contracts/interfaces/v0.8.x/IBytecodeStorageReaderV2.sol/IBytecodeStorageReaderV2.json +130 -0
  48. package/artifacts/contracts/interfaces/v0.8.x/IDependencyRegistryV0.sol/IDependencyRegistryV0.json +58 -45
  49. package/artifacts/contracts/interfaces/v0.8.x/IEngineFactoryV0.sol/IEngineFactoryV0.json +283 -0
  50. package/artifacts/contracts/interfaces/v0.8.x/IFilteredMinterDAExpSettlementV0.sol/IFilteredMinterDAExpSettlementV0.json +12 -12
  51. package/artifacts/contracts/interfaces/v0.8.x/IFilteredMinterDAExpSettlementV1.sol/IFilteredMinterDAExpSettlementV1.json +12 -12
  52. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3.sol/IGenArt721CoreContractV3.json +30 -62
  53. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Base.sol/IGenArt721CoreContractV3_Base.json +30 -62
  54. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine.sol/IGenArt721CoreContractV3_Engine.json +170 -104
  55. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex.sol/IGenArt721CoreContractV3_Engine_Flex.json +170 -104
  56. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex_PreV3p2.sol/IGenArt721CoreContractV3_Engine_Flex_PreV3p2.json +1028 -0
  57. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_PreV3p2.sol/IGenArt721CoreContractV3_Engine_PreV3p2.json +741 -0
  58. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_ProjectFinance.sol/IGenArt721CoreContractV3_ProjectFinance.json +87 -0
  59. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721Minter_PBAB.sol/IGenArt721Minter_PBAB.json +279 -0
  60. package/artifacts/contracts/interfaces/v0.8.x/IPseudorandomAtomic.sol/IPseudorandomAtomic.json +1 -1
  61. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterDAExpSettlementV0.sol/ISharedMinterDAExpSettlementV0.json +18 -0
  62. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterRAMV0.sol/ISharedMinterRAMV0.json +62 -0
  63. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterRequired.sol/ISharedMinterRequired.json +37 -0
  64. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterSEAV0.sol/ISharedMinterSEAV0.json +1 -1
  65. package/artifacts/contracts/interfaces/v0.8.x/ISplitAtomicFactoryV0.sol/ISplitAtomicFactoryV0.json +170 -0
  66. package/artifacts/contracts/interfaces/v0.8.x/ISplitAtomicV0.sol/ISplitAtomicV0.json +126 -0
  67. package/artifacts/contracts/interfaces/v0.8.x/ISplitProviderV0.sol/ISplitProviderV0.json +98 -0
  68. package/artifacts/contracts/interfaces/v0.8.x/integration-refs/splits-0x-v2/ISplitFactoryV2.sol/ISplitFactoryV2.json +123 -0
  69. package/artifacts/contracts/libs/integration-refs/delegation-registry/DelegationRegistry.sol/DelegationRegistry.json +2 -2
  70. package/artifacts/contracts/libs/integration-refs/gnosis-safe/GnosisSafeMock.sol/GnosisSafeMock.json +2 -2
  71. package/artifacts/contracts/libs/integration-refs/gnosis-safe/GnosisSafeProxyFactoryMock.sol/GnosisSafeProxyFactoryMock.json +2 -2
  72. package/artifacts/contracts/libs/integration-refs/gnosis-safe/MultiSendMock.sol/MultiSendMock.json +2 -2
  73. package/artifacts/contracts/libs/integration-refs/weth9/weth9.sol/WETH9_.json +2 -2
  74. package/artifacts/contracts/libs/v0.8.x/ABHelpers.sol/ABHelpers.json +2 -2
  75. package/artifacts/contracts/libs/v0.8.x/AuthLib.sol/AuthLib.json +2 -2
  76. package/artifacts/contracts/libs/v0.8.x/BitMap.sol/BitMaps256.json +10 -0
  77. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV0.sol/BytecodeStorage.json +2 -2
  78. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV1.sol/BytecodeStorageReader.json +2 -2
  79. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV1.sol/BytecodeStorageWriter.json +2 -2
  80. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV2.sol/BytecodeStorageReader.json +214 -0
  81. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV2.sol/BytecodeStorageWriter.json +10 -0
  82. package/artifacts/contracts/libs/v0.8.x/Bytes32Strings.sol/Bytes32Strings.json +2 -2
  83. package/artifacts/contracts/libs/v0.8.x/DependencyRegistryStorageLib.sol/DependencyRegistryStorageLib.json +10 -0
  84. package/artifacts/contracts/libs/v0.8.x/ERC721_PackedHashSeed.sol/ERC721_PackedHashSeed.json +2 -2
  85. package/artifacts/contracts/libs/v0.8.x/ERC721_PackedHashSeedV1.sol/ERC721_PackedHashSeedV1.json +444 -0
  86. package/artifacts/contracts/libs/v0.8.x/PackedBools.sol/PackedBools.json +10 -0
  87. package/artifacts/contracts/libs/v0.8.x/SSTORE2.sol/SSTORE2.json +2 -2
  88. package/artifacts/contracts/libs/v0.8.x/V3FlexLib.sol/V3FlexLib.json +208 -0
  89. package/artifacts/contracts/libs/v0.8.x/minter-libs/DAExpLib.sol/DAExpLib.json +2 -2
  90. package/artifacts/contracts/libs/v0.8.x/minter-libs/DALib.sol/DALib.json +2 -2
  91. package/artifacts/contracts/libs/v0.8.x/minter-libs/DALinLib.sol/DALinLib.json +2 -2
  92. package/artifacts/contracts/libs/v0.8.x/minter-libs/GenericMinterEventsLib.sol/GenericMinterEventsLib.json +2 -2
  93. package/artifacts/contracts/libs/v0.8.x/minter-libs/MaxInvocationsLib.sol/MaxInvocationsLib.json +2 -2
  94. package/artifacts/contracts/libs/v0.8.x/minter-libs/MerkleLib.sol/MerkleLib.json +2 -2
  95. package/artifacts/contracts/libs/v0.8.x/minter-libs/PolyptychLib.sol/PolyptychLib.json +2 -2
  96. package/artifacts/contracts/libs/v0.8.x/minter-libs/RAMLib.sol/RAMLib.json +398 -0
  97. package/artifacts/contracts/libs/v0.8.x/minter-libs/SEALib.sol/SEALib.json +2 -2
  98. package/artifacts/contracts/libs/v0.8.x/minter-libs/SetPriceLib.sol/SetPriceLib.json +2 -2
  99. package/artifacts/contracts/libs/v0.8.x/minter-libs/SettlementExpLib.sol/SettlementExpLib.json +2 -2
  100. package/artifacts/contracts/libs/v0.8.x/minter-libs/SplitFundsLib.sol/SplitFundsLib.json +2 -2
  101. package/artifacts/contracts/libs/v0.8.x/minter-libs/TokenHolderLib.sol/TokenHolderLib.json +2 -2
  102. package/artifacts/contracts/minter-suite/MinterFilter/MinterFilterV1.sol/MinterFilterV1.json +2 -2
  103. package/artifacts/contracts/minter-suite/MinterFilter/MinterFilterV2.sol/MinterFilterV2.json +2 -2
  104. package/artifacts/contracts/minter-suite/Minters/MinterDAExpHolderV5.sol/MinterDAExpHolderV5.json +2 -2
  105. package/artifacts/contracts/minter-suite/Minters/MinterDAExpSettlementV3.sol/MinterDAExpSettlementV3.json +2 -2
  106. package/artifacts/contracts/minter-suite/Minters/MinterDAExpV5.sol/MinterDAExpV5.json +2 -2
  107. package/artifacts/contracts/minter-suite/Minters/MinterDALinHolderV5.sol/MinterDALinHolderV5.json +2 -2
  108. package/artifacts/contracts/minter-suite/Minters/MinterDALinV5.sol/MinterDALinV5.json +2 -2
  109. package/artifacts/contracts/minter-suite/Minters/MinterRAMV0.sol/MinterRAMV0.json +1374 -0
  110. package/artifacts/contracts/minter-suite/Minters/MinterSEAV1.sol/MinterSEAV1.json +7 -7
  111. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceERC20V5.sol/MinterSetPriceERC20V5.json +2 -2
  112. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceHolderV5.sol/MinterSetPriceHolderV5.json +2 -2
  113. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceMerkleV5.sol/MinterSetPriceMerkleV5.json +2 -2
  114. package/artifacts/contracts/minter-suite/Minters/MinterSetPricePolyptychERC20V5.sol/MinterSetPricePolyptychERC20V5.json +2 -2
  115. package/artifacts/contracts/minter-suite/Minters/MinterSetPricePolyptychV5.sol/MinterSetPricePolyptychV5.json +2 -2
  116. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceV5.sol/MinterSetPriceV5.json +2 -2
  117. package/artifacts/contracts/minter-suite/Minters/one-off/MinterSetPriceV5_SingleCore.sol/MinterSetPriceV5_SingleCore.json +417 -0
  118. package/artifacts/contracts/mock/BytecodeV2LibCallsMock.sol/BytecodeV2LibCallsMock.json +154 -0
  119. package/artifacts/contracts/mock/BytecodeV2TextCR_DMock.sol/BytecodeV2TextCR_DMock.json +428 -0
  120. package/artifacts/contracts/mock/DummySharedMinter.sol/DummySharedMinter.json +2 -2
  121. package/artifacts/contracts/mock/ERC20Mock.sol/ERC20Mock.json +2 -2
  122. package/artifacts/contracts/mock/ForceSendMock.sol/ForceSendMock.json +24 -0
  123. package/artifacts/contracts/mock/GenArt721CoreV3_Engine_IncorrectCoreType.sol/GenArt721CoreV3_Engine_IncorrectCoreType.json +2 -2
  124. package/artifacts/contracts/mock/Mock0xSplitsV2PullFactory.sol/Mock0xSplitsV2PullFactory.json +149 -0
  125. package/artifacts/contracts/mock/Mock0xSplitsV2Splitter.sol/Mock0xSplitsV2Splitter.json +99 -0
  126. package/artifacts/contracts/mock/MockAdminACLV0.sol/MockAdminACLV0Events.json +20 -2
  127. package/artifacts/contracts/mock/MockAdminACLV0_PROHIBITION.sol/MockAdminACLV0Events_PROHIBITION.json +20 -2
  128. package/artifacts/contracts/mock/RandomizerV2_NoAssignMock.sol/RandomizerV2_NoAssignMock.json +2 -2
  129. package/artifacts/contracts/mock/ReentrancyGenArt721MinterMock.sol/ReentrancyGenArt721MinterMock.json +100 -0
  130. package/artifacts/contracts/mock/ReentrancyHolderMock.sol/ReentrancyHolderMock.json +2 -2
  131. package/artifacts/contracts/mock/ReentrancyHolderMockShared.sol/ReentrancyHolderMockShared.json +2 -2
  132. package/artifacts/contracts/mock/ReentrancyMerkleMock.sol/ReentrancyMerkleMock.json +2 -2
  133. package/artifacts/contracts/mock/ReentrancyMerkleMockShared.sol/ReentrancyMerkleMockShared.json +2 -2
  134. package/artifacts/contracts/mock/ReentrancyMock.sol/ReentrancyMock.json +2 -2
  135. package/artifacts/contracts/mock/ReentrancyMockShared.sol/ReentrancyMockShared.json +2 -2
  136. package/artifacts/contracts/mock/ReentrancySEAMock.sol/ReentrancySEAAutoBidderMock.json +2 -2
  137. package/artifacts/contracts/mock/ReentrancySEAMockShared.sol/ReentrancySEAAutoBidderMockShared.json +2 -2
  138. package/artifacts/contracts/mock/ReentrancySplitterMocks.sol/ReentrancySplitterDrainETHMock.json +54 -0
  139. package/artifacts/contracts/mock/ReentrancySplitterMocks.sol/ReentrancySplitterSendETHMock.json +54 -0
  140. package/artifacts/contracts/randomizer/deprecated/PolyptychRandomizerV0.sol/BasicPolyptychRandomizerV0.json +2 -2
  141. package/artifacts/contracts/randomizer/deprecated/RandomizerV2.sol/BasicRandomizerV2.json +2 -2
  142. package/artifacts/contracts/randomizer/primitive/PseudorandomAtomicBasic.sol/PseudorandomAtomic.json +2 -2
  143. package/artifacts/contracts/randomizer/shared/SharedRandomizerV0.sol/SharedRandomizerV0.json +2 -2
  144. package/artifacts/contracts/split/SplitAtomicFactoryV0.sol/SplitAtomicFactoryV0.json +203 -0
  145. package/artifacts/contracts/split/SplitAtomicV0.sol/SplitAtomicV0.json +168 -0
  146. package/artifacts/contracts/split/split-provider/SplitProviderV0.sol/SplitProviderV0.json +141 -0
  147. package/contracts/AdminACLV0.sol +6 -2
  148. package/contracts/AdminACLV1.sol +2 -2
  149. package/contracts/DependencyRegistryV0.sol +687 -408
  150. package/contracts/{GenArt721CoreV3.sol → archive/GenArt721CoreV3.sol} +56 -20
  151. package/contracts/{explorations → archive}/GenArt721CoreV3_Explorations.sol +49 -13
  152. package/contracts/{minter-suite → archive/minter-suite}/Minters/MinterBase_v0_1_1.sol +4 -4
  153. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterDAExp}/MinterDAExpV4.sol +4 -4
  154. package/contracts/archive/minter-suite/Minters/MinterDAExpSettlement/MinterDAExpSettlementV0.sol +4 -4
  155. package/contracts/archive/minter-suite/Minters/MinterDAExpSettlement/MinterDAExpSettlementV1.sol +5 -5
  156. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterDAExpSettlement}/MinterDAExpSettlementV2.sol +8 -8
  157. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterDALin}/MinterDALinV4.sol +4 -4
  158. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterHolder}/MinterHolderV4.sol +5 -5
  159. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterMerkle}/MinterMerkleV5.sol +5 -5
  160. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterPolyptych}/MinterPolyptychV0.sol +7 -7
  161. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterSEA}/MinterSEAV0.sol +13 -13
  162. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterSetPrice}/MinterSetPriceV4.sol +4 -4
  163. package/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V0.sol +82 -10
  164. package/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V1.sol +82 -10
  165. package/contracts/{minter-suite/Minters → archive/minter-suite/Minters/MinterSetPriceERC20}/MinterSetPriceERC20V4.sol +88 -21
  166. package/contracts/engine/V2/GenArt721MinterBurner_PBAB.sol +81 -22
  167. package/contracts/engine/V2/GenArt721Minter_PBAB.sol +80 -22
  168. package/contracts/engine/V3/EngineFactoryV0.sol +419 -0
  169. package/contracts/engine/V3/GenArt721CoreV3_Engine.sol +894 -488
  170. package/contracts/engine/V3/GenArt721CoreV3_Engine_Flex.sol +1054 -650
  171. package/contracts/engine/V3/forks/GenArt721CoreV3_Engine_Flex_PROOF.sol +3 -3
  172. package/contracts/engine/V3/forks/PROHIBITION/GenArt721CoreV3_Engine_Flex_PROHIBITION.sol +1 -1
  173. package/contracts/engine/V3/forks/PROHIBITION/interfaces/IGenArt721CoreContractV3_Engine_Flex_PROHIBITION.sol +2 -2
  174. package/contracts/interfaces/v0.8.x/IAdminACLV0_Extended.sol +20 -0
  175. package/contracts/interfaces/v0.8.x/IBytecodeStorageReaderV2.sol +23 -0
  176. package/contracts/interfaces/v0.8.x/IDependencyRegistryV0.sol +47 -45
  177. package/contracts/interfaces/v0.8.x/IEngineFactoryV0.sol +124 -0
  178. package/contracts/interfaces/v0.8.x/IFilteredMinterDAExpSettlementV0.sol +1 -3
  179. package/contracts/interfaces/v0.8.x/IFilteredMinterDAExpSettlementV1.sol +1 -3
  180. package/contracts/interfaces/v0.8.x/IFilteredMinterDAExpV1.sol +1 -3
  181. package/contracts/interfaces/v0.8.x/IFilteredMinterDALinV1.sol +1 -3
  182. package/contracts/interfaces/v0.8.x/IFilteredMinterHolderV2.sol +1 -3
  183. package/contracts/interfaces/v0.8.x/IFilteredMinterMerkleV2.sol +1 -3
  184. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Base.sol +115 -11
  185. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine.sol +84 -8
  186. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex.sol +26 -8
  187. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex_PreV3p2.sol +141 -0
  188. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_PreV3p2.sol +78 -0
  189. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_ProjectFinance.sol +47 -0
  190. package/contracts/interfaces/v0.8.x/IGenArt721Minter_PBAB.sol +91 -0
  191. package/contracts/interfaces/v0.8.x/IPseudorandomAtomic.sol +1 -3
  192. package/contracts/interfaces/v0.8.x/ISharedMinterDAExpSettlementV0.sol +19 -0
  193. package/contracts/interfaces/v0.8.x/ISharedMinterRAMV0.sol +23 -0
  194. package/contracts/interfaces/v0.8.x/ISharedMinterRequired.sol +20 -0
  195. package/contracts/interfaces/v0.8.x/ISharedMinterSEAV0.sol +1 -4
  196. package/contracts/interfaces/v0.8.x/ISharedMinterV0.sol +12 -6
  197. package/contracts/interfaces/v0.8.x/ISplitAtomicFactoryV0.sol +81 -0
  198. package/contracts/interfaces/v0.8.x/ISplitAtomicV0.sol +72 -0
  199. package/contracts/interfaces/v0.8.x/ISplitProviderV0.sol +49 -0
  200. package/contracts/interfaces/v0.8.x/integration-refs/splits-0x-v2/ISplitFactoryV2.sol +62 -0
  201. package/contracts/libs/v0.8.x/ABHelpers.sol +18 -4
  202. package/contracts/libs/v0.8.x/BitMap.sol +112 -0
  203. package/contracts/libs/v0.8.x/BytecodeStorageV2.sol +593 -0
  204. package/contracts/libs/v0.8.x/DependencyRegistryStorageLib.sol +90 -0
  205. package/contracts/libs/v0.8.x/ERC721_PackedHashSeedV1.sol +591 -0
  206. package/contracts/libs/v0.8.x/PackedBools.sol +42 -0
  207. package/contracts/libs/v0.8.x/V3FlexLib.sol +591 -0
  208. package/contracts/libs/v0.8.x/minter-libs/DAExpLib.sol +10 -12
  209. package/contracts/libs/v0.8.x/minter-libs/DALinLib.sol +4 -9
  210. package/contracts/libs/v0.8.x/minter-libs/GenericMinterEventsLib.sol +44 -44
  211. package/contracts/libs/v0.8.x/minter-libs/MaxInvocationsLib.sol +64 -63
  212. package/contracts/libs/v0.8.x/minter-libs/MerkleLib.sol +14 -10
  213. package/contracts/libs/v0.8.x/minter-libs/RAMLib.sol +2927 -0
  214. package/contracts/libs/v0.8.x/minter-libs/SEALib.sol +60 -62
  215. package/contracts/libs/v0.8.x/minter-libs/SetPriceLib.sol +4 -8
  216. package/contracts/libs/v0.8.x/minter-libs/SettlementExpLib.sol +92 -89
  217. package/contracts/libs/v0.8.x/minter-libs/SplitFundsLib.sol +21 -15
  218. package/contracts/libs/v0.8.x/minter-libs/TokenHolderLib.sol +5 -4
  219. package/contracts/minter-suite/MinterFilter/MinterFilterV2.sol +16 -10
  220. package/contracts/minter-suite/Minters/MinterDAExpHolderV5.sol +2 -2
  221. package/contracts/minter-suite/Minters/MinterDAExpSettlementV3.sol +19 -15
  222. package/contracts/minter-suite/Minters/MinterDAExpV5.sol +2 -2
  223. package/contracts/minter-suite/Minters/MinterDALinHolderV5.sol +2 -2
  224. package/contracts/minter-suite/Minters/MinterDALinV5.sol +2 -2
  225. package/contracts/minter-suite/Minters/MinterRAMV0.sol +1205 -0
  226. package/contracts/minter-suite/Minters/MinterSEAV1.sol +21 -32
  227. package/contracts/minter-suite/Minters/MinterSetPriceERC20V5.sol +17 -8
  228. package/contracts/minter-suite/Minters/MinterSetPriceHolderV5.sol +2 -2
  229. package/contracts/minter-suite/Minters/MinterSetPriceMerkleV5.sol +2 -2
  230. package/contracts/minter-suite/Minters/MinterSetPricePolyptychERC20V5.sol +23 -9
  231. package/contracts/minter-suite/Minters/MinterSetPricePolyptychV5.sol +2 -2
  232. package/contracts/minter-suite/Minters/MinterSetPriceV5.sol +2 -2
  233. package/contracts/minter-suite/Minters/one-off/MinterSetPriceV5_SingleCore.sol +446 -0
  234. package/contracts/mock/BytecodeV2LibCallsMock.sol +128 -0
  235. package/contracts/mock/BytecodeV2TextCR_DMock.sol +316 -0
  236. package/contracts/mock/ForceSendMock.sol +22 -0
  237. package/contracts/mock/Mock0xSplitsV2PullFactory.sol +75 -0
  238. package/contracts/mock/Mock0xSplitsV2Splitter.sol +47 -0
  239. package/contracts/mock/MockAdminACLV0.sol +21 -0
  240. package/contracts/mock/MockAdminACLV0_PROHIBITION.sol +21 -0
  241. package/contracts/mock/ReentrancyGenArt721MinterMock.sol +47 -0
  242. package/contracts/mock/ReentrancySplitterMocks.sol +67 -0
  243. package/contracts/randomizer/primitive/PseudorandomAtomicBasic.sol +1 -1
  244. package/contracts/randomizer/shared/SharedRandomizerV0.sol +1 -1
  245. package/contracts/split/SplitAtomicFactoryV0.sol +121 -0
  246. package/contracts/split/SplitAtomicV0.sol +265 -0
  247. package/contracts/split/split-provider/SplitProviderV0.sol +201 -0
  248. package/package.json +62 -34
  249. package/artifacts/contracts/GenArt721CoreV3.sol/GenArt721CoreV3.json +0 -1965
  250. package/artifacts/contracts/explorations/GenArt721CoreV3_Explorations.sol/GenArt721CoreV3_Explorations.json +0 -1939
  251. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceERC20V4.sol/MinterSetPriceERC20V4.json +0 -768
  252. package/artifacts/contracts/royalty-registry/GenArt721RoyaltyOverride.sol/GenArt721RoyaltyOverride.json +0 -208
  253. package/artifacts/contracts/royalty-registry/GenArt721RoyaltyOverride_PBAB.sol/GenArt721RoyaltyOverride_PBAB.json +0 -301
  254. package/contracts/archive/readme.md +0 -16
  255. package/contracts/engine/README.md +0 -21
  256. package/contracts/royalty-registry/GenArt721RoyaltyOverride.sol +0 -168
  257. package/contracts/royalty-registry/GenArt721RoyaltyOverride_PBAB.sol +0 -221
@@ -1,19 +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";
7
+ import "../../interfaces/v0.8.x/IAdminACLV0_Extended.sol";
8
8
  import "../../interfaces/v0.8.x/IGenArt721CoreContractV3_Engine.sol";
9
+ import {IGenArt721CoreContractV3_ProjectFinance} from "../../interfaces/v0.8.x/IGenArt721CoreContractV3_ProjectFinance.sol";
9
10
  import "../../interfaces/v0.8.x/IGenArt721CoreContractExposesHashSeed.sol";
10
11
  import "../../interfaces/v0.8.x/IDependencyRegistryCompatibleV0.sol";
11
- import "../../interfaces/v0.8.x/IManifold.sol";
12
+ import {ISplitProviderV0} from "../../interfaces/v0.8.x/ISplitProviderV0.sol";
12
13
 
13
- import "@openzeppelin-4.7/contracts/utils/Strings.sol";
14
- import "@openzeppelin-4.7/contracts/access/Ownable.sol";
15
- import "../../libs/v0.8.x/ERC721_PackedHashSeed.sol";
16
- import "../../libs/v0.8.x/BytecodeStorageV1.sol";
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";
17
19
  import "../../libs/v0.8.x/Bytes32Strings.sol";
18
20
 
19
21
  /**
@@ -33,22 +35,27 @@ import "../../libs/v0.8.x/Bytes32Strings.sol";
33
35
  * ----------------------------------------------------------------------------
34
36
  * The following functions are restricted to the Admin ACL contract:
35
37
  * - updateArtblocksDependencyRegistryAddress
38
+ * - updateArtblocksOnChainGeneratorAddress
39
+ * - updateNextCoreContract
36
40
  * - updateProviderSalesAddresses
37
41
  * - updateProviderPrimarySalesPercentages (up to 100%)
38
- * - updateProviderSecondarySalesBPS (up to 100%)
42
+ * - updateProviderDefaultSecondarySalesBPS (up to 100%)
43
+ * - syncProviderSecondaryForProjectToDefaults
39
44
  * - updateMinterContract
40
45
  * - updateRandomizerAddress
41
- * - toggleProjectIsActive
46
+ * - toggleProjectIsActive (note: artist may be configured to activate projects)
42
47
  * - addProject
43
48
  * - forbidNewProjects (forever forbidding new projects)
44
49
  * - updateDefaultBaseURI (used to initialize new project base URIs)
50
+ * - updateSplitProvider
45
51
  * ----------------------------------------------------------------------------
46
- * The following functions are restricted to either the the Artist address or
52
+ * The following functions are restricted to either the Artist address or
47
53
  * the Admin ACL contract, only when the project is not locked:
48
54
  * - updateProjectName
49
55
  * - updateProjectArtistName
50
56
  * - updateProjectLicense
51
- * - Change project script via addProjectScript, updateProjectScript,
57
+ * - Change project script via addProjectScript, addProjectScriptCompressed,
58
+ * updateProjectScript, updateProjectScriptCompressed,
52
59
  * and removeProjectLastScript
53
60
  * - updateProjectScriptType
54
61
  * - updateProjectAspectRatio
@@ -92,14 +99,16 @@ import "../../libs/v0.8.x/Bytes32Strings.sol";
92
99
  * registries, and other contracts that may interact with this core contract.
93
100
  */
94
101
  contract GenArt721CoreV3_Engine is
95
- ERC721_PackedHashSeed,
102
+ ERC721_PackedHashSeedV1,
96
103
  Ownable,
104
+ IERC2981,
97
105
  IDependencyRegistryCompatibleV0,
98
- IManifold,
99
106
  IGenArt721CoreContractV3_Engine,
107
+ IGenArt721CoreContractV3_ProjectFinance,
100
108
  IGenArt721CoreContractExposesHashSeed
101
109
  {
102
110
  using BytecodeStorageWriter for string;
111
+ using BytecodeStorageWriter for bytes;
103
112
  using Bytes32Strings for bytes32;
104
113
  using Strings for uint256;
105
114
  using Strings for address;
@@ -113,49 +122,16 @@ contract GenArt721CoreV3_Engine is
113
122
  uint256 constant MAX_PROVIDER_SECONDARY_SALES_BPS = 10000; // 10_000 BPS = 100%
114
123
  uint256 constant ARTIST_MAX_SECONDARY_ROYALTY_PERCENTAGE = 95; // 95%
115
124
 
116
- // This contract emits generic events that contain fields that indicate
117
- // which parameter has been updated. This is sufficient for application
118
- // state management, while also simplifying the contract and indexing code.
119
- // This was done as an alternative to having custom events that emit what
120
- // field-values have changed for each event, given that changed values can
121
- // be introspected by indexers due to the design of this smart contract
122
- // exposing these state changes via publicly viewable fields.
123
- //
124
- // The following fields are used to indicate which contract-level parameter
125
- // has been updated in the `PlatformUpdated` event:
126
- bytes32 constant FIELD_NEXT_PROJECT_ID = "nextProjectId";
127
- bytes32 constant FIELD_NEW_PROJECTS_FORBIDDEN = "newProjectsForbidden";
128
- bytes32 constant FIELD_DEFAULT_BASE_URI = "defaultBaseURI";
129
- bytes32 constant FIELD_RANDOMIZER_ADDRESS = "randomizerAddress";
130
- bytes32 constant FIELD_ARTBLOCKS_DEPENDENCY_REGISTRY_ADDRESS =
131
- "dependencyRegistryAddress";
132
- bytes32 constant FIELD_PROVIDER_SALES_ADDRESSES = "providerSalesAddresses";
133
- bytes32 constant FIELD_PROVIDER_PRIMARY_SALES_PERCENTAGES =
134
- "providerPrimaryPercentages";
135
- bytes32 constant FIELD_PROVIDER_SECONDARY_SALES_BPS =
136
- "providerSecondaryBPS";
137
- // The following fields are used to indicate which project-level parameter
138
- // has been updated in the `ProjectUpdated` event:
139
- bytes32 constant FIELD_PROJECT_COMPLETED = "completed";
140
- bytes32 constant FIELD_PROJECT_ACTIVE = "active";
141
- bytes32 constant FIELD_PROJECT_ARTIST_ADDRESS = "artistAddress";
142
- bytes32 constant FIELD_PROJECT_PAUSED = "paused";
143
- bytes32 constant FIELD_PROJECT_CREATED = "created";
144
- bytes32 constant FIELD_PROJECT_NAME = "name";
145
- bytes32 constant FIELD_PROJECT_ARTIST_NAME = "artistName";
146
- bytes32 constant FIELD_PROJECT_SECONDARY_MARKET_ROYALTY_PERCENTAGE =
147
- "royaltyPercentage";
148
- bytes32 constant FIELD_PROJECT_DESCRIPTION = "description";
149
- bytes32 constant FIELD_PROJECT_WEBSITE = "website";
150
- bytes32 constant FIELD_PROJECT_LICENSE = "license";
151
- bytes32 constant FIELD_PROJECT_MAX_INVOCATIONS = "maxInvocations";
152
- bytes32 constant FIELD_PROJECT_SCRIPT = "script";
153
- bytes32 constant FIELD_PROJECT_SCRIPT_TYPE = "scriptType";
154
- bytes32 constant FIELD_PROJECT_ASPECT_RATIO = "aspectRatio";
155
- bytes32 constant FIELD_PROJECT_BASE_URI = "baseURI";
125
+ /// pointer to next core contract associated with this contract
126
+ address public nextCoreContract;
156
127
 
157
128
  /// Dependency registry managed by Art Blocks
158
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;
159
135
 
160
136
  /// current randomizer contract
161
137
  IRandomizer_V3CoreBase public randomizerContract;
@@ -189,20 +165,10 @@ contract GenArt721CoreV3_Engine is
189
165
 
190
166
  mapping(uint256 => Project) projects;
191
167
 
192
- /// packed struct containing project financial information
193
- struct ProjectFinance {
194
- address payable additionalPayeePrimarySales;
195
- // packed uint: max of 95, max uint8 = 255
196
- uint8 secondaryMarketRoyaltyPercentage;
197
- address payable additionalPayeeSecondarySales;
198
- // packed uint: max of 100, max uint8 = 255
199
- uint8 additionalPayeeSecondarySalesPercentage;
200
- address payable artistAddress;
201
- // packed uint: max of 100, max uint8 = 255
202
- uint8 additionalPayeePrimarySalesPercentage;
203
- }
204
- // Project financials mapping
205
- 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;
206
172
 
207
173
  /// hash of artist's proposed payment updates to be approved by admin
208
174
  mapping(uint256 => bytes32) public proposedArtistAddressesAndSplitsHash;
@@ -213,33 +179,54 @@ contract GenArt721CoreV3_Engine is
213
179
  /// Percentage of primary sales revenue allocated to the render provider
214
180
  /// (packed)
215
181
  // packed uint: max of 100, max uint8 = 255
216
- uint8 private _renderProviderPrimarySalesPercentage = 10;
182
+ uint8 private _renderProviderPrimarySalesPercentage;
217
183
  /// The platform provider payment address for all primary sales revenues
218
184
  /// (packed)
219
185
  address payable public platformProviderPrimarySalesAddress;
220
186
  /// Percentage of primary sales revenue allocated to the platform provider
221
187
  /// (packed)
222
188
  // packed uint: max of 100, max uint8 = 255
223
- uint8 private _platformProviderPrimarySalesPercentage = 10;
224
-
225
- /// The render provider payment address for all secondary sales royalty
226
- /// revenues
227
- address payable public renderProviderSecondarySalesAddress;
228
- /// Basis Points of secondary sales royalties allocated to the
229
- /// render provider
230
- uint256 public renderProviderSecondarySalesBPS = 250;
231
- /// The platform provider payment address for all secondary sales royalty
232
- /// revenues
233
- address payable public platformProviderSecondarySalesAddress;
234
- /// Basis Points of secondary sales royalties allocated to the
235
- /// platform provider
236
- 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
+ /// -----------------------------------------------------------------------
237
220
 
238
221
  /// single minter allowed for this core contract
239
222
  address public minterContract;
240
223
 
241
- /// starting (initial) project ID on this contract
242
- 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;
243
230
 
244
231
  /// next project ID to be created
245
232
  uint248 private _nextProjectId;
@@ -248,17 +235,37 @@ contract GenArt721CoreV3_Engine is
248
235
  /// default behavior is to allow new projects
249
236
  bool public newProjectsForbidden;
250
237
 
251
- /// configuration variable (determined at time of deployment)
252
- /// that determines whether or not admin approval^ should be required
253
- /// to accept artist address change proposals, or if these proposals
254
- /// should always auto-approve, as determined by the business process
255
- /// 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.
256
244
  ///
257
245
  /// ^does not apply in the case where contract-ownership itself is revoked
258
- 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;
259
266
 
260
267
  /// version & type of this core contract
261
- bytes32 constant CORE_VERSION = "v3.1.4";
268
+ bytes32 constant CORE_VERSION = "v3.2.2";
262
269
 
263
270
  function coreVersion() external pure returns (string memory) {
264
271
  return CORE_VERSION.toString();
@@ -273,54 +280,84 @@ contract GenArt721CoreV3_Engine is
273
280
  /// default base URI to initialize all new project projectBaseURI values to
274
281
  string public defaultBaseURI;
275
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
+
276
301
  function _onlyNonZeroAddress(address _address) internal pure {
277
- require(_address != address(0), "Must input non-zero address");
302
+ if (_address == address(0)) {
303
+ revert GenArt721Error(ErrorCodes.OnlyNonZeroAddress);
304
+ }
278
305
  }
279
306
 
280
307
  function _onlyNonEmptyString(string memory _string) internal pure {
281
- 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
+ }
282
317
  }
283
318
 
284
319
  function _onlyValidTokenId(uint256 _tokenId) internal view {
285
- require(_exists(_tokenId), "Token ID does not exist");
320
+ if (_ownerOf(_tokenId) == address(0)) {
321
+ revert GenArt721Error(ErrorCodes.TokenDoesNotExist);
322
+ }
286
323
  }
287
324
 
288
325
  function _onlyValidProjectId(uint256 _projectId) internal view {
289
- require(
290
- (_projectId >= startingProjectId) && (_projectId < _nextProjectId),
291
- "Project ID does not exist"
292
- );
326
+ if (_projectId < startingProjectId || _projectId >= _nextProjectId) {
327
+ revert GenArt721Error(ErrorCodes.ProjectDoesNotExist);
328
+ }
293
329
  }
294
330
 
295
331
  function _onlyUnlocked(uint256 _projectId) internal view {
296
332
  // Note: calling `_projectUnlocked` enforces that the `_projectId`
297
333
  // passed in is valid.`
298
- require(_projectUnlocked(_projectId), "Only if unlocked");
334
+ if (!_projectUnlocked(_projectId)) {
335
+ revert GenArt721Error(ErrorCodes.OnlyUnlockedProjects);
336
+ }
299
337
  }
300
338
 
301
339
  function _onlyAdminACL(bytes4 _selector) internal {
302
- require(
303
- adminACLAllowed(msg.sender, address(this), _selector),
304
- "Only Admin ACL allowed"
305
- );
340
+ if (!adminACLAllowed(msg.sender, address(this), _selector)) {
341
+ revert GenArt721Error(ErrorCodes.OnlyAdminACL);
342
+ }
306
343
  }
307
344
 
308
345
  function _onlyArtist(uint256 _projectId) internal view {
309
- require(
310
- msg.sender == projectIdToFinancials[_projectId].artistAddress,
311
- "Only artist"
312
- );
346
+ if (msg.sender != _projectIdToFinancials[_projectId].artistAddress) {
347
+ revert GenArt721Error(ErrorCodes.OnlyArtist);
348
+ }
313
349
  }
314
350
 
315
351
  function _onlyArtistOrAdminACL(
316
352
  uint256 _projectId,
317
353
  bytes4 _selector
318
354
  ) internal {
319
- require(
320
- msg.sender == projectIdToFinancials[_projectId].artistAddress ||
321
- adminACLAllowed(msg.sender, address(this), _selector),
322
- "Only artist or Admin ACL allowed"
323
- );
355
+ if (
356
+ !(msg.sender == _projectIdToFinancials[_projectId].artistAddress ||
357
+ adminACLAllowed(msg.sender, address(this), _selector))
358
+ ) {
359
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminACL);
360
+ }
324
361
  }
325
362
 
326
363
  /**
@@ -333,71 +370,102 @@ contract GenArt721CoreV3_Engine is
333
370
  uint256 _projectId,
334
371
  bytes4 _selector
335
372
  ) internal {
336
- require(
337
- adminACLAllowed(msg.sender, address(this), _selector) ||
338
- (owner() == address(0) &&
339
- msg.sender ==
340
- projectIdToFinancials[_projectId].artistAddress),
341
- "Only Admin ACL allowed, or artist if owner has renounced"
342
- );
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);
343
387
  }
344
388
 
345
389
  /**
346
- * @notice Initializes contract.
347
- * @param _tokenName Name of token.
348
- * @param _tokenSymbol Token symbol.
349
- * @param _randomizerContract Randomizer contract.
350
- * @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
351
399
  * set as contract owner.
352
- * @param _startingProjectId The initial next project ID.
353
- * @param _autoApproveArtistSplitProposals Whether or not to always
354
- * auto-approve proposed artist split updates.
355
- * @dev _startingProjectId should be set to a value much, much less than
356
- * max(uint248), but an explicit input type of `uint248` is used as it is
357
- * safer to cast up to `uint256` than it is to cast down for the purposes
358
- * of setting `_nextProjectId`.
359
- */
360
- constructor(
361
- string memory _tokenName,
362
- string memory _tokenSymbol,
363
- address _renderProviderAddress,
364
- address _platformProviderAddress,
365
- address _randomizerContract,
366
- address _adminACLContract,
367
- uint248 _startingProjectId,
368
- bool _autoApproveArtistSplitProposals
369
- ) ERC721_PackedHashSeed(_tokenName, _tokenSymbol) {
370
- _onlyNonZeroAddress(_renderProviderAddress);
371
- _onlyNonZeroAddress(_platformProviderAddress);
372
- _onlyNonZeroAddress(_randomizerContract);
373
- _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);
374
437
  // setup immutable `autoApproveArtistSplitProposals` config
375
- 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;
376
445
  // record contracts starting project ID
377
446
  // casting-up is safe
378
- startingProjectId = uint256(_startingProjectId);
447
+ startingProjectId = uint256(engineConfiguration.startingProjectId);
448
+ // @dev nullPlatformProvider must be set before calling _updateProviderSalesAddresses
379
449
  _updateProviderSalesAddresses(
380
- _renderProviderAddress,
381
- _renderProviderAddress,
382
- _platformProviderAddress,
383
- _platformProviderAddress
450
+ engineConfiguration.renderProviderAddress,
451
+ engineConfiguration.renderProviderAddress,
452
+ engineConfiguration.platformProviderAddress,
453
+ engineConfiguration.platformProviderAddress
384
454
  );
385
- _updateRandomizerAddress(_randomizerContract);
455
+ _updateRandomizerAddress(engineConfiguration.randomizerContract);
386
456
  // set AdminACL management contract as owner
387
- _transferOwnership(_adminACLContract);
457
+ _transferOwnership(adminACLContract_);
388
458
  // initialize default base URI
389
459
  _updateDefaultBaseURI(
390
- string.concat(
391
- "https://token.artblocks.io/",
392
- address(this).toHexString(),
393
- "/"
394
- )
460
+ string.concat(defaultBaseURIHost, address(this).toHexString(), "/")
395
461
  );
396
462
  // initialize next project ID
397
- _nextProjectId = _startingProjectId;
398
- emit PlatformUpdated(FIELD_NEXT_PROJECT_ID);
399
- // @dev follow-on action: This contract does not self-register. A core
400
- // registry owner must register contract in a subsequent call.
463
+ _nextProjectId = engineConfiguration.startingProjectId;
464
+ emit PlatformUpdated(
465
+ bytes32(uint256(PlatformUpdatedFields.FIELD_NEXT_PROJECT_ID))
466
+ );
467
+ // @dev This contract is registered on the core registry in a
468
+ // subsequent call by the factory.
401
469
  }
402
470
 
403
471
  /**
@@ -417,7 +485,9 @@ contract GenArt721CoreV3_Engine is
417
485
  address _by
418
486
  ) external returns (uint256 _tokenId) {
419
487
  // CHECKS
420
- require(msg.sender == minterContract, "Must mint from minter contract");
488
+ if (msg.sender != minterContract) {
489
+ revert GenArt721Error(ErrorCodes.OnlyMinterContract);
490
+ }
421
491
  Project storage project = projects[_projectId];
422
492
  // load invocations into memory
423
493
  uint24 invocationsBefore = project.invocations;
@@ -428,21 +498,21 @@ contract GenArt721CoreV3_Engine is
428
498
  invocationsAfter = invocationsBefore + 1;
429
499
  }
430
500
  uint24 maxInvocations = project.maxInvocations;
431
-
432
- require(
433
- invocationsBefore < maxInvocations,
434
- "Must not exceed max invocations"
435
- );
436
- require(
437
- project.active ||
438
- _by == projectIdToFinancials[_projectId].artistAddress,
439
- "Project must exist and be active"
440
- );
441
- require(
442
- !project.paused ||
443
- _by == projectIdToFinancials[_projectId].artistAddress,
444
- "Purchases are paused."
445
- );
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
+ }
446
516
 
447
517
  // EFFECTS
448
518
  // increment project's invocations
@@ -494,15 +564,15 @@ contract GenArt721CoreV3_Engine is
494
564
  OwnerAndHashSeed storage ownerAndHashSeed = _ownersAndHashSeeds[
495
565
  _tokenId
496
566
  ];
497
- require(
498
- msg.sender == address(randomizerContract),
499
- "Only randomizer may set"
500
- );
501
- require(
502
- ownerAndHashSeed.hashSeed == bytes12(0),
503
- "Token hash already set"
504
- );
505
- 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
+ }
506
576
  ownerAndHashSeed.hashSeed = bytes12(_hashSeed);
507
577
  }
508
578
 
@@ -533,6 +603,18 @@ contract GenArt721CoreV3_Engine is
533
603
  Ownable.renounceOwnership();
534
604
  }
535
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
+
536
618
  /**
537
619
  * @notice Updates reference to Art Blocks Dependency Registry contract.
538
620
  * @param _artblocksDependencyRegistryAddress Address of new Dependency
@@ -544,43 +626,74 @@ contract GenArt721CoreV3_Engine is
544
626
  _onlyAdminACL(this.updateArtblocksDependencyRegistryAddress.selector);
545
627
  _onlyNonZeroAddress(_artblocksDependencyRegistryAddress);
546
628
  artblocksDependencyRegistryAddress = _artblocksDependencyRegistryAddress;
547
- 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
+ );
548
657
  }
549
658
 
550
659
  /**
551
660
  * @notice Updates sales addresses for the platform and render providers to
552
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.
553
665
  * @param _renderProviderPrimarySalesAddress Address of new primary sales
554
666
  * payment address.
555
- * @param _renderProviderSecondarySalesAddress Address of new secondary sales
667
+ * @param _defaultRenderProviderSecondarySalesAddress Default address of new secondary sales
556
668
  * payment address.
557
669
  * @param _platformProviderPrimarySalesAddress Address of new primary sales
558
670
  * payment address.
559
- * @param _platformProviderSecondarySalesAddress Address of new secondary sales
671
+ * @param _defaultPlatformProviderSecondarySalesAddress Default address of new secondary sales
560
672
  * payment address.
561
673
  */
562
674
  function updateProviderSalesAddresses(
563
675
  address payable _renderProviderPrimarySalesAddress,
564
- address payable _renderProviderSecondarySalesAddress,
676
+ address payable _defaultRenderProviderSecondarySalesAddress,
565
677
  address payable _platformProviderPrimarySalesAddress,
566
- address payable _platformProviderSecondarySalesAddress
678
+ address payable _defaultPlatformProviderSecondarySalesAddress
567
679
  ) external {
568
680
  _onlyAdminACL(this.updateProviderSalesAddresses.selector);
569
681
  _onlyNonZeroAddress(_renderProviderPrimarySalesAddress);
570
- _onlyNonZeroAddress(_renderProviderSecondarySalesAddress);
571
- _onlyNonZeroAddress(_platformProviderPrimarySalesAddress);
572
- _onlyNonZeroAddress(_platformProviderSecondarySalesAddress);
682
+ _onlyNonZeroAddress(_defaultRenderProviderSecondarySalesAddress);
683
+ // @dev checks on platform provider addresses performed in _updateProviderSalesAddresses
573
684
  _updateProviderSalesAddresses(
574
685
  _renderProviderPrimarySalesAddress,
575
- _renderProviderSecondarySalesAddress,
686
+ _defaultRenderProviderSecondarySalesAddress,
576
687
  _platformProviderPrimarySalesAddress,
577
- _platformProviderSecondarySalesAddress
688
+ _defaultPlatformProviderSecondarySalesAddress
578
689
  );
579
690
  }
580
691
 
581
692
  /**
582
693
  * @notice Updates the render and platform provider primary sales revenue percentage to
583
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.
584
697
  * @param renderProviderPrimarySalesPercentage_ New primary sales revenue % for the render provider
585
698
  * @param platformProviderPrimarySalesPercentage_ New primary sales revenue % for the platform provider
586
699
  * percentage.
@@ -590,13 +703,20 @@ contract GenArt721CoreV3_Engine is
590
703
  uint256 platformProviderPrimarySalesPercentage_
591
704
  ) external {
592
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
+ }
593
712
 
594
713
  // Validate that the sum of the proposed %s, does not exceed 100%.
595
- require(
714
+ if (
596
715
  (renderProviderPrimarySalesPercentage_ +
597
- platformProviderPrimarySalesPercentage_) <= ONE_HUNDRED,
598
- "Max sum of ONE_HUNDRED %"
599
- );
716
+ platformProviderPrimarySalesPercentage_) > ONE_HUNDRED
717
+ ) {
718
+ revert GenArt721Error(ErrorCodes.OverMaxSumOfPercentages);
719
+ }
600
720
  // Casting to `uint8` here is safe due check above, which does not allow
601
721
  // overflow as of solidity version ^0.8.0.
602
722
  _renderProviderPrimarySalesPercentage = uint8(
@@ -605,15 +725,27 @@ contract GenArt721CoreV3_Engine is
605
725
  _platformProviderPrimarySalesPercentage = uint8(
606
726
  platformProviderPrimarySalesPercentage_
607
727
  );
608
- 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
+ );
609
736
  }
610
737
 
611
738
  /**
612
- * @notice Updates render and platform provider secondary sales royalty Basis Points to
613
- * the provided inputs.
614
- * @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
615
747
  * points.
616
- * @param _platformProviderSecondarySalesBPS New secondary sales royalty Basis
748
+ * @param _defaultPlatformProviderSecondarySalesBPS New default secondary sales royalty Basis
617
749
  * points.
618
750
  * @dev Due to secondary royalties being ultimately enforced via social
619
751
  * consensus, no hard upper limit is imposed on the BPS value, other than
@@ -621,21 +753,35 @@ contract GenArt721CoreV3_Engine is
621
753
  * changing this value is expected to either never occur, or be a rare
622
754
  * occurrence.
623
755
  */
624
- function updateProviderSecondarySalesBPS(
625
- uint256 _renderProviderSecondarySalesBPS,
626
- uint256 _platformProviderSecondarySalesBPS
756
+ function updateProviderDefaultSecondarySalesBPS(
757
+ uint256 _defaultRenderProviderSecondarySalesBPS,
758
+ uint256 _defaultPlatformProviderSecondarySalesBPS
627
759
  ) external {
628
- _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
+ }
629
768
  // Validate that the sum of the proposed provider BPS, does not exceed 10_000 BPS.
630
- require(
631
- (_renderProviderSecondarySalesBPS +
632
- _platformProviderSecondarySalesBPS) <=
633
- MAX_PROVIDER_SECONDARY_SALES_BPS,
634
- "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
+ )
635
784
  );
636
- renderProviderSecondarySalesBPS = _renderProviderSecondarySalesBPS;
637
- platformProviderSecondarySalesBPS = _platformProviderSecondarySalesBPS;
638
- emit PlatformUpdated(FIELD_PROVIDER_SECONDARY_SALES_BPS);
639
785
  }
640
786
 
641
787
  /**
@@ -645,8 +791,7 @@ contract GenArt721CoreV3_Engine is
645
791
  function updateMinterContract(address _address) external {
646
792
  _onlyAdminACL(this.updateMinterContract.selector);
647
793
  _onlyNonZeroAddress(_address);
648
- minterContract = _address;
649
- emit MinterUpdated(_address);
794
+ _updateMinterContract(_address);
650
795
  }
651
796
 
652
797
  /**
@@ -659,15 +804,35 @@ contract GenArt721CoreV3_Engine is
659
804
  _updateRandomizerAddress(_randomizerAddress);
660
805
  }
661
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
+
662
817
  /**
663
818
  * @notice Toggles project `_projectId` as active/inactive.
664
819
  * @param _projectId Project ID to be toggled.
665
820
  */
666
821
  function toggleProjectIsActive(uint256 _projectId) external {
667
- _onlyAdminACL(this.toggleProjectIsActive.selector);
822
+ if (allowArtistProjectActivation) {
823
+ _onlyArtistOrAdminACL(
824
+ _projectId,
825
+ this.toggleProjectIsActive.selector
826
+ );
827
+ } else {
828
+ _onlyAdminACL(this.toggleProjectIsActive.selector);
829
+ }
668
830
  _onlyValidProjectId(_projectId);
669
831
  projects[_projectId].active = !projects[_projectId].active;
670
- emit ProjectUpdated(_projectId, FIELD_PROJECT_ACTIVE);
832
+ emit ProjectUpdated(
833
+ _projectId,
834
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_ACTIVE))
835
+ );
671
836
  }
672
837
 
673
838
  /**
@@ -712,25 +877,28 @@ contract GenArt721CoreV3_Engine is
712
877
  _onlyValidProjectId(_projectId);
713
878
  _onlyArtist(_projectId);
714
879
  _onlyNonZeroAddress(_artistAddress);
715
- ProjectFinance storage projectFinance = projectIdToFinancials[
880
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
716
881
  _projectId
717
882
  ];
718
883
  // checks
719
- require(
720
- _additionalPayeePrimarySalesPercentage <= ONE_HUNDRED &&
721
- _additionalPayeeSecondarySalesPercentage <= ONE_HUNDRED,
722
- "Max of 100%"
723
- );
724
- require(
725
- _additionalPayeePrimarySalesPercentage == 0 ||
726
- _additionalPayeePrimarySales != address(0),
727
- "Primary payee is zero address"
728
- );
729
- require(
730
- _additionalPayeeSecondarySalesPercentage == 0 ||
731
- _additionalPayeeSecondarySales != address(0),
732
- "Secondary payee is zero address"
733
- );
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
+ }
734
902
  // effects
735
903
  // emit event for off-chain indexing
736
904
  // note: always emit a proposal event, even in the pathway of
@@ -766,6 +934,7 @@ contract GenArt721CoreV3_Engine is
766
934
  if (automaticAccept) {
767
935
  // clear any previously proposed values
768
936
  proposedArtistAddressesAndSplitsHash[_projectId] = bytes32(0);
937
+
769
938
  // update storage
770
939
  // artist address can change during automatic accept if
771
940
  // autoApproveArtistSplitProposals is true
@@ -782,6 +951,11 @@ contract GenArt721CoreV3_Engine is
782
951
  projectFinance.additionalPayeeSecondarySalesPercentage = uint8(
783
952
  _additionalPayeeSecondarySalesPercentage
784
953
  );
954
+
955
+ // assign project's splitter
956
+ // @dev only call after all previous storage updates
957
+ _assignSplitter(_projectId);
958
+
785
959
  // emit event for off-chain indexing
786
960
  emit AcceptedArtistAddressesAndSplits(_projectId);
787
961
  } else {
@@ -837,21 +1011,22 @@ contract GenArt721CoreV3_Engine is
837
1011
  );
838
1012
  _onlyNonZeroAddress(_artistAddress);
839
1013
  // checks
840
- require(
841
- proposedArtistAddressesAndSplitsHash[_projectId] ==
842
- keccak256(
843
- abi.encode(
844
- _artistAddress,
845
- _additionalPayeePrimarySales,
846
- _additionalPayeePrimarySalesPercentage,
847
- _additionalPayeeSecondarySales,
848
- _additionalPayeeSecondarySalesPercentage
849
- )
850
- ),
851
- "Must match artist proposal"
852
- );
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
+ }
853
1028
  // effects
854
- ProjectFinance storage projectFinance = projectIdToFinancials[
1029
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
855
1030
  _projectId
856
1031
  ];
857
1032
  projectFinance.artistAddress = _artistAddress;
@@ -867,6 +1042,11 @@ contract GenArt721CoreV3_Engine is
867
1042
  );
868
1043
  // clear proposed values
869
1044
  proposedArtistAddressesAndSplitsHash[_projectId] = bytes32(0);
1045
+
1046
+ // assign project's splitter
1047
+ // @dev only call after all previous storage updates
1048
+ _assignSplitter(_projectId);
1049
+
870
1050
  // emit event for off-chain indexing
871
1051
  emit AcceptedArtistAddressesAndSplits(_projectId);
872
1052
  }
@@ -888,8 +1068,17 @@ contract GenArt721CoreV3_Engine is
888
1068
  this.updateProjectArtistAddress.selector
889
1069
  );
890
1070
  _onlyNonZeroAddress(_artistAddress);
891
- projectIdToFinancials[_projectId].artistAddress = _artistAddress;
892
- 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
+ );
893
1082
  }
894
1083
 
895
1084
  /**
@@ -899,7 +1088,10 @@ contract GenArt721CoreV3_Engine is
899
1088
  function toggleProjectIsPaused(uint256 _projectId) external {
900
1089
  _onlyArtist(_projectId);
901
1090
  projects[_projectId].paused = !projects[_projectId].paused;
902
- emit ProjectUpdated(_projectId, FIELD_PROJECT_PAUSED);
1091
+ emit ProjectUpdated(
1092
+ _projectId,
1093
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_PAUSED))
1094
+ );
903
1095
  }
904
1096
 
905
1097
  /**
@@ -915,16 +1107,44 @@ contract GenArt721CoreV3_Engine is
915
1107
  _onlyAdminACL(this.addProject.selector);
916
1108
  _onlyNonEmptyString(_projectName);
917
1109
  _onlyNonZeroAddress(_artistAddress);
918
- require(!newProjectsForbidden, "New projects forbidden");
1110
+ if (newProjectsForbidden) {
1111
+ revert GenArt721Error(ErrorCodes.NewProjectsForbidden);
1112
+ }
919
1113
  uint256 projectId = _nextProjectId;
920
- projectIdToFinancials[projectId].artistAddress = _artistAddress;
1114
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
1115
+ projectId
1116
+ ];
1117
+ projectFinance.artistAddress = _artistAddress;
921
1118
  projects[projectId].name = _projectName;
922
1119
  projects[projectId].paused = true;
923
1120
  projects[projectId].maxInvocations = ONE_MILLION_UINT24;
924
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
+ );
925
1136
 
926
1137
  _nextProjectId = uint248(projectId) + 1;
927
- 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);
928
1148
  }
929
1149
 
930
1150
  /**
@@ -932,7 +1152,9 @@ contract GenArt721CoreV3_Engine is
932
1152
  */
933
1153
  function forbidNewProjects() external {
934
1154
  _onlyAdminACL(this.forbidNewProjects.selector);
935
- require(!newProjectsForbidden, "Already forbidden");
1155
+ if (newProjectsForbidden) {
1156
+ revert GenArt721Error(ErrorCodes.NewProjectsAlreadyForbidden);
1157
+ }
936
1158
  _forbidNewProjects();
937
1159
  }
938
1160
 
@@ -949,12 +1171,17 @@ contract GenArt721CoreV3_Engine is
949
1171
  _onlyArtistOrAdminACL(_projectId, this.updateProjectName.selector);
950
1172
  _onlyNonEmptyString(_projectName);
951
1173
  projects[_projectId].name = _projectName;
952
- emit ProjectUpdated(_projectId, FIELD_PROJECT_NAME);
1174
+ emit ProjectUpdated(
1175
+ _projectId,
1176
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_NAME))
1177
+ );
953
1178
  }
954
1179
 
955
1180
  /**
956
1181
  * @notice Updates artist name for project `_projectId` to be
957
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.
958
1185
  * @param _projectId Project ID.
959
1186
  * @param _projectArtistName New artist name.
960
1187
  */
@@ -962,42 +1189,111 @@ contract GenArt721CoreV3_Engine is
962
1189
  uint256 _projectId,
963
1190
  string memory _projectArtistName
964
1191
  ) external {
965
- _onlyUnlocked(_projectId);
966
- _onlyArtistOrAdminACL(
967
- _projectId,
968
- this.updateProjectArtistName.selector
969
- );
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
+ }
970
1211
  _onlyNonEmptyString(_projectArtistName);
971
1212
  projects[_projectId].artist = _projectArtistName;
972
- emit ProjectUpdated(_projectId, FIELD_PROJECT_ARTIST_NAME);
1213
+ emit ProjectUpdated(
1214
+ _projectId,
1215
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_ARTIST_NAME))
1216
+ );
973
1217
  }
974
1218
 
975
1219
  /**
976
1220
  * @notice Updates artist secondary market royalties for project
977
- * `_projectId` to be `_secondMarketRoyalty` percent.
1221
+ * `_projectId` to be `_secondaryMarketRoyalty` percent.
1222
+ * This deploys a new splitter contract if needed.
978
1223
  * This DOES NOT include the secondary market royalty percentages collected
979
1224
  * by the issuing platform; it is only the total percentage of royalties
980
1225
  * that will be split to artist and additionalSecondaryPayee.
981
1226
  * @param _projectId Project ID.
982
- * @param _secondMarketRoyalty Percent of secondary sales revenue that will
1227
+ * @param _secondaryMarketRoyalty Percent of secondary sales revenue that will
983
1228
  * be split to artist and additionalSecondaryPayee. This must be less than
984
1229
  * or equal to ARTIST_MAX_SECONDARY_ROYALTY_PERCENTAGE percent.
985
1230
  */
986
1231
  function updateProjectSecondaryMarketRoyaltyPercentage(
987
1232
  uint256 _projectId,
988
- uint256 _secondMarketRoyalty
1233
+ uint256 _secondaryMarketRoyalty
989
1234
  ) external {
990
1235
  _onlyArtist(_projectId);
991
- require(
992
- _secondMarketRoyalty <= ARTIST_MAX_SECONDARY_ROYALTY_PERCENTAGE,
993
- "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
+ )
994
1254
  );
995
- projectIdToFinancials[_projectId]
996
- .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
+
997
1284
  emit ProjectUpdated(
998
1285
  _projectId,
999
- FIELD_PROJECT_SECONDARY_MARKET_ROYALTY_PERCENTAGE
1286
+ bytes32(
1287
+ uint256(
1288
+ ProjectUpdatedFields
1289
+ .FIELD_PROJECT_PROVIDER_SECONDARY_FINANCIALS
1290
+ )
1291
+ )
1000
1292
  );
1293
+
1294
+ // assign project's splitter
1295
+ // @dev only call after all previous storage updates
1296
+ _assignSplitter(_projectId);
1001
1297
  }
1002
1298
 
1003
1299
  /**
@@ -1018,22 +1314,33 @@ contract GenArt721CoreV3_Engine is
1018
1314
  string memory _projectDescription
1019
1315
  ) external {
1020
1316
  // checks
1021
- require(
1022
- _projectUnlocked(_projectId)
1023
- ? msg.sender == projectIdToFinancials[_projectId].artistAddress
1024
- : 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(
1025
1327
  msg.sender,
1026
1328
  address(this),
1027
1329
  this.updateProjectDescription.selector
1028
- ),
1029
- "Only artist when unlocked, owner when locked"
1030
- );
1330
+ )
1331
+ ) {
1332
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1333
+ }
1334
+ }
1031
1335
  // effects
1032
1336
  // store description in contract bytecode, replacing reference address from
1033
1337
  // the old storage description with the newly created one
1034
1338
  projects[_projectId].descriptionAddress = _projectDescription
1035
1339
  .writeToBytecode();
1036
- emit ProjectUpdated(_projectId, FIELD_PROJECT_DESCRIPTION);
1340
+ emit ProjectUpdated(
1341
+ _projectId,
1342
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_DESCRIPTION))
1343
+ );
1037
1344
  }
1038
1345
 
1039
1346
  /**
@@ -1048,7 +1355,10 @@ contract GenArt721CoreV3_Engine is
1048
1355
  ) external {
1049
1356
  _onlyArtist(_projectId);
1050
1357
  projects[_projectId].website = _projectWebsite;
1051
- emit ProjectUpdated(_projectId, FIELD_PROJECT_WEBSITE);
1358
+ emit ProjectUpdated(
1359
+ _projectId,
1360
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_WEBSITE))
1361
+ );
1052
1362
  }
1053
1363
 
1054
1364
  /**
@@ -1064,7 +1374,10 @@ contract GenArt721CoreV3_Engine is
1064
1374
  _onlyArtistOrAdminACL(_projectId, this.updateProjectLicense.selector);
1065
1375
  _onlyNonEmptyString(_projectLicense);
1066
1376
  projects[_projectId].license = _projectLicense;
1067
- emit ProjectUpdated(_projectId, FIELD_PROJECT_LICENSE);
1377
+ emit ProjectUpdated(
1378
+ _projectId,
1379
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_LICENSE))
1380
+ );
1068
1381
  }
1069
1382
 
1070
1383
  /**
@@ -1084,14 +1397,18 @@ contract GenArt721CoreV3_Engine is
1084
1397
  // CHECKS
1085
1398
  Project storage project = projects[_projectId];
1086
1399
  uint256 _invocations = project.invocations;
1087
- require(
1088
- (_maxInvocations < project.maxInvocations),
1089
- "Only maxInvocations decrease"
1090
- );
1091
- 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
+ }
1092
1406
  // EFFECTS
1093
1407
  project.maxInvocations = _maxInvocations;
1094
- emit ProjectUpdated(_projectId, FIELD_PROJECT_MAX_INVOCATIONS);
1408
+ emit ProjectUpdated(
1409
+ _projectId,
1410
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_MAX_INVOCATIONS))
1411
+ );
1095
1412
 
1096
1413
  // register completed timestamp if action completed the project
1097
1414
  if (_maxInvocations == _invocations) {
@@ -1117,7 +1434,41 @@ contract GenArt721CoreV3_Engine is
1117
1434
  project.scriptBytecodeAddresses[project.scriptCount] = _script
1118
1435
  .writeToBytecode();
1119
1436
  project.scriptCount = project.scriptCount + 1;
1120
- 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
+ );
1121
1472
  }
1122
1473
 
1123
1474
  /**
@@ -1136,11 +1487,52 @@ contract GenArt721CoreV3_Engine is
1136
1487
  _onlyArtistOrAdminACL(_projectId, this.updateProjectScript.selector);
1137
1488
  _onlyNonEmptyString(_script);
1138
1489
  Project storage project = projects[_projectId];
1139
- require(_scriptId < project.scriptCount, "scriptId out of range");
1490
+ if (_scriptId >= project.scriptCount) {
1491
+ revert GenArt721Error(ErrorCodes.ScriptIdOutOfRange);
1492
+ }
1140
1493
  // store script in contract bytecode, replacing reference address from
1141
1494
  // the old storage contract with the newly created one
1142
1495
  project.scriptBytecodeAddresses[_scriptId] = _script.writeToBytecode();
1143
- 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
+ );
1144
1536
  }
1145
1537
 
1146
1538
  /**
@@ -1154,13 +1546,18 @@ contract GenArt721CoreV3_Engine is
1154
1546
  this.removeProjectLastScript.selector
1155
1547
  );
1156
1548
  Project storage project = projects[_projectId];
1157
- require(project.scriptCount > 0, "No scripts to remove");
1549
+ if (project.scriptCount == 0) {
1550
+ revert GenArt721Error(ErrorCodes.NoScriptsToRemove);
1551
+ }
1158
1552
  // delete reference to old storage contract address
1159
1553
  delete project.scriptBytecodeAddresses[project.scriptCount - 1];
1160
1554
  unchecked {
1161
1555
  project.scriptCount = project.scriptCount - 1;
1162
1556
  }
1163
- emit ProjectUpdated(_projectId, FIELD_PROJECT_SCRIPT);
1557
+ emit ProjectUpdated(
1558
+ _projectId,
1559
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT))
1560
+ );
1164
1561
  }
1165
1562
 
1166
1563
  /**
@@ -1180,15 +1577,19 @@ contract GenArt721CoreV3_Engine is
1180
1577
  );
1181
1578
  Project storage project = projects[_projectId];
1182
1579
  // require exactly one @ symbol in _scriptTypeAndVersion
1183
- require(
1184
- _scriptTypeAndVersion.containsExactCharacterQty(
1580
+ if (
1581
+ !_scriptTypeAndVersion.containsExactCharacterQty(
1185
1582
  AT_CHARACTER_CODE,
1186
1583
  uint8(1)
1187
- ),
1188
- "must contain exactly one @"
1189
- );
1584
+ )
1585
+ ) {
1586
+ revert GenArt721Error(ErrorCodes.ScriptTypeAndVersionFormat);
1587
+ }
1190
1588
  project.scriptTypeAndVersion = _scriptTypeAndVersion;
1191
- emit ProjectUpdated(_projectId, FIELD_PROJECT_SCRIPT_TYPE);
1589
+ emit ProjectUpdated(
1590
+ _projectId,
1591
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT_TYPE))
1592
+ );
1192
1593
  }
1193
1594
 
1194
1595
  /**
@@ -1211,7 +1612,9 @@ contract GenArt721CoreV3_Engine is
1211
1612
  // Perform more detailed input validation for aspect ratio.
1212
1613
  bytes memory aspectRatioBytes = bytes(_aspectRatio);
1213
1614
  uint256 bytesLength = aspectRatioBytes.length;
1214
- require(bytesLength <= 11, "Aspect ratio format too long");
1615
+ if (bytesLength > 11) {
1616
+ revert GenArt721Error(ErrorCodes.AspectRatioTooLong);
1617
+ }
1215
1618
  bool hasSeenDecimalSeparator = false;
1216
1619
  bool hasSeenNumber = false;
1217
1620
  for (uint256 i; i < bytesLength; i++) {
@@ -1231,12 +1634,17 @@ contract GenArt721CoreV3_Engine is
1231
1634
  continue;
1232
1635
  }
1233
1636
  }
1234
- revert("Improperly formatted aspect ratio");
1637
+ revert GenArt721Error(ErrorCodes.AspectRatioImproperFormat);
1638
+ }
1639
+ if (!hasSeenNumber) {
1640
+ revert GenArt721Error(ErrorCodes.AspectRatioNoNumbers);
1235
1641
  }
1236
- require(hasSeenNumber, "Aspect ratio has no numbers");
1237
1642
 
1238
1643
  projects[_projectId].aspectRatio = _aspectRatio;
1239
- emit ProjectUpdated(_projectId, FIELD_PROJECT_ASPECT_RATIO);
1644
+ emit ProjectUpdated(
1645
+ _projectId,
1646
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_ASPECT_RATIO))
1647
+ );
1240
1648
  }
1241
1649
 
1242
1650
  /**
@@ -1254,7 +1662,10 @@ contract GenArt721CoreV3_Engine is
1254
1662
  _onlyArtist(_projectId);
1255
1663
  _onlyNonEmptyString(_newBaseURI);
1256
1664
  projects[_projectId].projectBaseURI = _newBaseURI;
1257
- emit ProjectUpdated(_projectId, FIELD_PROJECT_BASE_URI);
1665
+ emit ProjectUpdated(
1666
+ _projectId,
1667
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_BASE_URI))
1668
+ );
1258
1669
  }
1259
1670
 
1260
1671
  /**
@@ -1343,7 +1754,7 @@ contract GenArt721CoreV3_Engine is
1343
1754
  function projectIdToArtistAddress(
1344
1755
  uint256 _projectId
1345
1756
  ) external view returns (address payable) {
1346
- return projectIdToFinancials[_projectId].artistAddress;
1757
+ return _projectIdToFinancials[_projectId].artistAddress;
1347
1758
  }
1348
1759
 
1349
1760
  /**
@@ -1358,60 +1769,19 @@ contract GenArt721CoreV3_Engine is
1358
1769
  uint256 _projectId
1359
1770
  ) external view returns (uint256) {
1360
1771
  return
1361
- projectIdToFinancials[_projectId].secondaryMarketRoyaltyPercentage;
1362
- }
1363
-
1364
- /**
1365
- * @notice View function returning Artist's additional payee address for
1366
- * primary sales, for project `_projectId`.
1367
- * @param _projectId Project ID to be queried.
1368
- * @return address Artist's additional payee address for primary sales.
1369
- */
1370
- function projectIdToAdditionalPayeePrimarySales(
1371
- uint256 _projectId
1372
- ) external view returns (address payable) {
1373
- return projectIdToFinancials[_projectId].additionalPayeePrimarySales;
1374
- }
1375
-
1376
- /**
1377
- * @notice View function returning Artist's additional payee primary sales
1378
- * percentage, for project `_projectId`.
1379
- * @param _projectId Project ID to be queried.
1380
- * @return uint256 Artist's additional payee primary sales percentage.
1381
- */
1382
- function projectIdToAdditionalPayeePrimarySalesPercentage(
1383
- uint256 _projectId
1384
- ) external view returns (uint256) {
1385
- return
1386
- projectIdToFinancials[_projectId]
1387
- .additionalPayeePrimarySalesPercentage;
1772
+ _projectIdToFinancials[_projectId].secondaryMarketRoyaltyPercentage;
1388
1773
  }
1389
1774
 
1390
1775
  /**
1391
- * @notice View function returning Artist's additional payee address for
1392
- * secondary sales, for project `_projectId`.
1393
- * @param _projectId Project ID to be queried.
1394
- * @return address payable Artist's additional payee address for secondary
1395
- * sales.
1396
- */
1397
- function projectIdToAdditionalPayeeSecondarySales(
1398
- uint256 _projectId
1399
- ) external view returns (address payable) {
1400
- return projectIdToFinancials[_projectId].additionalPayeeSecondarySales;
1401
- }
1402
-
1403
- /**
1404
- * @notice View function returning Artist's additional payee secondary
1405
- * sales percentage, for project `_projectId`.
1776
+ * @notice View function returning project financial details for project
1777
+ * `_projectId`.
1406
1778
  * @param _projectId Project ID to be queried.
1407
- * @return uint256 Artist's additional payee secondary sales percentage.
1779
+ * @return ProjectFinance Project financial details.
1408
1780
  */
1409
- function projectIdToAdditionalPayeeSecondarySalesPercentage(
1781
+ function projectIdToFinancials(
1410
1782
  uint256 _projectId
1411
- ) external view returns (uint256) {
1412
- return
1413
- projectIdToFinancials[_projectId]
1414
- .additionalPayeeSecondarySalesPercentage;
1783
+ ) external view returns (ProjectFinance memory) {
1784
+ return _projectIdToFinancials[_projectId];
1415
1785
  }
1416
1786
 
1417
1787
  /**
@@ -1485,54 +1855,6 @@ contract GenArt721CoreV3_Engine is
1485
1855
  locked = !_projectUnlocked(_projectId);
1486
1856
  }
1487
1857
 
1488
- /**
1489
- * @notice Returns artist payment information for project `_projectId`.
1490
- * @param _projectId Project to be queried
1491
- * @return artistAddress Project Artist's address
1492
- * @return additionalPayeePrimarySales Additional payee address for primary
1493
- * sales
1494
- * @return additionalPayeePrimarySalesPercentage Percentage of artist revenue
1495
- * to be sent to the additional payee address for primary sales
1496
- * @return additionalPayeeSecondarySales Additional payee address for secondary
1497
- * sales royalties
1498
- * @return additionalPayeeSecondarySalesPercentage Percentage of artist revenue
1499
- * to be sent to the additional payee address for secondary sales royalties
1500
- * @return secondaryMarketRoyaltyPercentage Royalty percentage to be sent to
1501
- * combination of artist and additional payee. This does not include the
1502
- * platform's percentage of secondary sales royalties, which is defined as
1503
- * the sum of `renderProviderSecondarySalesBPS`
1504
- * and `platformProviderSecondarySalesBPS`.
1505
- */
1506
- function projectArtistPaymentInfo(
1507
- uint256 _projectId
1508
- )
1509
- external
1510
- view
1511
- returns (
1512
- address artistAddress,
1513
- address additionalPayeePrimarySales,
1514
- uint256 additionalPayeePrimarySalesPercentage,
1515
- address additionalPayeeSecondarySales,
1516
- uint256 additionalPayeeSecondarySalesPercentage,
1517
- uint256 secondaryMarketRoyaltyPercentage
1518
- )
1519
- {
1520
- ProjectFinance storage projectFinance = projectIdToFinancials[
1521
- _projectId
1522
- ];
1523
- artistAddress = projectFinance.artistAddress;
1524
- additionalPayeePrimarySales = projectFinance
1525
- .additionalPayeePrimarySales;
1526
- additionalPayeePrimarySalesPercentage = projectFinance
1527
- .additionalPayeePrimarySalesPercentage;
1528
- additionalPayeeSecondarySales = projectFinance
1529
- .additionalPayeeSecondarySales;
1530
- additionalPayeeSecondarySalesPercentage = projectFinance
1531
- .additionalPayeeSecondarySalesPercentage;
1532
- secondaryMarketRoyaltyPercentage = projectFinance
1533
- .secondaryMarketRoyaltyPercentage;
1534
- }
1535
-
1536
1858
  /**
1537
1859
  * @notice Returns script information for project `_projectId`.
1538
1860
  * @param _projectId Project to be queried.
@@ -1571,6 +1893,18 @@ contract GenArt721CoreV3_Engine is
1571
1893
  return projects[_projectId].scriptBytecodeAddresses[_index];
1572
1894
  }
1573
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
+
1574
1908
  /**
1575
1909
  * @notice Returns script for project `_projectId` at script index `_index`.
1576
1910
  * @param _projectId Project to be queried.
@@ -1630,82 +1964,50 @@ contract GenArt721CoreV3_Engine is
1630
1964
  function getHistoricalRandomizerAt(
1631
1965
  uint256 _index
1632
1966
  ) external view returns (address) {
1633
- require(
1634
- _index < _historicalRandomizerAddresses.length,
1635
- "Index out of bounds"
1636
- );
1967
+ if (_index >= _historicalRandomizerAddresses.length) {
1968
+ revert GenArt721Error(ErrorCodes.IndexOutOfBounds);
1969
+ }
1637
1970
  return _historicalRandomizerAddresses[_index];
1638
1971
  }
1639
1972
 
1640
1973
  /**
1641
- * @notice Gets royalty Basis Points (BPS) for token ID `_tokenId`.
1642
- * This conforms to the IManifold interface designated in the Royalty
1643
- * Registry's RoyaltyEngineV1.sol contract.
1644
- * ref: https://github.com/manifoldxyz/royalty-registry-solidity
1645
- * @param _tokenId Token ID to be queried.
1646
- * @return recipients Array of royalty payment recipients
1647
- * @return bps Array of Basis Points (BPS) allocated to each recipient,
1648
- * 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
1649
1980
  * @dev reverts if invalid _tokenId
1650
- * @dev only returns recipients that have a non-zero BPS allocation
1651
1981
  */
1652
- function getRoyalties(
1653
- uint256 _tokenId
1654
- )
1655
- external
1656
- view
1657
- returns (address payable[] memory recipients, uint256[] memory bps)
1658
- {
1982
+ function royaltyInfo(
1983
+ uint256 _tokenId,
1984
+ uint256 _salePrice
1985
+ ) external view returns (address receiver, uint256 royaltyAmount) {
1659
1986
  _onlyValidTokenId(_tokenId);
1660
- // initialize arrays with maximum potential length
1661
- recipients = new address payable[](4);
1662
- bps = new uint256[](4);
1663
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
1664
1991
  uint256 projectId = tokenIdToProjectId(_tokenId);
1665
- ProjectFinance storage projectFinance = projectIdToFinancials[
1992
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
1666
1993
  projectId
1667
1994
  ];
1668
- // load values into memory
1669
- uint256 royaltyPercentageForArtistAndAdditional = projectFinance
1670
- .secondaryMarketRoyaltyPercentage;
1671
- uint256 additionalPayeePercentage = projectFinance
1672
- .additionalPayeeSecondarySalesPercentage;
1673
- // calculate BPS = percentage * 100
1674
- uint256 artistBPS = (ONE_HUNDRED - additionalPayeePercentage) *
1675
- royaltyPercentageForArtistAndAdditional;
1676
-
1677
- uint256 additionalBPS = additionalPayeePercentage *
1678
- royaltyPercentageForArtistAndAdditional;
1679
- uint256 renderProviderBPS = renderProviderSecondarySalesBPS;
1680
- uint256 platformProviderBPS = platformProviderSecondarySalesBPS;
1681
- // populate arrays
1682
- uint256 payeeCount;
1683
- if (artistBPS > 0) {
1684
- recipients[payeeCount] = projectFinance.artistAddress;
1685
- bps[payeeCount++] = artistBPS;
1686
- }
1687
- if (additionalBPS > 0) {
1688
- recipients[payeeCount] = projectFinance
1689
- .additionalPayeeSecondarySales;
1690
- bps[payeeCount++] = additionalBPS;
1691
- }
1692
- if (renderProviderBPS > 0) {
1693
- recipients[payeeCount] = renderProviderSecondarySalesAddress;
1694
- bps[payeeCount++] = renderProviderBPS;
1695
- }
1696
- if (platformProviderBPS > 0) {
1697
- recipients[payeeCount] = platformProviderSecondarySalesAddress;
1698
- bps[payeeCount++] = platformProviderBPS;
1699
- }
1700
- // trim arrays if necessary
1701
- if (4 > payeeCount) {
1702
- assembly {
1703
- let decrease := sub(4, payeeCount)
1704
- mstore(recipients, sub(mload(recipients), decrease))
1705
- mstore(bps, sub(mload(bps), decrease))
1706
- }
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);
1707
2006
  }
1708
- 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;
1709
2011
  }
1710
2012
 
1711
2013
  /**
@@ -1758,7 +2060,7 @@ contract GenArt721CoreV3_Engine is
1758
2060
  address payable additionalPayeePrimaryAddress_
1759
2061
  )
1760
2062
  {
1761
- ProjectFinance storage projectFinance = projectIdToFinancials[
2063
+ ProjectFinance storage projectFinance = _projectIdToFinancials[
1762
2064
  _projectId
1763
2065
  ];
1764
2066
  // calculate revenues – this is a three-way split between the
@@ -1880,9 +2182,15 @@ contract GenArt721CoreV3_Engine is
1880
2182
  */
1881
2183
  function supportsInterface(
1882
2184
  bytes4 interfaceId
1883
- ) public view virtual override returns (bool) {
2185
+ )
2186
+ public
2187
+ view
2188
+ virtual
2189
+ override(ERC721_PackedHashSeedV1, IERC165)
2190
+ returns (bool)
2191
+ {
1884
2192
  return
1885
- interfaceId == type(IManifold).interfaceId ||
2193
+ interfaceId == _INTERFACE_ID_ERC2981 ||
1886
2194
  super.supportsInterface(interfaceId);
1887
2195
  }
1888
2196
 
@@ -1894,7 +2202,11 @@ contract GenArt721CoreV3_Engine is
1894
2202
  function _forbidNewProjects() internal {
1895
2203
  if (!newProjectsForbidden) {
1896
2204
  newProjectsForbidden = true;
1897
- emit PlatformUpdated(FIELD_NEW_PROJECTS_FORBIDDEN);
2205
+ emit PlatformUpdated(
2206
+ bytes32(
2207
+ uint256(PlatformUpdatedFields.FIELD_NEW_PROJECTS_FORBIDDEN)
2208
+ )
2209
+ );
1898
2210
  }
1899
2211
  }
1900
2212
 
@@ -1914,37 +2226,65 @@ contract GenArt721CoreV3_Engine is
1914
2226
  /**
1915
2227
  * @notice Updates sales addresses for the platform and render providers to
1916
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.
1917
2232
  * @param _renderProviderPrimarySalesAddress Address of new primary sales
1918
2233
  * payment address.
1919
- * @param _renderProviderSecondarySalesAddress Address of new secondary sales
2234
+ * @param _defaultRenderProviderSecondarySalesAddress Address of new secondary sales
1920
2235
  * payment address.
1921
2236
  * @param _platformProviderPrimarySalesAddress Address of new primary sales
1922
2237
  * payment address.
1923
- * @param _platformProviderSecondarySalesAddress Address of new secondary sales
2238
+ * @param _defaultPlatformProviderSecondarySalesAddress Address of new secondary sales
1924
2239
  * payment address.
1925
- * @dev Note that this method does not check that the input address is
1926
- * not `address(0)`, as it is expected that callers of this method should
1927
- * perform input validation where applicable.
1928
2240
  */
1929
2241
  function _updateProviderSalesAddresses(
1930
2242
  address _renderProviderPrimarySalesAddress,
1931
- address _renderProviderSecondarySalesAddress,
2243
+ address _defaultRenderProviderSecondarySalesAddress,
1932
2244
  address _platformProviderPrimarySalesAddress,
1933
- address _platformProviderSecondarySalesAddress
2245
+ address _defaultPlatformProviderSecondarySalesAddress
1934
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
+ }
1935
2259
  platformProviderPrimarySalesAddress = payable(
1936
2260
  _platformProviderPrimarySalesAddress
1937
2261
  );
1938
- platformProviderSecondarySalesAddress = payable(
1939
- _platformProviderSecondarySalesAddress
2262
+ defaultPlatformProviderSecondarySalesAddress = payable(
2263
+ _defaultPlatformProviderSecondarySalesAddress
1940
2264
  );
1941
2265
  renderProviderPrimarySalesAddress = payable(
1942
2266
  _renderProviderPrimarySalesAddress
1943
2267
  );
1944
- renderProviderSecondarySalesAddress = payable(
1945
- _renderProviderSecondarySalesAddress
2268
+ defaultRenderProviderSecondarySalesAddress = payable(
2269
+ _defaultRenderProviderSecondarySalesAddress
2270
+ );
2271
+ emit PlatformUpdated(
2272
+ bytes32(
2273
+ uint256(PlatformUpdatedFields.FIELD_PROVIDER_SALES_ADDRESSES)
2274
+ )
1946
2275
  );
1947
- 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);
1948
2288
  }
1949
2289
 
1950
2290
  /**
@@ -1958,7 +2298,68 @@ contract GenArt721CoreV3_Engine is
1958
2298
  randomizerContract = IRandomizer_V3CoreBase(_randomizerAddress);
1959
2299
  // populate historical randomizer array
1960
2300
  _historicalRandomizerAddresses.push(_randomizerAddress);
1961
- 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
+ });
1962
2363
  }
1963
2364
 
1964
2365
  /**
@@ -1972,7 +2373,9 @@ contract GenArt721CoreV3_Engine is
1972
2373
  */
1973
2374
  function _updateDefaultBaseURI(string memory _defaultBaseURI) internal {
1974
2375
  defaultBaseURI = _defaultBaseURI;
1975
- emit PlatformUpdated(FIELD_DEFAULT_BASE_URI);
2376
+ emit PlatformUpdated(
2377
+ bytes32(uint256(PlatformUpdatedFields.FIELD_DEFAULT_BASE_URI))
2378
+ );
1976
2379
  }
1977
2380
 
1978
2381
  /**
@@ -1981,7 +2384,10 @@ contract GenArt721CoreV3_Engine is
1981
2384
  */
1982
2385
  function _completeProject(uint256 _projectId) internal {
1983
2386
  projects[_projectId].completedTimestamp = uint64(block.timestamp);
1984
- emit ProjectUpdated(_projectId, FIELD_PROJECT_COMPLETED);
2387
+ emit ProjectUpdated(
2388
+ _projectId,
2389
+ bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_COMPLETED))
2390
+ );
1985
2391
  }
1986
2392
 
1987
2393
  /**