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