@artblocks/contracts 1.3.2 → 1.4.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 (229) hide show
  1. package/README.md +11 -10
  2. package/artifacts/contracts/AdminACLV0RoyaltyRegistry.sol/AdminACLV0RoyaltyRegistry.json +193 -0
  3. package/artifacts/contracts/AdminACLV0RoyaltyRegistry.sol/IRoyaltyRegistry.json +35 -0
  4. package/artifacts/contracts/AdminACLV1.sol/AdminACLV1.json +2 -2
  5. package/artifacts/contracts/BytecodeStorageReaders/BytecodeStorageReaderContractV2.sol/BytecodeStorageReaderContractV2.json +2 -2
  6. package/artifacts/contracts/BytecodeStorageReaders/BytecodeStorageReaderContractV2_Web3Call.sol/BytecodeStorageReaderContractV2_Web3Call.json +2 -2
  7. package/artifacts/contracts/BytecodeStorageV2Writer.sol/BytecodeStorageV2Writer.json +2 -2
  8. package/artifacts/contracts/DependencyRegistryV0.sol/DependencyRegistryV0.json +210 -2
  9. package/artifacts/contracts/GenArt721CoreV3_Curated.sol/GenArt721CoreV3_Curated.json +235 -20
  10. package/artifacts/contracts/GenArt721CoreV3_Curated_Flex.sol/GenArt721CoreV3_Curated_Flex.json +3197 -0
  11. package/artifacts/contracts/GenArt721CoreV3_Explorations_Flex.sol/GenArt721CoreV3_Explorations_Flex.json +3192 -0
  12. package/artifacts/contracts/OwnedCreate2FactoryV0.sol/OwnedCreate2FactoryV0.json +2 -2
  13. package/artifacts/contracts/archive/GenArt721CoreV3.sol/GenArt721CoreV3.json +27 -2
  14. package/artifacts/contracts/archive/GenArt721CoreV3_Explorations.sol/GenArt721CoreV3_Explorations.json +27 -2
  15. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExp/MinterDAExpV2.sol/MinterDAExpV2.json +2 -2
  16. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExp/MinterDAExpV3.sol/MinterDAExpV3.json +2 -2
  17. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExp/MinterDAExpV4.sol/MinterDAExpV4.json +2 -2
  18. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExpSettlement/MinterDAExpSettlementV0.sol/MinterDAExpSettlementV0.json +2 -2
  19. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExpSettlement/MinterDAExpSettlementV1.sol/MinterDAExpSettlementV1.json +2 -2
  20. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExpSettlement/MinterDAExpSettlementV2.sol/MinterDAExpSettlementV2.json +2 -2
  21. package/artifacts/contracts/archive/minter-suite/Minters/MinterDALin/MinterDALinV2.sol/MinterDALinV2.json +2 -2
  22. package/artifacts/contracts/archive/minter-suite/Minters/MinterDALin/MinterDALinV3.sol/MinterDALinV3.json +2 -2
  23. package/artifacts/contracts/archive/minter-suite/Minters/MinterDALin/MinterDALinV4.sol/MinterDALinV4.json +2 -2
  24. package/artifacts/contracts/archive/minter-suite/Minters/MinterHolder/MinterHolderV1.sol/MinterHolderV1.json +2 -2
  25. package/artifacts/contracts/archive/minter-suite/Minters/MinterHolder/MinterHolderV2.sol/MinterHolderV2.json +2 -2
  26. package/artifacts/contracts/archive/minter-suite/Minters/MinterHolder/MinterHolderV3.sol/MinterHolderV3.json +2 -2
  27. package/artifacts/contracts/archive/minter-suite/Minters/MinterHolder/MinterHolderV4.sol/MinterHolderV4.json +2 -2
  28. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV1.sol/MinterMerkleV1.json +2 -2
  29. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV2.sol/MinterMerkleV2.json +2 -2
  30. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV3.sol/MinterMerkleV3.json +2 -2
  31. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV4.sol/MinterMerkleV4.json +2 -2
  32. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV5.sol/MinterMerkleV5.json +2 -2
  33. package/artifacts/contracts/archive/minter-suite/Minters/MinterPolyptych/MinterPolyptychV0.sol/IGenArt721CoreContractV3WithRandomizer.json +25 -0
  34. package/artifacts/contracts/archive/minter-suite/Minters/MinterPolyptych/MinterPolyptychV0.sol/MinterPolyptychV0.json +2 -2
  35. package/artifacts/contracts/archive/minter-suite/Minters/MinterSEA/MinterSEAV0.sol/MinterSEAV0.json +2 -2
  36. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPrice/MinterSetPriceV2.sol/MinterSetPriceV2.json +2 -2
  37. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPrice/MinterSetPriceV3.sol/MinterSetPriceV3.json +2 -2
  38. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPrice/MinterSetPriceV4.sol/MinterSetPriceV4.json +2 -2
  39. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V2.sol/MinterSetPriceERC20V2.json +2 -2
  40. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V3.sol/MinterSetPriceERC20V3.json +2 -2
  41. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V4.sol/MinterSetPriceERC20V4.json +2 -2
  42. package/artifacts/contracts/engine/V3/EngineFactoryV0.sol/EngineFactoryV0.json +28 -2
  43. package/artifacts/contracts/engine/V3/GenArt721CoreV3_Engine.sol/GenArt721CoreV3_Engine.json +239 -20
  44. package/artifacts/contracts/engine/V3/GenArt721CoreV3_Engine_Flex.sol/GenArt721CoreV3_Engine_Flex.json +267 -48
  45. package/artifacts/contracts/engine/V3/forks/GenArt721CoreV3_Engine_Flex_PROOF.sol/GenArt721CoreV3_Engine_Flex_PROOF.json +27 -2
  46. package/artifacts/contracts/engine/V3/forks/PROHIBITION/AdminACLV0_PROHIBITION.sol/AdminACLV0_PROHIBITION.json +2 -2
  47. package/artifacts/contracts/engine/V3/forks/PROHIBITION/GenArt721CoreV3_Engine_Flex_PROHIBITION.sol/GenArt721CoreV3_Engine_Flex_PROHIBITION.json +27 -2
  48. package/artifacts/contracts/engine/V3/forks/PROHIBITION/interfaces/IGenArt721CoreContractV3_Engine_Flex_PROHIBITION.sol/IGenArt721CoreContractV3_Engine_Flex_PROHIBITION.json +25 -0
  49. package/artifacts/contracts/engine/V3/transfer-hooks/AbstractTransferHook.sol/AbstractTransferHook.json +79 -0
  50. package/artifacts/contracts/engine/V3/transfer-hooks/OwnerHistoryTransferHook.sol/OwnerHistoryTransferHook.json +315 -0
  51. package/artifacts/contracts/generator/GenArt721GeneratorV0.sol/GenArt721GeneratorV0.json +2 -2
  52. package/artifacts/contracts/interfaces/v0.8.x/IClaimMinter.sol/IClaimMinter.json +189 -0
  53. package/artifacts/contracts/interfaces/v0.8.x/IDependencyRegistryV0.sol/IDependencyRegistryV0.json +149 -0
  54. package/artifacts/contracts/interfaces/v0.8.x/IEngineFactoryV0.sol/IEngineFactoryV0.json +26 -0
  55. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3.sol/IGenArt721CoreContractV3.json +25 -0
  56. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Base.sol/IGenArt721CoreContractV3_Base.json +25 -0
  57. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine.sol/IGenArt721CoreContractV3_Engine.json +123 -0
  58. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex.sol/IGenArt721CoreContractV3_Engine_Flex.json +123 -0
  59. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex_PreV3p2.sol/IGenArt721CoreContractV3_Engine_Flex_PreV3p2.json +25 -0
  60. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_PreV3p2.sol/IGenArt721CoreContractV3_Engine_PreV3p2.json +25 -0
  61. package/artifacts/contracts/interfaces/v0.8.x/IOwnerHistoryTransferHook.sol/IOwnerHistoryTransferHook.json +299 -0
  62. package/artifacts/contracts/interfaces/v0.8.x/ISRHooks.sol/ISRHooks.json +432 -0
  63. package/artifacts/contracts/interfaces/v0.8.x/ISeaDropShimForContract.sol/ISeaDropShimForContract.json +0 -13
  64. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterTieredAllowV0.sol/ISharedMinterTieredAllowV0.json +94 -0
  65. package/artifacts/contracts/interfaces/v0.8.x/ITransferHook.sol/ITransferHook.json +63 -0
  66. package/artifacts/contracts/libs/v0.8.x/AuthLib.sol/AuthLib.json +2 -2
  67. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV2.sol/BytecodeStorageReader.json +2 -2
  68. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV2.sol/BytecodeStorageWriter.json +2 -2
  69. package/artifacts/contracts/libs/v0.8.x/DependencyRegistryStorageLib.sol/DependencyRegistryStorageLib.json +2 -2
  70. package/artifacts/contracts/libs/v0.8.x/ENSLib.sol/ENSLib.json +10 -0
  71. package/artifacts/contracts/libs/v0.8.x/ENSLib.sol/IUniversalResolver.json +45 -0
  72. package/artifacts/contracts/libs/v0.8.x/EnumerableSetUint16.sol/EnumerableSetUint16.json +10 -0
  73. package/artifacts/contracts/libs/v0.8.x/FeistelWalkLib.sol/FeistelWalkLib.json +10 -0
  74. package/artifacts/contracts/libs/v0.8.x/ImmutableUint16Array.sol/ImmutableUint16Array.json +10 -0
  75. package/artifacts/contracts/libs/v0.8.x/V3EngineLib.sol/V3EngineLib.json +163 -0
  76. package/artifacts/contracts/libs/v0.8.x/V3FlexLib.sol/V3FlexLib.json +2 -2
  77. package/artifacts/contracts/libs/v0.8.x/V3TransferHookLib.sol/V3TransferHookLib.json +79 -0
  78. package/artifacts/contracts/libs/v0.8.x/minter-libs/MaxInvocationsLib.sol/MaxInvocationsLib.json +2 -2
  79. package/artifacts/contracts/libs/v0.8.x/minter-libs/OnChainAllowlistLib.sol/OnChainAllowlistLib.json +10 -0
  80. package/artifacts/contracts/libs/v0.8.x/minter-libs/PolyptychLib.sol/PolyptychLib.json +2 -2
  81. package/artifacts/contracts/libs/v0.8.x/minter-libs/RAMLib.sol/RAMLib.json +2 -2
  82. package/artifacts/contracts/libs/v0.8.x/minter-libs/SEALib.sol/SEALib.json +2 -2
  83. package/artifacts/contracts/libs/v0.8.x/minter-libs/SettlementExpLib.sol/SettlementExpLib.json +2 -2
  84. package/artifacts/contracts/libs/v0.8.x/minter-libs/SplitFundsLib.sol/SplitFundsLib.json +2 -2
  85. package/artifacts/contracts/minter-suite/MinterFilter/MinterFilterV1.sol/MinterFilterV1.json +2 -2
  86. package/artifacts/contracts/minter-suite/MinterFilter/MinterFilterV2.sol/MinterFilterV2.json +2 -2
  87. package/artifacts/contracts/minter-suite/Minters/MinterDAExpHolderV5.sol/MinterDAExpHolderV5.json +2 -2
  88. package/artifacts/contracts/minter-suite/Minters/MinterDAExpSettlementV3.sol/MinterDAExpSettlementV3.json +2 -2
  89. package/artifacts/contracts/minter-suite/Minters/MinterDAExpV5.sol/MinterDAExpV5.json +2 -2
  90. package/artifacts/contracts/minter-suite/Minters/MinterDALinHolderV5.sol/MinterDALinHolderV5.json +2 -2
  91. package/artifacts/contracts/minter-suite/Minters/MinterDALinV5.sol/MinterDALinV5.json +2 -2
  92. package/artifacts/contracts/minter-suite/Minters/MinterMinPriceMerkleV0.sol/MinterMinPriceMerkleV0.json +2 -2
  93. package/artifacts/contracts/minter-suite/Minters/MinterMinPriceV0.sol/MinterMinPriceV0.json +2 -2
  94. package/artifacts/contracts/minter-suite/Minters/MinterRAMV0.sol/MinterRAMV0.json +2 -2
  95. package/artifacts/contracts/minter-suite/Minters/MinterSEAV1.sol/MinterSEAV1.json +2 -2
  96. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceERC20V5.sol/MinterSetPriceERC20V5.json +2 -2
  97. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceHolderV5.sol/MinterSetPriceHolderV5.json +2 -2
  98. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceMerkleV5.sol/MinterSetPriceMerkleV5.json +2 -2
  99. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceOnChainAllowV0.sol/MinterSetPriceOnChainAllowV0.json +522 -0
  100. package/artifacts/contracts/minter-suite/Minters/MinterSetPricePolyptychERC20V5.sol/MinterSetPricePolyptychERC20V5.json +2 -2
  101. package/artifacts/contracts/minter-suite/Minters/MinterSetPricePolyptychV5.sol/MinterSetPricePolyptychV5.json +2 -2
  102. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceTieredAllowV1.sol/MinterSetPriceTieredAllowV1.json +715 -0
  103. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceV5.sol/MinterSetPriceV5.json +2 -2
  104. package/artifacts/contracts/minter-suite/Minters/MinterSlidingScaleV0.sol/MinterSlidingScaleV0.json +431 -0
  105. package/artifacts/contracts/minter-suite/Minters/one-off/ClaimMinter.sol/ClaimMinter.json +502 -0
  106. package/artifacts/contracts/minter-suite/Minters/one-off/MinterSetPriceTieredOnChainAllowV0.sol/MinterSetPriceTieredOnChainAllowV0.json +673 -0
  107. package/artifacts/contracts/minter-suite/Minters/one-off/MinterSetPriceV5_SingleCore.sol/MinterSetPriceV5_SingleCore.json +2 -2
  108. package/artifacts/contracts/minter-suite/Minters/one-off/SeaDropXArtBlocksShim.sol/SeaDropXArtBlocksShim.json +6 -19
  109. package/artifacts/contracts/mock/BytecodeV2TextCR_DMock.sol/BytecodeV2TextCR_DMock.json +2 -2
  110. package/artifacts/contracts/mock/DummySharedMinter.sol/DummySharedMinter.json +2 -2
  111. package/artifacts/contracts/mock/ENSLibMock.sol/ENSLibMock.json +30 -0
  112. package/artifacts/contracts/mock/EnumerableSetUint16Mock.sol/EnumerableSetUint16Mock.json +146 -0
  113. package/artifacts/contracts/mock/FeistelWalkLibMock.sol/FeistelWalkLibMock.json +142 -0
  114. package/artifacts/contracts/mock/ForceSendMock.sol/ForceSendMock.json +2 -2
  115. package/artifacts/contracts/mock/GenArt721CoreV3_Engine_IncorrectCoreType.sol/GenArt721CoreV3_Engine_IncorrectCoreType.json +2 -2
  116. package/artifacts/contracts/mock/ImmutableUint16ArrayMock.sol/ImmutableUint16ArrayMock.json +89 -0
  117. package/artifacts/contracts/mock/MockAdminACLV0_PROHIBITION.sol/MockAdminACLV0Events_PROHIBITION.json +2 -2
  118. package/artifacts/contracts/mock/MockGenArt721V3Core.sol/MockGenArt721V3Core.json +490 -0
  119. package/artifacts/contracts/mock/MockPMP.sol/MockPMP.json +523 -0
  120. package/artifacts/contracts/mock/MockTransferHook.sol/MockTransferHook.json +453 -0
  121. package/artifacts/contracts/mock/MockTransferHookTestHelpers.sol/MockBatchTransferrer.json +39 -0
  122. package/artifacts/contracts/mock/MockTransferHookTestHelpers.sol/MockForwardingERC721Receiver.json +71 -0
  123. package/artifacts/contracts/mock/MockTransferHookTestHelpers.sol/MockSpoofingCore.json +94 -0
  124. package/artifacts/contracts/mock/RandomizerV2_NoAssignMock.sol/RandomizerV2_NoAssignMock.json +2 -2
  125. package/artifacts/contracts/mock/ReentrancyBatchMockShared.sol/IBatchMinter.json +64 -0
  126. package/artifacts/contracts/mock/ReentrancyBatchMockShared.sol/ReentrancyBatchMockShared.json +113 -0
  127. package/artifacts/contracts/mock/RelayExecutorTestHelper.sol/MockTarget.json +74 -0
  128. package/artifacts/contracts/mock/RelayExecutorTestHelper.sol/RelayExecutorPartialRevertsTestHelper.json +138 -0
  129. package/artifacts/contracts/mock/RelayExecutorTestHelper.sol/RelayExecutorTestHelper.json +119 -0
  130. package/artifacts/contracts/randomizer/deprecated/PolyptychRandomizerV0.sol/BasicPolyptychRandomizerV0.json +2 -2
  131. package/artifacts/contracts/randomizer/deprecated/RandomizerV2.sol/BasicRandomizerV2.json +2 -2
  132. package/artifacts/contracts/randomizer/shared/SharedRandomizerV0.sol/SharedRandomizerV0.json +2 -2
  133. package/artifacts/contracts/relay/RelayExecutor.sol/RelayExecutor.json +101 -0
  134. package/artifacts/contracts/relay/RelayExecutorPartialReverts.sol/RelayExecutorPartialReverts.json +120 -0
  135. package/artifacts/contracts/royalty-registry/GenArt721RoyaltyOverrideSplits.sol/GenArt721RoyaltyOverrideSplits.json +263 -0
  136. package/artifacts/contracts/utils/MintMulticallUtil.sol/IMinterSetPriceV5.json +40 -0
  137. package/artifacts/contracts/utils/MintMulticallUtil.sol/MintMulticallUtil.json +163 -0
  138. package/artifacts/contracts/web3call/PMPV0.sol/PMPV0.json +2 -2
  139. package/artifacts/contracts/web3call/PMPV1.sol/PMPV1.json +648 -0
  140. package/artifacts/contracts/web3call/augment-hooks/InjectBaseGasFee.sol/InjectBaseGasFee.json +2 -2
  141. package/artifacts/contracts/web3call/augment-hooks/InjectBlockHeight.sol/InjectBlockHeight.json +83 -0
  142. package/artifacts/contracts/web3call/augment-hooks/InjectBlockHeightAndArtistProjectOverrides.sol/InjectBlockHeightAndArtistProjectOverrides.json +226 -0
  143. package/artifacts/contracts/web3call/augment-hooks/InjectBlockHeightAndNumOwnedProjectTokens.sol/InjectBlockHeightAndNumOwnedProjectTokens.json +182 -0
  144. package/artifacts/contracts/web3call/augment-hooks/InjectBlockHeightProjectInvocationsAndArtistProjectOverrides.sol/InjectBlockHeightProjectInvocationsAndArtistProjectOverrides.json +226 -0
  145. package/artifacts/contracts/web3call/augment-hooks/InjectBlockTimestamp.sol/InjectBlockTimestamp.json +83 -0
  146. package/artifacts/contracts/web3call/augment-hooks/InjectBytesPerToken.sol/InjectBytesPerToken.json +358 -0
  147. package/artifacts/contracts/web3call/augment-hooks/InjectChromieSquiggleFloorPrice.sol/InjectChromieSquiggleFloorPrice.json +2 -2
  148. package/artifacts/contracts/web3call/augment-hooks/InjectIsNounsDaoMember.sol/InjectIsNounsDaoMember.json +2 -2
  149. package/artifacts/contracts/web3call/augment-hooks/InjectIsProjectFullyMinted.sol/InjectIsProjectFullyMinted.json +2 -2
  150. package/artifacts/contracts/web3call/augment-hooks/InjectPolyptychTokenHash.sol/InjectPolyptychTokenHash.json +2 -2
  151. package/artifacts/contracts/web3call/augment-hooks/InjectTokenHashSeed.sol/InjectTokenHashSeed.json +2 -2
  152. package/artifacts/contracts/web3call/augment-hooks/InjectTokenOwner.sol/InjectTokenOwner.json +2 -2
  153. package/artifacts/contracts/web3call/augment-hooks/InjectTokenOwnerEthBalance.sol/InjectTokenOwnerEthBalance.json +2 -2
  154. package/artifacts/contracts/web3call/augment-hooks/InjectUSDCTotalSupply.sol/InjectUSDCTotalSupply.json +2 -2
  155. package/artifacts/contracts/web3call/augment-hooks/SRHooks.sol/SRHooks.json +899 -0
  156. package/artifacts/contracts/web3call/combined-hooks/LiftHooks.sol/IGenArt721V0_Minimal.json +30 -0
  157. package/artifacts/contracts/web3call/combined-hooks/LiftHooks.sol/IRelic.json +35 -0
  158. package/artifacts/contracts/web3call/combined-hooks/LiftHooks.sol/LiftHooks.json +256 -0
  159. package/artifacts/contracts/web3call/configure-hooks/{abstractPMPConfigureHook.sol → AbstractPMPConfigureHook.sol}/AbstractPMPConfigureHook.json +1 -1
  160. package/artifacts/contracts/web3call/configure-hooks/PMPConfigureLockHook.sol/PMPConfigureLockHook.json +195 -0
  161. package/contracts/AdminACLV0RoyaltyRegistry.sol +142 -0
  162. package/contracts/DependencyRegistryV0.sol +143 -13
  163. package/contracts/GenArt721CoreV3_Curated.sol +1 -1
  164. package/contracts/GenArt721CoreV3_Curated_Flex.sol +173 -0
  165. package/contracts/GenArt721CoreV3_Explorations_Flex.sol +159 -0
  166. package/contracts/engine/V3/EngineFactoryV0.sol +20 -1
  167. package/contracts/engine/V3/GenArt721CoreV3_Engine.sol +286 -299
  168. package/contracts/engine/V3/GenArt721CoreV3_Engine_Flex.sol +292 -301
  169. package/contracts/engine/V3/transfer-hooks/AbstractTransferHook.sol +101 -0
  170. package/contracts/engine/V3/transfer-hooks/OwnerHistoryTransferHook.sol +291 -0
  171. package/contracts/generator/GenArt721GeneratorV0.sol +145 -47
  172. package/contracts/helpers/ERC1967ProxyImport.sol +5 -0
  173. package/contracts/interfaces/v0.8.x/IArtblocksRoyaltyOverride.sol +1 -1
  174. package/contracts/interfaces/v0.8.x/IClaimMinter.sol +70 -0
  175. package/contracts/interfaces/v0.8.x/IDependencyRegistryV0.sol +95 -0
  176. package/contracts/interfaces/v0.8.x/IEngineFactoryV0.sol +15 -0
  177. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Base.sol +21 -2
  178. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine.sol +72 -0
  179. package/contracts/interfaces/v0.8.x/IOwnerHistoryTransferHook.sol +119 -0
  180. package/contracts/interfaces/v0.8.x/ISRHooks.sol +229 -0
  181. package/contracts/interfaces/v0.8.x/ISeaDropShimForContract.sol +0 -6
  182. package/contracts/interfaces/v0.8.x/ISharedMinterTieredAllowV0.sol +69 -0
  183. package/contracts/interfaces/v0.8.x/ITransferHook.sol +48 -0
  184. package/contracts/libs/v0.8.x/DependencyRegistryStorageLib.sol +12 -0
  185. package/contracts/libs/v0.8.x/ENSLib.sol +85 -0
  186. package/contracts/libs/v0.8.x/EnumerableSetUint16.sol +429 -0
  187. package/contracts/libs/v0.8.x/FeistelWalkLib.sol +221 -0
  188. package/contracts/libs/v0.8.x/ImmutableUint16Array.sol +201 -0
  189. package/contracts/libs/v0.8.x/V3EngineLib.sol +490 -0
  190. package/contracts/libs/v0.8.x/V3TransferHookLib.sol +251 -0
  191. package/contracts/libs/v0.8.x/minter-libs/OnChainAllowlistLib.sol +165 -0
  192. package/contracts/minter-suite/Minters/MinterSetPriceOnChainAllowV0.sol +632 -0
  193. package/contracts/minter-suite/Minters/MinterSetPriceTieredAllowV1.sol +871 -0
  194. package/contracts/minter-suite/Minters/MinterSlidingScaleV0.sol +493 -0
  195. package/contracts/minter-suite/Minters/one-off/ClaimMinter.sol +595 -0
  196. package/contracts/minter-suite/Minters/one-off/MinterSetPriceTieredOnChainAllowV0.sol +894 -0
  197. package/contracts/minter-suite/Minters/one-off/SeaDropXArtBlocksShim.sol +59 -41
  198. package/contracts/mock/ENSLibMock.sol +25 -0
  199. package/contracts/mock/EnumerableSetUint16Mock.sol +88 -0
  200. package/contracts/mock/FeistelWalkLibMock.sol +81 -0
  201. package/contracts/mock/ImmutableUint16ArrayMock.sol +62 -0
  202. package/contracts/mock/MockGenArt721V3Core.sol +416 -0
  203. package/contracts/mock/MockPMP.sol +287 -0
  204. package/contracts/mock/MockTransferHook.sol +160 -0
  205. package/contracts/mock/MockTransferHookTestHelpers.sol +96 -0
  206. package/contracts/mock/ReentrancyBatchMockShared.sol +53 -0
  207. package/contracts/mock/RelayExecutorTestHelper.sol +44 -0
  208. package/contracts/relay/RelayExecutor.sol +61 -0
  209. package/contracts/relay/RelayExecutorPartialReverts.sol +79 -0
  210. package/contracts/royalty-registry/GenArt721RoyaltyOverrideSplits.sol +130 -0
  211. package/contracts/utils/MintMulticallUtil.sol +103 -0
  212. package/contracts/web3call/PMPV1.sol +1204 -0
  213. package/contracts/web3call/augment-hooks/AbstractPMPAugmentHook.sol +1 -1
  214. package/contracts/web3call/augment-hooks/InjectBaseGasFee.sol +1 -1
  215. package/contracts/web3call/augment-hooks/InjectBlockHeight.sol +57 -0
  216. package/contracts/web3call/augment-hooks/InjectBlockHeightAndArtistProjectOverrides.sol +310 -0
  217. package/contracts/web3call/augment-hooks/InjectBlockHeightAndNumOwnedProjectTokens.sol +141 -0
  218. package/contracts/web3call/augment-hooks/InjectBlockHeightProjectInvocationsAndArtistProjectOverrides.sol +326 -0
  219. package/contracts/web3call/augment-hooks/InjectBlockTimestamp.sol +57 -0
  220. package/contracts/web3call/augment-hooks/InjectBytesPerToken.sol +279 -0
  221. package/contracts/web3call/augment-hooks/InjectIsProjectFullyMinted.sol +1 -1
  222. package/contracts/web3call/augment-hooks/InjectTokenHashSeed.sol +1 -1
  223. package/contracts/web3call/augment-hooks/InjectTokenOwner.sol +1 -1
  224. package/contracts/web3call/augment-hooks/InjectTokenOwnerEthBalance.sol +1 -1
  225. package/contracts/web3call/augment-hooks/SRHooks.sol +1722 -0
  226. package/contracts/web3call/combined-hooks/LiftHooks.sol +304 -0
  227. package/contracts/web3call/configure-hooks/{abstractPMPConfigureHook.sol → AbstractPMPConfigureHook.sol} +1 -1
  228. package/contracts/web3call/configure-hooks/PMPConfigureLockHook.sol +107 -0
  229. package/package.json +39 -24
@@ -11,6 +11,7 @@ import "../../interfaces/v0.8.x/IGenArt721CoreContractExposesHashSeed.sol";
11
11
  import "../../interfaces/v0.8.x/IDependencyRegistryCompatibleV0.sol";
12
12
  import {ISplitProviderV0} from "../../interfaces/v0.8.x/ISplitProviderV0.sol";
13
13
  import {IBytecodeStorageReader_Base} from "../../interfaces/v0.8.x/IBytecodeStorageReader_Base.sol";
14
+ import {ITransferHook} from "../../interfaces/v0.8.x/ITransferHook.sol";
14
15
 
15
16
  import "@openzeppelin-5.0/contracts/utils/Strings.sol";
16
17
  import "@openzeppelin-5.0/contracts/access/Ownable.sol";
@@ -19,6 +20,8 @@ import "../../libs/v0.8.x/ERC721_PackedHashSeedV1.sol";
19
20
  import {BytecodeStorageWriter, BytecodeStorageReader} from "../../libs/v0.8.x/BytecodeStorageV2.sol";
20
21
  import {V3FlexLib} from "../../libs/v0.8.x/V3FlexLib.sol";
21
22
  import "../../libs/v0.8.x/Bytes32Strings.sol";
23
+ import {V3EngineLib} from "../../libs/v0.8.x/V3EngineLib.sol";
24
+ import {V3TransferHookLib} from "../../libs/v0.8.x/V3TransferHookLib.sol";
22
25
 
23
26
  /**
24
27
  * @title Art Blocks Engine Flex ERC-721 core contract, V3.
@@ -81,6 +84,23 @@ import "../../libs/v0.8.x/Bytes32Strings.sol";
81
84
  * current number of invocations, and less than current project maximum
82
85
  * invocations)
83
86
  * - updateProjectBaseURI (controlling the base URI for tokens in the project)
87
+ * - lockProjectTransferHook (one-way. Requires the caller to pass the hook
88
+ * they expect to lock in, so a concurrent configure call cannot cause an
89
+ * unintended hook to be locked. Locking while the hook is address(0)
90
+ * forever forbids assigning a transfer hook. If the hook is address(0) when
91
+ * the four-week project metadata lock elapses, it is auto-locked at zero —
92
+ * restoring today's transfer security profile with no extra action. If a
93
+ * hook is already set at auto-lock, it remains configurable until this is
94
+ * called.)
95
+ * ----------------------------------------------------------------------------
96
+ * The following functions are restricted to either the Artist address or
97
+ * the Admin ACL contract. After the four-week project metadata lock, they
98
+ * remain available only if a transfer hook is already set; if the hook is
99
+ * address(0) at auto-lock, it can never be assigned. Independently, the
100
+ * artist may one-way lockProjectTransferHook at any time:
101
+ * - configureProjectTransferHook (WARNING: a reverting hook bricks transfers
102
+ * and mints for the project. A non-zero hook may execute arbitrary code on
103
+ * every transfer. Prefer locking at address(0) if no hook is intended.)
84
104
  * ----------------------------------------------------------------------------
85
105
  * The following function is restricted to either the Admin ACL contract, or
86
106
  * the Artist address if the core contract owner has renounced ownership:
@@ -113,6 +133,11 @@ import "../../libs/v0.8.x/Bytes32Strings.sol";
113
133
  * ----------------------------------------------------------------------------
114
134
  * Additional admin and artist privileged roles may be described on minters,
115
135
  * registries, and other contracts that may interact with this core contract.
136
+ * @dev External libraries (`V3EngineLib`, `V3TransferHookLib`, `V3FlexLib`)
137
+ * are used so Engine and Engine Flex share one implementation of shared logic
138
+ * while both remain under the 24KB bytecode size limit. `V3EngineLib` and
139
+ * `V3TransferHookLib` are shared with `GenArt721CoreV3_Engine`; `V3FlexLib` is
140
+ * Flex-only (external asset dependencies and related helpers).
116
141
  */
117
142
  contract GenArt721CoreV3_Engine_Flex is
118
143
  ERC721_PackedHashSeedV1,
@@ -127,12 +152,10 @@ contract GenArt721CoreV3_Engine_Flex is
127
152
  using BytecodeStorageWriter for bytes;
128
153
  using Bytes32Strings for bytes32;
129
154
  using Strings for uint256;
130
- using Strings for address;
131
155
  uint256 constant ONE_HUNDRED = 100;
132
156
  uint256 constant ONE_MILLION = 1_000_000;
133
157
  uint24 constant ONE_MILLION_UINT24 = 1_000_000;
134
158
  uint256 constant FOUR_WEEKS_IN_SECONDS = 2_419_200;
135
- uint8 constant AT_CHARACTER_CODE = uint8(bytes1("@")); // 0x40
136
159
 
137
160
  // numeric constants
138
161
  uint256 constant MAX_PROVIDER_SECONDARY_SALES_BPS = 10000; // 10_000 BPS = 100%
@@ -281,7 +304,7 @@ contract GenArt721CoreV3_Engine_Flex is
281
304
  bool public allowArtistProjectActivation;
282
305
 
283
306
  /// version & type of this core contract
284
- bytes32 constant CORE_VERSION = "v3.2.5";
307
+ bytes32 constant CORE_VERSION = "v3.3.1";
285
308
 
286
309
  function coreVersion() external pure virtual returns (string memory) {
287
310
  return CORE_VERSION.toString();
@@ -306,6 +329,12 @@ contract GenArt721CoreV3_Engine_Flex is
306
329
  // bytecode storage reader contract; may be universal or specific version reader contract
307
330
  IBytecodeStorageReader_Base public bytecodeStorageReaderContract;
308
331
 
332
+ /// per-project transfer hook configuration and reentrancy flag
333
+ /// @dev appended to the end of this contract's storage; new state
334
+ /// variables must also be appended here, never inserted above, so that
335
+ /// existing storage slot assignments are never shifted
336
+ V3TransferHookLib.Layout private _transferHookLayout;
337
+
309
338
  /**
310
339
  * @dev This constructor sets the owner to a non-functional address as a formality.
311
340
  * It is only ever ran on the implementation contract. The `Ownable` constructor is
@@ -379,6 +408,23 @@ contract GenArt721CoreV3_Engine_Flex is
379
408
  }
380
409
  }
381
410
 
411
+ function _onlyArtistIfUnlockedElseAdminACL(
412
+ uint256 _projectId,
413
+ bytes4 _selector
414
+ ) internal {
415
+ if (_projectUnlocked(_projectId)) {
416
+ if (
417
+ msg.sender != _projectIdToFinancials[_projectId].artistAddress
418
+ ) {
419
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
420
+ }
421
+ } else {
422
+ if (!adminACLAllowed(msg.sender, address(this), _selector)) {
423
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
424
+ }
425
+ }
426
+ }
427
+
382
428
  /**
383
429
  * This modifier allows the artist of a project to call a function if the
384
430
  * owner of the contract has renounced ownership. This is to allow the
@@ -466,6 +512,7 @@ contract GenArt721CoreV3_Engine_Flex is
466
512
 
467
513
  /**
468
514
  * @notice Updates external asset dependency for project `_projectId`.
515
+ * @dev public virtual to allow for derived contracts to override this function
469
516
  * @param _projectId Project to be updated.
470
517
  * @param _index Asset index.
471
518
  * @param _cidOrData Field that contains the CID of the dependency if IPFS or ARWEAVE,
@@ -482,7 +529,7 @@ contract GenArt721CoreV3_Engine_Flex is
482
529
  uint256 _index,
483
530
  string memory _cidOrData,
484
531
  ExternalAssetDependencyType _dependencyType
485
- ) external {
532
+ ) public virtual {
486
533
  _onlyArtistOrAdminACL(
487
534
  _projectId,
488
535
  this.updateProjectExternalAssetDependency.selector
@@ -571,6 +618,7 @@ contract GenArt721CoreV3_Engine_Flex is
571
618
 
572
619
  /**
573
620
  * @notice Adds external asset dependency for project `_projectId`.
621
+ * @dev public virtual to allow for derived contracts to override this function
574
622
  * @param _projectId Project to be updated.
575
623
  * @param _cidOrData Field that contains the CID of the dependency if IPFS or ARWEAVE,
576
624
  * empty string of ONCHAIN, or a string representation of the Art Blocks Dependency
@@ -585,7 +633,7 @@ contract GenArt721CoreV3_Engine_Flex is
585
633
  uint256 _projectId,
586
634
  string memory _cidOrData,
587
635
  ExternalAssetDependencyType _dependencyType
588
- ) external {
636
+ ) public virtual {
589
637
  _onlyArtistOrAdminACL(
590
638
  _projectId,
591
639
  this.addProjectExternalAssetDependency.selector
@@ -714,10 +762,24 @@ contract GenArt721CoreV3_Engine_Flex is
714
762
  // token hash is updated by the randomizer contract on V3
715
763
  randomizerContract.assignTokenHash(thisTokenId);
716
764
 
765
+ // mint transfer hook after hash assignment so the hook can read
766
+ // tokenIdToHash. `_update` skips mint dispatch (from == address(0)).
767
+ _dispatchTransferHook({
768
+ from: address(0),
769
+ to: _to,
770
+ tokenId: thisTokenId,
771
+ operator: _by
772
+ });
773
+
717
774
  // Do not need to also log `projectId` in event, as the `projectId` for
718
775
  // a given token can be derived from the `tokenId` with:
719
776
  // projectId = tokenId / 1_000_000
720
- emit Mint(_to, thisTokenId);
777
+ bytes12 hashSeed = _ownersAndHashSeeds[thisTokenId].hashSeed;
778
+ emit Mint(
779
+ _to,
780
+ thisTokenId,
781
+ hashSeed != 0 ? keccak256(abi.encode(hashSeed)) : bytes32(0)
782
+ );
721
783
 
722
784
  return thisTokenId;
723
785
  }
@@ -1070,98 +1132,20 @@ contract GenArt721CoreV3_Engine_Flex is
1070
1132
  _onlyValidProjectId(_projectId);
1071
1133
  _onlyArtist(_projectId);
1072
1134
  _onlyNonZeroAddress(_artistAddress);
1073
- ProjectFinance storage projectFinance = _projectIdToFinancials[
1074
- _projectId
1075
- ];
1076
- // checks
1077
- if (
1078
- _additionalPayeePrimarySalesPercentage > ONE_HUNDRED ||
1079
- _additionalPayeeSecondarySalesPercentage > ONE_HUNDRED
1080
- ) {
1081
- revert GenArt721Error(ErrorCodes.MaxOf100Percent);
1082
- }
1083
- if (
1084
- _additionalPayeePrimarySalesPercentage > 0 &&
1085
- _additionalPayeePrimarySales == address(0)
1086
- ) {
1087
- revert GenArt721Error(ErrorCodes.PrimaryPayeeIsZeroAddress);
1088
- }
1089
- if (
1090
- _additionalPayeeSecondarySalesPercentage > 0 &&
1091
- _additionalPayeeSecondarySales == address(0)
1092
- ) {
1093
- revert GenArt721Error(ErrorCodes.SecondaryPayeeIsZeroAddress);
1094
- }
1095
- // effects
1096
- // emit event for off-chain indexing
1097
- // note: always emit a proposal event, even in the pathway of
1098
- // automatic approval, to simplify indexing expectations
1099
- emit ProposedArtistAddressesAndSplits(
1100
- _projectId,
1101
- _artistAddress,
1102
- _additionalPayeePrimarySales,
1103
- _additionalPayeePrimarySalesPercentage,
1104
- _additionalPayeeSecondarySales,
1105
- _additionalPayeeSecondarySalesPercentage
1106
- );
1107
- // automatically accept if no proposed addresses modifications, or if
1108
- // the proposal only removes payee addresses, or if contract is set to
1109
- // always auto-approve.
1110
- // store proposal hash on-chain, only if not automatic accept
1111
- bool automaticAccept = autoApproveArtistSplitProposals;
1112
- if (!automaticAccept) {
1113
- // block scope to avoid stack too deep error
1114
- bool artistUnchanged = _artistAddress ==
1115
- projectFinance.artistAddress;
1116
- bool additionalPrimaryUnchangedOrRemoved = (_additionalPayeePrimarySales ==
1117
- projectFinance.additionalPayeePrimarySales) ||
1118
- (_additionalPayeePrimarySales == address(0));
1119
- bool additionalSecondaryUnchangedOrRemoved = (_additionalPayeeSecondarySales ==
1120
- projectFinance.additionalPayeeSecondarySales) ||
1121
- (_additionalPayeeSecondarySales == address(0));
1122
- automaticAccept =
1123
- artistUnchanged &&
1124
- additionalPrimaryUnchangedOrRemoved &&
1125
- additionalSecondaryUnchangedOrRemoved;
1126
- }
1127
- if (automaticAccept) {
1128
- // clear any previously proposed values
1129
- proposedArtistAddressesAndSplitsHash[_projectId] = bytes32(0);
1130
-
1131
- // update storage
1132
- // artist address can change during automatic accept if
1133
- // autoApproveArtistSplitProposals is true
1134
- projectFinance.artistAddress = _artistAddress;
1135
- projectFinance
1136
- .additionalPayeePrimarySales = _additionalPayeePrimarySales;
1137
- // safe to cast as uint8 as max is 100%, max uint8 is 255
1138
- projectFinance.additionalPayeePrimarySalesPercentage = uint8(
1139
- _additionalPayeePrimarySalesPercentage
1140
- );
1141
- projectFinance
1142
- .additionalPayeeSecondarySales = _additionalPayeeSecondarySales;
1143
- // safe to cast as uint8 as max is 100%, max uint8 is 255
1144
- projectFinance.additionalPayeeSecondarySalesPercentage = uint8(
1145
- _additionalPayeeSecondarySalesPercentage
1146
- );
1147
-
1148
- // assign project's splitter
1149
- // @dev only call after all previous storage updates
1150
- _assignSplitter(_projectId);
1151
-
1152
- // emit event for off-chain indexing
1153
- emit AcceptedArtistAddressesAndSplits(_projectId);
1154
- } else {
1155
- proposedArtistAddressesAndSplitsHash[_projectId] = keccak256(
1156
- abi.encode(
1157
- _artistAddress,
1158
- _additionalPayeePrimarySales,
1159
- _additionalPayeePrimarySalesPercentage,
1160
- _additionalPayeeSecondarySales,
1161
- _additionalPayeeSecondarySalesPercentage
1162
- )
1163
- );
1164
- }
1135
+ V3EngineLib.proposeArtistPaymentAddressesAndSplits({
1136
+ proposal: V3EngineLib.ArtistSplitProposal({
1137
+ projectId: _projectId,
1138
+ artistAddress: _artistAddress,
1139
+ additionalPayeePrimarySales: _additionalPayeePrimarySales,
1140
+ additionalPayeePrimarySalesPercentage: _additionalPayeePrimarySalesPercentage,
1141
+ additionalPayeeSecondarySales: _additionalPayeeSecondarySales,
1142
+ additionalPayeeSecondarySalesPercentage: _additionalPayeeSecondarySalesPercentage
1143
+ }),
1144
+ projectFinance: _projectIdToFinancials[_projectId],
1145
+ proposedHashes: proposedArtistAddressesAndSplitsHash,
1146
+ autoApprove: autoApproveArtistSplitProposals,
1147
+ splitProvider: splitProvider
1148
+ });
1165
1149
  }
1166
1150
 
1167
1151
  /**
@@ -1203,45 +1187,19 @@ contract GenArt721CoreV3_Engine_Flex is
1203
1187
  this.adminAcceptArtistAddressesAndSplits.selector
1204
1188
  );
1205
1189
  _onlyNonZeroAddress(_artistAddress);
1206
- // checks
1207
- if (
1208
- proposedArtistAddressesAndSplitsHash[_projectId] !=
1209
- keccak256(
1210
- abi.encode(
1211
- _artistAddress,
1212
- _additionalPayeePrimarySales,
1213
- _additionalPayeePrimarySalesPercentage,
1214
- _additionalPayeeSecondarySales,
1215
- _additionalPayeeSecondarySalesPercentage
1216
- )
1217
- )
1218
- ) {
1219
- revert GenArt721Error(ErrorCodes.MustMatchArtistProposal);
1220
- }
1221
- // effects
1222
- ProjectFinance storage projectFinance = _projectIdToFinancials[
1223
- _projectId
1224
- ];
1225
- projectFinance.artistAddress = _artistAddress;
1226
- projectFinance
1227
- .additionalPayeePrimarySales = _additionalPayeePrimarySales;
1228
- projectFinance.additionalPayeePrimarySalesPercentage = uint8(
1229
- _additionalPayeePrimarySalesPercentage
1230
- );
1231
- projectFinance
1232
- .additionalPayeeSecondarySales = _additionalPayeeSecondarySales;
1233
- projectFinance.additionalPayeeSecondarySalesPercentage = uint8(
1234
- _additionalPayeeSecondarySalesPercentage
1235
- );
1236
- // clear proposed values
1237
- proposedArtistAddressesAndSplitsHash[_projectId] = bytes32(0);
1238
-
1239
- // assign project's splitter
1240
- // @dev only call after all previous storage updates
1241
- _assignSplitter(_projectId);
1242
-
1243
- // emit event for off-chain indexing
1244
- emit AcceptedArtistAddressesAndSplits(_projectId);
1190
+ V3EngineLib.adminAcceptArtistAddressesAndSplits({
1191
+ proposal: V3EngineLib.ArtistSplitProposal({
1192
+ projectId: _projectId,
1193
+ artistAddress: _artistAddress,
1194
+ additionalPayeePrimarySales: _additionalPayeePrimarySales,
1195
+ additionalPayeePrimarySalesPercentage: _additionalPayeePrimarySalesPercentage,
1196
+ additionalPayeeSecondarySales: _additionalPayeeSecondarySales,
1197
+ additionalPayeeSecondarySalesPercentage: _additionalPayeeSecondarySalesPercentage
1198
+ }),
1199
+ projectFinance: _projectIdToFinancials[_projectId],
1200
+ proposedHashes: proposedArtistAddressesAndSplitsHash,
1201
+ splitProvider: splitProvider
1202
+ });
1245
1203
  }
1246
1204
 
1247
1205
  /**
@@ -1382,25 +1340,10 @@ contract GenArt721CoreV3_Engine_Flex is
1382
1340
  uint256 _projectId,
1383
1341
  string memory _projectArtistName
1384
1342
  ) external {
1385
- // if unlocked, only artist may update, if locked, only admin may update
1386
- // @dev valid project checked in _projectUnlocked function
1387
- if (_projectUnlocked(_projectId)) {
1388
- if (
1389
- msg.sender != _projectIdToFinancials[_projectId].artistAddress
1390
- ) {
1391
- revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1392
- }
1393
- } else {
1394
- if (
1395
- !adminACLAllowed(
1396
- msg.sender,
1397
- address(this),
1398
- this.updateProjectArtistName.selector
1399
- )
1400
- ) {
1401
- revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1402
- }
1403
- }
1343
+ _onlyArtistIfUnlockedElseAdminACL(
1344
+ _projectId,
1345
+ this.updateProjectArtistName.selector
1346
+ );
1404
1347
  _onlyNonEmptyString(_projectArtistName);
1405
1348
  projects[_projectId].artist = _projectArtistName;
1406
1349
  emit ProjectUpdated(
@@ -1507,24 +1450,10 @@ contract GenArt721CoreV3_Engine_Flex is
1507
1450
  string memory _projectDescription
1508
1451
  ) external {
1509
1452
  // checks
1510
- // if unlocked, only artist may update, if locked, only admin may update
1511
- if (_projectUnlocked(_projectId)) {
1512
- if (
1513
- msg.sender != _projectIdToFinancials[_projectId].artistAddress
1514
- ) {
1515
- revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1516
- }
1517
- } else {
1518
- if (
1519
- !adminACLAllowed(
1520
- msg.sender,
1521
- address(this),
1522
- this.updateProjectDescription.selector
1523
- )
1524
- ) {
1525
- revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1526
- }
1527
- }
1453
+ _onlyArtistIfUnlockedElseAdminACL(
1454
+ _projectId,
1455
+ this.updateProjectDescription.selector
1456
+ );
1528
1457
  // effects
1529
1458
  // store description in contract bytecode, replacing reference address from
1530
1459
  // the old storage description with the newly created one
@@ -1768,17 +1697,9 @@ contract GenArt721CoreV3_Engine_Flex is
1768
1697
  _projectId,
1769
1698
  this.updateProjectScriptType.selector
1770
1699
  );
1771
- Project storage project = projects[_projectId];
1772
1700
  // require exactly one @ symbol in _scriptTypeAndVersion
1773
- if (
1774
- !_scriptTypeAndVersion.containsExactCharacterQty(
1775
- AT_CHARACTER_CODE,
1776
- uint8(1)
1777
- )
1778
- ) {
1779
- revert GenArt721Error(ErrorCodes.ScriptTypeAndVersionFormat);
1780
- }
1781
- project.scriptTypeAndVersion = _scriptTypeAndVersion;
1701
+ V3EngineLib.validateScriptTypeAndVersion(_scriptTypeAndVersion);
1702
+ projects[_projectId].scriptTypeAndVersion = _scriptTypeAndVersion;
1782
1703
  emit ProjectUpdated(
1783
1704
  _projectId,
1784
1705
  bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT_TYPE))
@@ -1803,35 +1724,7 @@ contract GenArt721CoreV3_Engine_Flex is
1803
1724
  );
1804
1725
  _onlyNonEmptyString(_aspectRatio);
1805
1726
  // Perform more detailed input validation for aspect ratio.
1806
- bytes memory aspectRatioBytes = bytes(_aspectRatio);
1807
- uint256 bytesLength = aspectRatioBytes.length;
1808
- if (bytesLength > 11) {
1809
- revert GenArt721Error(ErrorCodes.AspectRatioTooLong);
1810
- }
1811
- bool hasSeenDecimalSeparator = false;
1812
- bool hasSeenNumber = false;
1813
- for (uint256 i; i < bytesLength; i++) {
1814
- bytes1 character = aspectRatioBytes[i];
1815
- // Allow as many #s as desired.
1816
- if (character >= 0x30 && character <= 0x39) {
1817
- // 9-0
1818
- // We need to ensure there is at least 1 `9-0` occurrence.
1819
- hasSeenNumber = true;
1820
- continue;
1821
- }
1822
- if (character == 0x2E) {
1823
- // .
1824
- // Allow no more than 1 `.` occurrence.
1825
- if (!hasSeenDecimalSeparator) {
1826
- hasSeenDecimalSeparator = true;
1827
- continue;
1828
- }
1829
- }
1830
- revert GenArt721Error(ErrorCodes.AspectRatioImproperFormat);
1831
- }
1832
- if (!hasSeenNumber) {
1833
- revert GenArt721Error(ErrorCodes.AspectRatioNoNumbers);
1834
- }
1727
+ V3EngineLib.validateAspectRatio(_aspectRatio);
1835
1728
 
1836
1729
  projects[_projectId].aspectRatio = _aspectRatio;
1837
1730
  emit ProjectUpdated(
@@ -1861,6 +1754,76 @@ contract GenArt721CoreV3_Engine_Flex is
1861
1754
  );
1862
1755
  }
1863
1756
 
1757
+ /**
1758
+ * @notice Set or clear the transfer hook for project `_projectId`.
1759
+ * Artist or Admin ACL. Reverts if the configuration is locked: either the
1760
+ * artist called `lockProjectTransferHook`, or the four-week project
1761
+ * metadata lock has elapsed while the hook is `address(0)`. After that
1762
+ * auto-lock, a hook that is already set remains configurable until the
1763
+ * artist calls `lockProjectTransferHook`. Clearing to `address(0)` after
1764
+ * auto-lock permanently forbids assigning a hook again.
1765
+ * WARNING: A reverting hook bricks transfers and mints for every token in
1766
+ * the project. A hook may execute arbitrary code, and a mutable proxy hook
1767
+ * can change behavior after it is set. Artists who do not want a hook may
1768
+ * leave it unset until auto-lock, or `lockProjectTransferHook` earlier.
1769
+ * @dev Hook configuration is implemented in `V3TransferHookLib` so Engine
1770
+ * and Engine Flex share one implementation while both remain under the
1771
+ * 24KB bytecode size limit.
1772
+ * @param _projectId Project ID.
1773
+ * @param _hook Hook contract, or `address(0)` to clear.
1774
+ */
1775
+ function configureProjectTransferHook(
1776
+ uint256 _projectId,
1777
+ address _hook
1778
+ ) external {
1779
+ _onlyValidProjectId(_projectId);
1780
+ _onlyArtistOrAdminACL(
1781
+ _projectId,
1782
+ this.configureProjectTransferHook.selector
1783
+ );
1784
+ V3TransferHookLib.configure({
1785
+ layout: _transferHookLayout,
1786
+ projectId: _projectId,
1787
+ hook: ITransferHook(_hook),
1788
+ projectUnlocked: _projectUnlocked(_projectId)
1789
+ });
1790
+ }
1791
+
1792
+ /**
1793
+ * @notice Permanently lock the transfer hook for project `_projectId` at
1794
+ * `_expectedHook`, which may be `address(0)`. Artist only. If locked at
1795
+ * `address(0)`, a hook can never be assigned. Reverts if already locked,
1796
+ * including when the four-week project metadata lock has already frozen
1797
+ * an unset hook.
1798
+ * @dev `_expectedHook` must match the project's currently configured hook.
1799
+ * Because this lock is permanent and the hook may be updated by either the
1800
+ * artist or the Admin ACL, requiring the expected value prevents a
1801
+ * `configureProjectTransferHook` call landing first from causing an
1802
+ * unintended hook to be permanently locked in.
1803
+ * WARNING: locking freezes the hook ADDRESS, not the hook's behavior. If
1804
+ * `_expectedHook` is an upgradeable proxy, its owner may still change what
1805
+ * runs on every transfer, and the project has no way to move away from it.
1806
+ * Locking is only a meaningful guarantee when the hook is immutable, or
1807
+ * when locking at `address(0)`.
1808
+ * @dev Implemented in `V3TransferHookLib` so Engine and Engine Flex share
1809
+ * one implementation while both remain under the 24KB bytecode size limit.
1810
+ * @param _projectId Project ID.
1811
+ * @param _expectedHook Hook the caller expects to lock in.
1812
+ */
1813
+ function lockProjectTransferHook(
1814
+ uint256 _projectId,
1815
+ address _expectedHook
1816
+ ) external {
1817
+ _onlyValidProjectId(_projectId);
1818
+ _onlyArtist(_projectId);
1819
+ V3TransferHookLib.lock({
1820
+ layout: _transferHookLayout,
1821
+ projectId: _projectId,
1822
+ expectedHook: _expectedHook,
1823
+ projectUnlocked: _projectUnlocked(_projectId)
1824
+ });
1825
+ }
1826
+
1864
1827
  /**
1865
1828
  * @notice Updates default base URI to `_defaultBaseURI`. The
1866
1829
  * contract-level defaultBaseURI is only used when initializing new
@@ -2127,6 +2090,33 @@ contract GenArt721CoreV3_Engine_Flex is
2127
2090
  projectBaseURI = projects[_projectId].projectBaseURI;
2128
2091
  }
2129
2092
 
2093
+ /**
2094
+ * @notice Transfer hook configuration for project `_projectId`.
2095
+ * @dev Reverts if `_projectId` is not a valid project on this contract.
2096
+ * @dev The effective lock is evaluated by `V3TransferHookLib` so that this
2097
+ * view, `configureProjectTransferHook`, and `lockProjectTransferHook` can
2098
+ * never disagree about whether a project is locked.
2099
+ * @param _projectId Project to be queried.
2100
+ * @return hook Hook address, or `address(0)` if none is configured.
2101
+ * @return locked True if the artist called `lockProjectTransferHook`, or
2102
+ * if the four-week project metadata lock has elapsed while the hook is
2103
+ * `address(0)`.
2104
+ */
2105
+ function projectTransferHookConfig(
2106
+ uint256 _projectId
2107
+ ) external view returns (address hook, bool locked) {
2108
+ V3TransferHookLib.ProjectTransferHookConfig
2109
+ storage config = _transferHookLayout.configs[_projectId];
2110
+ // @dev `_projectUnlocked` also enforces that `_projectId` is valid
2111
+ return (
2112
+ address(config.hook),
2113
+ V3TransferHookLib.isLocked({
2114
+ config: config,
2115
+ projectUnlocked: _projectUnlocked(_projectId)
2116
+ })
2117
+ );
2118
+ }
2119
+
2130
2120
  /**
2131
2121
  * @notice Backwards-compatible (pre-V3) function returning if `_minter` is
2132
2122
  * minterContract.
@@ -2172,36 +2162,21 @@ contract GenArt721CoreV3_Engine_Flex is
2172
2162
  * @return receiver address that should be sent the royalty payment
2173
2163
  * @return royaltyAmount the royalty payment amount for `_salePrice
2174
2164
  * @dev reverts if invalid _tokenId
2165
+ * @dev Implemented in `V3EngineLib` so Engine and Engine Flex share one
2166
+ * implementation while both remain under the 24KB bytecode size limit.
2175
2167
  */
2176
2168
  function royaltyInfo(
2177
2169
  uint256 _tokenId,
2178
2170
  uint256 _salePrice
2179
2171
  ) external view returns (address receiver, uint256 royaltyAmount) {
2180
2172
  _onlyValidTokenId(_tokenId);
2181
-
2182
- // populate receiver with project's royalty splitter
2183
- // @dev royalty splitter created upon project creation, so will always exist
2184
- // for valid token ID
2185
- uint256 projectId = tokenIdToProjectId(_tokenId);
2186
- ProjectFinance storage projectFinance = _projectIdToFinancials[
2187
- projectId
2188
- ];
2189
- receiver = projectFinance.royaltySplitter;
2190
-
2191
- // populate royaltyAmount with calculated royalty amount
2192
- // @dev important to cast to uint256 before multiplying to avoid overflow
2193
- uint256 totalRoyaltyBPS = (100 *
2194
- uint256(projectFinance.secondaryMarketRoyaltyPercentage)) +
2195
- projectFinance.platformProviderSecondarySalesBPS +
2196
- projectFinance.renderProviderSecondarySalesBPS;
2197
- // @dev totalRoyaltyBPS guaranteed to be <= 10,000,
2198
- if (totalRoyaltyBPS > 10_000) {
2199
- revert GenArt721Error(ErrorCodes.OverMaxSumOfBPS);
2200
- }
2201
- // @dev overflow automatically checked in solidity 0.8
2202
- // @dev totalRoyaltyBPS guaranteed to be <= 10_000,
2203
- // so overflow only possible with unreasonably high _salePrice values near uint256 max
2204
- royaltyAmount = (_salePrice * totalRoyaltyBPS) / 10_000;
2173
+ return
2174
+ V3EngineLib.royaltyInfo({
2175
+ projectFinance: _projectIdToFinancials[
2176
+ tokenIdToProjectId(_tokenId)
2177
+ ],
2178
+ salePrice: _salePrice
2179
+ });
2205
2180
  }
2206
2181
 
2207
2182
  /**
@@ -2236,6 +2211,8 @@ contract GenArt721CoreV3_Engine_Flex is
2236
2211
  * revenue is zero, the corresponding address will be address(0). It is up
2237
2212
  * to the contract performing the revenue split to handle this
2238
2213
  * appropriately.
2214
+ * @dev Implemented in `V3EngineLib` so Engine and Engine Flex share one
2215
+ * implementation while both remain under the 24KB bytecode size limit.
2239
2216
  */
2240
2217
  function getPrimaryRevenueSplits(
2241
2218
  uint256 _projectId,
@@ -2254,41 +2231,15 @@ contract GenArt721CoreV3_Engine_Flex is
2254
2231
  address payable additionalPayeePrimaryAddress_
2255
2232
  )
2256
2233
  {
2257
- ProjectFinance storage projectFinance = _projectIdToFinancials[
2258
- _projectId
2259
- ];
2260
- // calculate revenues – this is a three-way split between the
2261
- // render provider, the platform provider, and the artist, and
2262
- // is safe to perform this given that in the case of loss of
2263
- // precision Solidity will round down.
2264
- uint256 projectFunds = _price;
2265
- renderProviderRevenue_ =
2266
- (_price * uint256(_renderProviderPrimarySalesPercentage)) /
2267
- ONE_HUNDRED;
2268
- // renderProviderRevenue_ percentage is always <=100, so guaranteed to never underflow
2269
- projectFunds -= renderProviderRevenue_;
2270
- platformProviderRevenue_ =
2271
- (_price * uint256(_platformProviderPrimarySalesPercentage)) /
2272
- ONE_HUNDRED;
2273
- // platformProviderRevenue_ percentage is always <=100, so guaranteed to never underflow
2274
- projectFunds -= platformProviderRevenue_;
2275
- additionalPayeePrimaryRevenue_ =
2276
- (projectFunds *
2277
- projectFinance.additionalPayeePrimarySalesPercentage) /
2278
- ONE_HUNDRED;
2279
- // projectIdToAdditionalPayeePrimarySalesPercentage is always
2280
- // <=100, so guaranteed to never underflow
2281
- artistRevenue_ = projectFunds - additionalPayeePrimaryRevenue_;
2282
- // set addresses from storage
2283
- renderProviderAddress_ = renderProviderPrimarySalesAddress;
2284
- platformProviderAddress_ = platformProviderPrimarySalesAddress;
2285
- if (artistRevenue_ > 0) {
2286
- artistAddress_ = projectFinance.artistAddress;
2287
- }
2288
- if (additionalPayeePrimaryRevenue_ > 0) {
2289
- additionalPayeePrimaryAddress_ = projectFinance
2290
- .additionalPayeePrimarySales;
2291
- }
2234
+ return
2235
+ V3EngineLib.getPrimaryRevenueSplits({
2236
+ projectFinance: _projectIdToFinancials[_projectId],
2237
+ price: _price,
2238
+ renderProviderPrimarySalesPercentage: _renderProviderPrimarySalesPercentage,
2239
+ platformProviderPrimarySalesPercentage: _platformProviderPrimarySalesPercentage,
2240
+ renderProviderPrimarySalesAddress: renderProviderPrimarySalesAddress,
2241
+ platformProviderPrimarySalesAddress: platformProviderPrimarySalesAddress
2242
+ });
2292
2243
  }
2293
2244
 
2294
2245
  /**
@@ -2444,6 +2395,64 @@ contract GenArt721CoreV3_Engine_Flex is
2444
2395
  super.supportsInterface(interfaceId);
2445
2396
  }
2446
2397
 
2398
+ /**
2399
+ * @dev After ownership is written, dispatch the project's transfer hook
2400
+ * for non-mint transfers. Mint dispatch happens in `mint_Ecf` after hash
2401
+ * assignment so the hook can read `tokenIdToHash`.
2402
+ * Reverts if a transfer hook is already executing, blocking reentrant
2403
+ * transfers from a hook.
2404
+ */
2405
+ function _update(
2406
+ address to,
2407
+ uint256 tokenId,
2408
+ address auth
2409
+ ) internal override returns (address) {
2410
+ if (_transferHookLayout.executing) {
2411
+ revert GenArt721Error(ErrorCodes.TransferHookReentrancy);
2412
+ }
2413
+ address from = super._update(to, tokenId, auth);
2414
+ if (from != address(0)) {
2415
+ _dispatchTransferHook({
2416
+ from: from,
2417
+ to: to,
2418
+ tokenId: tokenId,
2419
+ operator: _msgSender()
2420
+ });
2421
+ }
2422
+ return from;
2423
+ }
2424
+
2425
+ /**
2426
+ * @notice Call the project's transfer hook if one is configured.
2427
+ * @dev Projects with no hook return after a single SLOAD of the project's
2428
+ * config slot, with no DELEGATECALL. Combined with the `executing` SLOAD
2429
+ * in `_update`, a transfer on a contract using no hooks costs roughly
2430
+ * 4,200 gas more than it did prior to v3.3. A transfer that does dispatch
2431
+ * a hook additionally pays a ~20,000 gas SSTORE to set the reentrancy
2432
+ * flag, plus the DELEGATECALL and the hook's own execution.
2433
+ */
2434
+ function _dispatchTransferHook(
2435
+ address from,
2436
+ address to,
2437
+ uint256 tokenId,
2438
+ address operator
2439
+ ) internal {
2440
+ ITransferHook hook = _transferHookLayout
2441
+ .configs[tokenId / ONE_MILLION]
2442
+ .hook;
2443
+ if (address(hook) == address(0)) {
2444
+ return;
2445
+ }
2446
+ V3TransferHookLib.callHook({
2447
+ layout: _transferHookLayout,
2448
+ hook: hook,
2449
+ tokenId: tokenId,
2450
+ from: from,
2451
+ to: to,
2452
+ operator: operator
2453
+ });
2454
+ }
2455
+
2447
2456
  /**
2448
2457
  * @notice Forbids new projects from being created
2449
2458
  * @dev only performs operation and emits event if contract is not already
@@ -2594,39 +2603,16 @@ contract GenArt721CoreV3_Engine_Flex is
2594
2603
  * financials, so ensure storage has been updated before calling this
2595
2604
  * @dev This function includes a trusted interaction that is entrusted to
2596
2605
  * not reenter this contract.
2606
+ * @dev Implemented in `V3EngineLib` so Engine and Engine Flex share one
2607
+ * implementation while both remain under the 24KB bytecode size limit.
2597
2608
  * @param projectId Project ID to be updated.
2598
2609
  */
2599
2610
  function _assignSplitter(uint256 projectId) internal {
2600
- ProjectFinance storage projectFinance = _projectIdToFinancials[
2611
+ V3EngineLib.assignSplitter(
2612
+ _projectIdToFinancials[projectId],
2613
+ splitProvider,
2601
2614
  projectId
2602
- ];
2603
- // assign project's royalty splitter
2604
- // @dev loads values from storage, so need to ensure storage has been updated
2605
- address royaltySplitter = splitProvider.getOrCreateSplitter(
2606
- ISplitProviderV0.SplitInputs({
2607
- platformProviderSecondarySalesAddress: projectFinance
2608
- .platformProviderSecondarySalesAddress,
2609
- platformProviderSecondarySalesBPS: projectFinance
2610
- .platformProviderSecondarySalesBPS,
2611
- renderProviderSecondarySalesAddress: projectFinance
2612
- .renderProviderSecondarySalesAddress,
2613
- renderProviderSecondarySalesBPS: projectFinance
2614
- .renderProviderSecondarySalesBPS,
2615
- artistTotalRoyaltyPercentage: projectFinance
2616
- .secondaryMarketRoyaltyPercentage,
2617
- artist: projectFinance.artistAddress,
2618
- additionalPayee: projectFinance.additionalPayeeSecondarySales,
2619
- additionalPayeePercentage: projectFinance
2620
- .additionalPayeeSecondarySalesPercentage
2621
- })
2622
2615
  );
2623
-
2624
- projectFinance.royaltySplitter = royaltySplitter;
2625
-
2626
- emit ProjectRoyaltySplitterUpdated({
2627
- projectId: projectId,
2628
- royaltySplitter: royaltySplitter
2629
- });
2630
2616
  }
2631
2617
 
2632
2618
  /**
@@ -2727,8 +2713,13 @@ contract GenArt721CoreV3_Engine_Flex is
2727
2713
  // set AdminACL management contract as owner
2728
2714
  _transferOwnership(adminACLContract_);
2729
2715
  // initialize default base URI
2716
+ // @dev offloaded to V3EngineLib to keep `Strings.toHexString` out of
2717
+ // the size-constrained cores; this runs once, at initialization
2730
2718
  _updateDefaultBaseURI(
2731
- string.concat(defaultBaseURIHost, address(this).toHexString(), "/")
2719
+ V3EngineLib.buildDefaultBaseURI({
2720
+ host: defaultBaseURIHost,
2721
+ coreContract: address(this)
2722
+ })
2732
2723
  );
2733
2724
  // initialize next project ID
2734
2725
  _nextProjectId = engineConfiguration.startingProjectId;