@artblocks/contracts 1.3.1 → 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 (234) 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/IPMPV0.sol/IPMPV0.json +7 -1
  63. package/artifacts/contracts/interfaces/v0.8.x/ISRHooks.sol/ISRHooks.json +432 -0
  64. package/artifacts/contracts/interfaces/v0.8.x/ISeaDropShimForContract.sol/ISeaDropShimForContract.json +0 -13
  65. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterTieredAllowV0.sol/ISharedMinterTieredAllowV0.json +94 -0
  66. package/artifacts/contracts/interfaces/v0.8.x/ITransferHook.sol/ITransferHook.json +63 -0
  67. package/artifacts/contracts/libs/v0.8.x/AuthLib.sol/AuthLib.json +2 -2
  68. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV2.sol/BytecodeStorageReader.json +2 -2
  69. package/artifacts/contracts/libs/v0.8.x/BytecodeStorageV2.sol/BytecodeStorageWriter.json +2 -2
  70. package/artifacts/contracts/libs/v0.8.x/DependencyRegistryStorageLib.sol/DependencyRegistryStorageLib.json +2 -2
  71. package/artifacts/contracts/libs/v0.8.x/ENSLib.sol/ENSLib.json +10 -0
  72. package/artifacts/contracts/libs/v0.8.x/ENSLib.sol/IUniversalResolver.json +45 -0
  73. package/artifacts/contracts/libs/v0.8.x/EnumerableSetUint16.sol/EnumerableSetUint16.json +10 -0
  74. package/artifacts/contracts/libs/v0.8.x/FeistelWalkLib.sol/FeistelWalkLib.json +10 -0
  75. package/artifacts/contracts/libs/v0.8.x/ImmutableUint16Array.sol/ImmutableUint16Array.json +10 -0
  76. package/artifacts/contracts/libs/v0.8.x/V3EngineLib.sol/V3EngineLib.json +163 -0
  77. package/artifacts/contracts/libs/v0.8.x/V3FlexLib.sol/V3FlexLib.json +2 -2
  78. package/artifacts/contracts/libs/v0.8.x/V3TransferHookLib.sol/V3TransferHookLib.json +79 -0
  79. package/artifacts/contracts/libs/v0.8.x/minter-libs/MaxInvocationsLib.sol/MaxInvocationsLib.json +2 -2
  80. package/artifacts/contracts/libs/v0.8.x/minter-libs/OnChainAllowlistLib.sol/OnChainAllowlistLib.json +10 -0
  81. package/artifacts/contracts/libs/v0.8.x/minter-libs/PolyptychLib.sol/PolyptychLib.json +2 -2
  82. package/artifacts/contracts/libs/v0.8.x/minter-libs/RAMLib.sol/RAMLib.json +2 -2
  83. package/artifacts/contracts/libs/v0.8.x/minter-libs/SEALib.sol/SEALib.json +2 -2
  84. package/artifacts/contracts/libs/v0.8.x/minter-libs/SettlementExpLib.sol/SettlementExpLib.json +2 -2
  85. package/artifacts/contracts/libs/v0.8.x/minter-libs/SplitFundsLib.sol/SplitFundsLib.json +2 -2
  86. package/artifacts/contracts/minter-suite/MinterFilter/MinterFilterV1.sol/MinterFilterV1.json +2 -2
  87. package/artifacts/contracts/minter-suite/MinterFilter/MinterFilterV2.sol/MinterFilterV2.json +2 -2
  88. package/artifacts/contracts/minter-suite/Minters/MinterDAExpHolderV5.sol/MinterDAExpHolderV5.json +2 -2
  89. package/artifacts/contracts/minter-suite/Minters/MinterDAExpSettlementV3.sol/MinterDAExpSettlementV3.json +2 -2
  90. package/artifacts/contracts/minter-suite/Minters/MinterDAExpV5.sol/MinterDAExpV5.json +2 -2
  91. package/artifacts/contracts/minter-suite/Minters/MinterDALinHolderV5.sol/MinterDALinHolderV5.json +2 -2
  92. package/artifacts/contracts/minter-suite/Minters/MinterDALinV5.sol/MinterDALinV5.json +2 -2
  93. package/artifacts/contracts/minter-suite/Minters/MinterMinPriceMerkleV0.sol/MinterMinPriceMerkleV0.json +2 -2
  94. package/artifacts/contracts/minter-suite/Minters/MinterMinPriceV0.sol/MinterMinPriceV0.json +2 -2
  95. package/artifacts/contracts/minter-suite/Minters/MinterRAMV0.sol/MinterRAMV0.json +2 -2
  96. package/artifacts/contracts/minter-suite/Minters/MinterSEAV1.sol/MinterSEAV1.json +2 -2
  97. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceERC20V5.sol/MinterSetPriceERC20V5.json +2 -2
  98. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceHolderV5.sol/MinterSetPriceHolderV5.json +2 -2
  99. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceMerkleV5.sol/MinterSetPriceMerkleV5.json +2 -2
  100. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceOnChainAllowV0.sol/MinterSetPriceOnChainAllowV0.json +522 -0
  101. package/artifacts/contracts/minter-suite/Minters/MinterSetPricePolyptychERC20V5.sol/MinterSetPricePolyptychERC20V5.json +2 -2
  102. package/artifacts/contracts/minter-suite/Minters/MinterSetPricePolyptychV5.sol/MinterSetPricePolyptychV5.json +2 -2
  103. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceTieredAllowV1.sol/MinterSetPriceTieredAllowV1.json +715 -0
  104. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceV5.sol/MinterSetPriceV5.json +2 -2
  105. package/artifacts/contracts/minter-suite/Minters/MinterSlidingScaleV0.sol/MinterSlidingScaleV0.json +431 -0
  106. package/artifacts/contracts/minter-suite/Minters/one-off/ClaimMinter.sol/ClaimMinter.json +502 -0
  107. package/artifacts/contracts/minter-suite/Minters/one-off/MinterSetPriceTieredOnChainAllowV0.sol/MinterSetPriceTieredOnChainAllowV0.json +673 -0
  108. package/artifacts/contracts/minter-suite/Minters/one-off/MinterSetPriceV5_SingleCore.sol/MinterSetPriceV5_SingleCore.json +2 -2
  109. package/artifacts/contracts/minter-suite/Minters/one-off/SeaDropXArtBlocksShim.sol/SeaDropXArtBlocksShim.json +6 -19
  110. package/artifacts/contracts/mock/BytecodeV2TextCR_DMock.sol/BytecodeV2TextCR_DMock.json +2 -2
  111. package/artifacts/contracts/mock/DummySharedMinter.sol/DummySharedMinter.json +2 -2
  112. package/artifacts/contracts/mock/ENSLibMock.sol/ENSLibMock.json +30 -0
  113. package/artifacts/contracts/mock/EnumerableSetUint16Mock.sol/EnumerableSetUint16Mock.json +146 -0
  114. package/artifacts/contracts/mock/FeistelWalkLibMock.sol/FeistelWalkLibMock.json +142 -0
  115. package/artifacts/contracts/mock/ForceSendMock.sol/ForceSendMock.json +2 -2
  116. package/artifacts/contracts/mock/GenArt721CoreV3_Engine_IncorrectCoreType.sol/GenArt721CoreV3_Engine_IncorrectCoreType.json +2 -2
  117. package/artifacts/contracts/mock/ImmutableUint16ArrayMock.sol/ImmutableUint16ArrayMock.json +89 -0
  118. package/artifacts/contracts/mock/MockAdminACLV0_PROHIBITION.sol/MockAdminACLV0Events_PROHIBITION.json +2 -2
  119. package/artifacts/contracts/mock/MockGenArt721V3Core.sol/MockGenArt721V3Core.json +490 -0
  120. package/artifacts/contracts/mock/MockPMP.sol/MockPMP.json +523 -0
  121. package/artifacts/contracts/mock/MockPMPAugmentHook.sol/MockPMPAugmentHook.json +2 -2
  122. package/artifacts/contracts/mock/MockPMPConfigureHook.sol/MockPMPConfigureHook.json +2 -2
  123. package/artifacts/contracts/mock/MockTransferHook.sol/MockTransferHook.json +453 -0
  124. package/artifacts/contracts/mock/MockTransferHookTestHelpers.sol/MockBatchTransferrer.json +39 -0
  125. package/artifacts/contracts/mock/MockTransferHookTestHelpers.sol/MockForwardingERC721Receiver.json +71 -0
  126. package/artifacts/contracts/mock/MockTransferHookTestHelpers.sol/MockSpoofingCore.json +94 -0
  127. package/artifacts/contracts/mock/RandomizerV2_NoAssignMock.sol/RandomizerV2_NoAssignMock.json +2 -2
  128. package/artifacts/contracts/mock/ReentrancyBatchMockShared.sol/IBatchMinter.json +64 -0
  129. package/artifacts/contracts/mock/ReentrancyBatchMockShared.sol/ReentrancyBatchMockShared.json +113 -0
  130. package/artifacts/contracts/mock/RelayExecutorTestHelper.sol/MockTarget.json +74 -0
  131. package/artifacts/contracts/mock/RelayExecutorTestHelper.sol/RelayExecutorPartialRevertsTestHelper.json +138 -0
  132. package/artifacts/contracts/mock/RelayExecutorTestHelper.sol/RelayExecutorTestHelper.json +119 -0
  133. package/artifacts/contracts/randomizer/deprecated/PolyptychRandomizerV0.sol/BasicPolyptychRandomizerV0.json +2 -2
  134. package/artifacts/contracts/randomizer/deprecated/RandomizerV2.sol/BasicRandomizerV2.json +2 -2
  135. package/artifacts/contracts/randomizer/shared/SharedRandomizerV0.sol/SharedRandomizerV0.json +2 -2
  136. package/artifacts/contracts/relay/RelayExecutor.sol/RelayExecutor.json +101 -0
  137. package/artifacts/contracts/relay/RelayExecutorPartialReverts.sol/RelayExecutorPartialReverts.json +120 -0
  138. package/artifacts/contracts/royalty-registry/GenArt721RoyaltyOverrideSplits.sol/GenArt721RoyaltyOverrideSplits.json +263 -0
  139. package/artifacts/contracts/utils/MintMulticallUtil.sol/IMinterSetPriceV5.json +40 -0
  140. package/artifacts/contracts/utils/MintMulticallUtil.sol/MintMulticallUtil.json +163 -0
  141. package/artifacts/contracts/web3call/PMPV0.sol/PMPV0.json +9 -3
  142. package/artifacts/contracts/web3call/PMPV1.sol/PMPV1.json +648 -0
  143. package/artifacts/contracts/web3call/augment-hooks/InjectBaseGasFee.sol/InjectBaseGasFee.json +2 -2
  144. package/artifacts/contracts/web3call/augment-hooks/InjectBlockHeight.sol/InjectBlockHeight.json +83 -0
  145. package/artifacts/contracts/web3call/augment-hooks/InjectBlockHeightAndArtistProjectOverrides.sol/InjectBlockHeightAndArtistProjectOverrides.json +226 -0
  146. package/artifacts/contracts/web3call/augment-hooks/InjectBlockHeightAndNumOwnedProjectTokens.sol/InjectBlockHeightAndNumOwnedProjectTokens.json +182 -0
  147. package/artifacts/contracts/web3call/augment-hooks/InjectBlockHeightProjectInvocationsAndArtistProjectOverrides.sol/InjectBlockHeightProjectInvocationsAndArtistProjectOverrides.json +226 -0
  148. package/artifacts/contracts/web3call/augment-hooks/InjectBlockTimestamp.sol/InjectBlockTimestamp.json +83 -0
  149. package/artifacts/contracts/web3call/augment-hooks/InjectBytesPerToken.sol/InjectBytesPerToken.json +358 -0
  150. package/artifacts/contracts/web3call/augment-hooks/InjectChromieSquiggleFloorPrice.sol/InjectChromieSquiggleFloorPrice.json +2 -2
  151. package/artifacts/contracts/web3call/augment-hooks/InjectIsNounsDaoMember.sol/InjectIsNounsDaoMember.json +2 -2
  152. package/artifacts/contracts/web3call/augment-hooks/InjectIsProjectFullyMinted.sol/InjectIsProjectFullyMinted.json +2 -2
  153. package/artifacts/contracts/web3call/augment-hooks/InjectPolyptychTokenHash.sol/InjectPolyptychTokenHash.json +2 -2
  154. package/artifacts/contracts/web3call/augment-hooks/InjectTokenHashSeed.sol/InjectTokenHashSeed.json +2 -2
  155. package/artifacts/contracts/web3call/augment-hooks/InjectTokenOwner.sol/InjectTokenOwner.json +2 -2
  156. package/artifacts/contracts/web3call/augment-hooks/InjectTokenOwnerEthBalance.sol/InjectTokenOwnerEthBalance.json +2 -2
  157. package/artifacts/contracts/web3call/augment-hooks/InjectUSDCTotalSupply.sol/InjectUSDCTotalSupply.json +2 -2
  158. package/artifacts/contracts/web3call/augment-hooks/SRHooks.sol/SRHooks.json +899 -0
  159. package/artifacts/contracts/web3call/combined-hooks/LiftHooks.sol/IGenArt721V0_Minimal.json +30 -0
  160. package/artifacts/contracts/web3call/combined-hooks/LiftHooks.sol/IRelic.json +35 -0
  161. package/artifacts/contracts/web3call/combined-hooks/LiftHooks.sol/LiftHooks.json +256 -0
  162. package/artifacts/contracts/web3call/configure-hooks/{abstractPMPConfigureHook.sol → AbstractPMPConfigureHook.sol}/AbstractPMPConfigureHook.json +1 -1
  163. package/artifacts/contracts/web3call/configure-hooks/PMPConfigureLockHook.sol/PMPConfigureLockHook.json +195 -0
  164. package/contracts/AdminACLV0RoyaltyRegistry.sol +142 -0
  165. package/contracts/DependencyRegistryV0.sol +143 -13
  166. package/contracts/GenArt721CoreV3_Curated.sol +1 -1
  167. package/contracts/GenArt721CoreV3_Curated_Flex.sol +173 -0
  168. package/contracts/GenArt721CoreV3_Explorations_Flex.sol +159 -0
  169. package/contracts/engine/V3/EngineFactoryV0.sol +20 -1
  170. package/contracts/engine/V3/GenArt721CoreV3_Engine.sol +286 -299
  171. package/contracts/engine/V3/GenArt721CoreV3_Engine_Flex.sol +292 -301
  172. package/contracts/engine/V3/transfer-hooks/AbstractTransferHook.sol +101 -0
  173. package/contracts/engine/V3/transfer-hooks/OwnerHistoryTransferHook.sol +291 -0
  174. package/contracts/generator/GenArt721GeneratorV0.sol +145 -47
  175. package/contracts/helpers/ERC1967ProxyImport.sol +5 -0
  176. package/contracts/interfaces/v0.8.x/IArtblocksRoyaltyOverride.sol +1 -1
  177. package/contracts/interfaces/v0.8.x/IClaimMinter.sol +70 -0
  178. package/contracts/interfaces/v0.8.x/IDependencyRegistryV0.sol +95 -0
  179. package/contracts/interfaces/v0.8.x/IEngineFactoryV0.sol +15 -0
  180. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Base.sol +21 -2
  181. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine.sol +72 -0
  182. package/contracts/interfaces/v0.8.x/IOwnerHistoryTransferHook.sol +119 -0
  183. package/contracts/interfaces/v0.8.x/IPMPV0.sol +5 -3
  184. package/contracts/interfaces/v0.8.x/ISRHooks.sol +229 -0
  185. package/contracts/interfaces/v0.8.x/ISeaDropShimForContract.sol +0 -6
  186. package/contracts/interfaces/v0.8.x/ISharedMinterTieredAllowV0.sol +69 -0
  187. package/contracts/interfaces/v0.8.x/ITransferHook.sol +48 -0
  188. package/contracts/libs/v0.8.x/DependencyRegistryStorageLib.sol +12 -0
  189. package/contracts/libs/v0.8.x/ENSLib.sol +85 -0
  190. package/contracts/libs/v0.8.x/EnumerableSetUint16.sol +429 -0
  191. package/contracts/libs/v0.8.x/FeistelWalkLib.sol +221 -0
  192. package/contracts/libs/v0.8.x/ImmutableUint16Array.sol +201 -0
  193. package/contracts/libs/v0.8.x/V3EngineLib.sol +490 -0
  194. package/contracts/libs/v0.8.x/V3TransferHookLib.sol +251 -0
  195. package/contracts/libs/v0.8.x/minter-libs/OnChainAllowlistLib.sol +165 -0
  196. package/contracts/minter-suite/Minters/MinterSetPriceOnChainAllowV0.sol +632 -0
  197. package/contracts/minter-suite/Minters/MinterSetPriceTieredAllowV1.sol +871 -0
  198. package/contracts/minter-suite/Minters/MinterSlidingScaleV0.sol +493 -0
  199. package/contracts/minter-suite/Minters/one-off/ClaimMinter.sol +595 -0
  200. package/contracts/minter-suite/Minters/one-off/MinterSetPriceTieredOnChainAllowV0.sol +894 -0
  201. package/contracts/minter-suite/Minters/one-off/SeaDropXArtBlocksShim.sol +59 -41
  202. package/contracts/mock/ENSLibMock.sol +25 -0
  203. package/contracts/mock/EnumerableSetUint16Mock.sol +88 -0
  204. package/contracts/mock/FeistelWalkLibMock.sol +81 -0
  205. package/contracts/mock/ImmutableUint16ArrayMock.sol +62 -0
  206. package/contracts/mock/MockGenArt721V3Core.sol +416 -0
  207. package/contracts/mock/MockPMP.sol +287 -0
  208. package/contracts/mock/MockTransferHook.sol +160 -0
  209. package/contracts/mock/MockTransferHookTestHelpers.sol +96 -0
  210. package/contracts/mock/ReentrancyBatchMockShared.sol +53 -0
  211. package/contracts/mock/RelayExecutorTestHelper.sol +44 -0
  212. package/contracts/relay/RelayExecutor.sol +61 -0
  213. package/contracts/relay/RelayExecutorPartialReverts.sol +79 -0
  214. package/contracts/royalty-registry/GenArt721RoyaltyOverrideSplits.sol +130 -0
  215. package/contracts/utils/MintMulticallUtil.sol +103 -0
  216. package/contracts/web3call/PMPV0.sol +92 -98
  217. package/contracts/web3call/PMPV1.sol +1204 -0
  218. package/contracts/web3call/augment-hooks/AbstractPMPAugmentHook.sol +1 -1
  219. package/contracts/web3call/augment-hooks/InjectBaseGasFee.sol +1 -1
  220. package/contracts/web3call/augment-hooks/InjectBlockHeight.sol +57 -0
  221. package/contracts/web3call/augment-hooks/InjectBlockHeightAndArtistProjectOverrides.sol +310 -0
  222. package/contracts/web3call/augment-hooks/InjectBlockHeightAndNumOwnedProjectTokens.sol +141 -0
  223. package/contracts/web3call/augment-hooks/InjectBlockHeightProjectInvocationsAndArtistProjectOverrides.sol +326 -0
  224. package/contracts/web3call/augment-hooks/InjectBlockTimestamp.sol +57 -0
  225. package/contracts/web3call/augment-hooks/InjectBytesPerToken.sol +279 -0
  226. package/contracts/web3call/augment-hooks/InjectIsProjectFullyMinted.sol +1 -1
  227. package/contracts/web3call/augment-hooks/InjectTokenHashSeed.sol +1 -1
  228. package/contracts/web3call/augment-hooks/InjectTokenOwner.sol +1 -1
  229. package/contracts/web3call/augment-hooks/InjectTokenOwnerEthBalance.sol +1 -1
  230. package/contracts/web3call/augment-hooks/SRHooks.sol +1722 -0
  231. package/contracts/web3call/combined-hooks/LiftHooks.sol +304 -0
  232. package/contracts/web3call/configure-hooks/{abstractPMPConfigureHook.sol → AbstractPMPConfigureHook.sol} +1 -1
  233. package/contracts/web3call/configure-hooks/PMPConfigureLockHook.sol +107 -0
  234. package/package.json +40 -25
@@ -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";
@@ -18,6 +19,8 @@ import {IERC2981} from "@openzeppelin-5.0/contracts/interfaces/IERC2981.sol";
18
19
  import "../../libs/v0.8.x/ERC721_PackedHashSeedV1.sol";
19
20
  import {BytecodeStorageWriter, BytecodeStorageReader} from "../../libs/v0.8.x/BytecodeStorageV2.sol";
20
21
  import "../../libs/v0.8.x/Bytes32Strings.sol";
22
+ import {V3EngineLib} from "../../libs/v0.8.x/V3EngineLib.sol";
23
+ import {V3TransferHookLib} from "../../libs/v0.8.x/V3TransferHookLib.sol";
21
24
 
22
25
  /**
23
26
  * @title Art Blocks Engine ERC-721 core contract, V3.
@@ -78,6 +81,23 @@ import "../../libs/v0.8.x/Bytes32Strings.sol";
78
81
  * current number of invocations, and less than current project maximum
79
82
  * invocations)
80
83
  * - updateProjectBaseURI (controlling the base URI for tokens in the project)
84
+ * - lockProjectTransferHook (one-way. Requires the caller to pass the hook
85
+ * they expect to lock in, so a concurrent configure call cannot cause an
86
+ * unintended hook to be locked. Locking while the hook is address(0)
87
+ * forever forbids assigning a transfer hook. If the hook is address(0) when
88
+ * the four-week project metadata lock elapses, it is auto-locked at zero —
89
+ * restoring today's transfer security profile with no extra action. If a
90
+ * hook is already set at auto-lock, it remains configurable until this is
91
+ * called.)
92
+ * ----------------------------------------------------------------------------
93
+ * The following functions are restricted to either the Artist address or
94
+ * the Admin ACL contract. After the four-week project metadata lock, they
95
+ * remain available only if a transfer hook is already set; if the hook is
96
+ * address(0) at auto-lock, it can never be assigned. Independently, the
97
+ * artist may one-way lockProjectTransferHook at any time:
98
+ * - configureProjectTransferHook (WARNING: a reverting hook bricks transfers
99
+ * and mints for the project. A non-zero hook may execute arbitrary code on
100
+ * every transfer. Prefer locking at address(0) if no hook is intended.)
81
101
  * ----------------------------------------------------------------------------
82
102
  * The following function is restricted to either the Admin ACL contract, or
83
103
  * the Artist address if the core contract owner has renounced ownership:
@@ -99,6 +119,9 @@ import "../../libs/v0.8.x/Bytes32Strings.sol";
99
119
  * ----------------------------------------------------------------------------
100
120
  * Additional admin and artist privileged roles may be described on minters,
101
121
  * registries, and other contracts that may interact with this core contract.
122
+ * @dev External libraries (`V3EngineLib`, `V3TransferHookLib`) are used so
123
+ * Engine and Engine Flex share one implementation of shared logic while both
124
+ * remain under the 24KB bytecode size limit.
102
125
  */
103
126
  contract GenArt721CoreV3_Engine is
104
127
  ERC721_PackedHashSeedV1,
@@ -113,12 +136,10 @@ contract GenArt721CoreV3_Engine is
113
136
  using BytecodeStorageWriter for bytes;
114
137
  using Bytes32Strings for bytes32;
115
138
  using Strings for uint256;
116
- using Strings for address;
117
139
  uint256 constant ONE_HUNDRED = 100;
118
140
  uint256 constant ONE_MILLION = 1_000_000;
119
141
  uint24 constant ONE_MILLION_UINT24 = 1_000_000;
120
142
  uint256 constant FOUR_WEEKS_IN_SECONDS = 2_419_200;
121
- uint8 constant AT_CHARACTER_CODE = uint8(bytes1("@")); // 0x40
122
143
 
123
144
  // numeric constants
124
145
  uint256 constant MAX_PROVIDER_SECONDARY_SALES_BPS = 10000; // 10_000 BPS = 100%
@@ -267,7 +288,7 @@ contract GenArt721CoreV3_Engine is
267
288
  bool public allowArtistProjectActivation;
268
289
 
269
290
  /// version & type of this core contract
270
- bytes32 constant CORE_VERSION = "v3.2.4";
291
+ bytes32 constant CORE_VERSION = "v3.3.0";
271
292
 
272
293
  function coreVersion() external pure virtual returns (string memory) {
273
294
  return CORE_VERSION.toString();
@@ -292,6 +313,12 @@ contract GenArt721CoreV3_Engine is
292
313
  // bytecode storage reader contract; may be universal or specific version reader contract
293
314
  IBytecodeStorageReader_Base public bytecodeStorageReaderContract;
294
315
 
316
+ /// per-project transfer hook configuration and reentrancy flag
317
+ /// @dev appended to the end of this contract's storage; new state
318
+ /// variables must also be appended here, never inserted above, so that
319
+ /// existing storage slot assignments are never shifted
320
+ V3TransferHookLib.Layout private _transferHookLayout;
321
+
295
322
  /**
296
323
  * @dev This constructor sets the owner to a non-functional address as a formality.
297
324
  * It is only ever ran on the implementation contract. The `Ownable` constructor is
@@ -365,6 +392,23 @@ contract GenArt721CoreV3_Engine is
365
392
  }
366
393
  }
367
394
 
395
+ function _onlyArtistIfUnlockedElseAdminACL(
396
+ uint256 _projectId,
397
+ bytes4 _selector
398
+ ) internal {
399
+ if (_projectUnlocked(_projectId)) {
400
+ if (
401
+ msg.sender != _projectIdToFinancials[_projectId].artistAddress
402
+ ) {
403
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
404
+ }
405
+ } else {
406
+ if (!adminACLAllowed(msg.sender, address(this), _selector)) {
407
+ revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
408
+ }
409
+ }
410
+ }
411
+
368
412
  /**
369
413
  * This modifier allows the artist of a project to call a function if the
370
414
  * owner of the contract has renounced ownership. This is to allow the
@@ -490,10 +534,24 @@ contract GenArt721CoreV3_Engine is
490
534
  // token hash is updated by the randomizer contract on V3
491
535
  randomizerContract.assignTokenHash(thisTokenId);
492
536
 
537
+ // mint transfer hook after hash assignment so the hook can read
538
+ // tokenIdToHash. `_update` skips mint dispatch (from == address(0)).
539
+ _dispatchTransferHook({
540
+ from: address(0),
541
+ to: _to,
542
+ tokenId: thisTokenId,
543
+ operator: _by
544
+ });
545
+
493
546
  // Do not need to also log `projectId` in event, as the `projectId` for
494
547
  // a given token can be derived from the `tokenId` with:
495
548
  // projectId = tokenId / 1_000_000
496
- emit Mint(_to, thisTokenId);
549
+ bytes12 hashSeed = _ownersAndHashSeeds[thisTokenId].hashSeed;
550
+ emit Mint(
551
+ _to,
552
+ thisTokenId,
553
+ hashSeed != 0 ? keccak256(abi.encode(hashSeed)) : bytes32(0)
554
+ );
497
555
 
498
556
  return thisTokenId;
499
557
  }
@@ -846,98 +904,20 @@ contract GenArt721CoreV3_Engine is
846
904
  _onlyValidProjectId(_projectId);
847
905
  _onlyArtist(_projectId);
848
906
  _onlyNonZeroAddress(_artistAddress);
849
- ProjectFinance storage projectFinance = _projectIdToFinancials[
850
- _projectId
851
- ];
852
- // checks
853
- if (
854
- _additionalPayeePrimarySalesPercentage > ONE_HUNDRED ||
855
- _additionalPayeeSecondarySalesPercentage > ONE_HUNDRED
856
- ) {
857
- revert GenArt721Error(ErrorCodes.MaxOf100Percent);
858
- }
859
- if (
860
- _additionalPayeePrimarySalesPercentage > 0 &&
861
- _additionalPayeePrimarySales == address(0)
862
- ) {
863
- revert GenArt721Error(ErrorCodes.PrimaryPayeeIsZeroAddress);
864
- }
865
- if (
866
- _additionalPayeeSecondarySalesPercentage > 0 &&
867
- _additionalPayeeSecondarySales == address(0)
868
- ) {
869
- revert GenArt721Error(ErrorCodes.SecondaryPayeeIsZeroAddress);
870
- }
871
- // effects
872
- // emit event for off-chain indexing
873
- // note: always emit a proposal event, even in the pathway of
874
- // automatic approval, to simplify indexing expectations
875
- emit ProposedArtistAddressesAndSplits(
876
- _projectId,
877
- _artistAddress,
878
- _additionalPayeePrimarySales,
879
- _additionalPayeePrimarySalesPercentage,
880
- _additionalPayeeSecondarySales,
881
- _additionalPayeeSecondarySalesPercentage
882
- );
883
- // automatically accept if no proposed addresses modifications, or if
884
- // the proposal only removes payee addresses, or if contract is set to
885
- // always auto-approve.
886
- // store proposal hash on-chain, only if not automatic accept
887
- bool automaticAccept = autoApproveArtistSplitProposals;
888
- if (!automaticAccept) {
889
- // block scope to avoid stack too deep error
890
- bool artistUnchanged = _artistAddress ==
891
- projectFinance.artistAddress;
892
- bool additionalPrimaryUnchangedOrRemoved = (_additionalPayeePrimarySales ==
893
- projectFinance.additionalPayeePrimarySales) ||
894
- (_additionalPayeePrimarySales == address(0));
895
- bool additionalSecondaryUnchangedOrRemoved = (_additionalPayeeSecondarySales ==
896
- projectFinance.additionalPayeeSecondarySales) ||
897
- (_additionalPayeeSecondarySales == address(0));
898
- automaticAccept =
899
- artistUnchanged &&
900
- additionalPrimaryUnchangedOrRemoved &&
901
- additionalSecondaryUnchangedOrRemoved;
902
- }
903
- if (automaticAccept) {
904
- // clear any previously proposed values
905
- proposedArtistAddressesAndSplitsHash[_projectId] = bytes32(0);
906
-
907
- // update storage
908
- // artist address can change during automatic accept if
909
- // autoApproveArtistSplitProposals is true
910
- projectFinance.artistAddress = _artistAddress;
911
- projectFinance
912
- .additionalPayeePrimarySales = _additionalPayeePrimarySales;
913
- // safe to cast as uint8 as max is 100%, max uint8 is 255
914
- projectFinance.additionalPayeePrimarySalesPercentage = uint8(
915
- _additionalPayeePrimarySalesPercentage
916
- );
917
- projectFinance
918
- .additionalPayeeSecondarySales = _additionalPayeeSecondarySales;
919
- // safe to cast as uint8 as max is 100%, max uint8 is 255
920
- projectFinance.additionalPayeeSecondarySalesPercentage = uint8(
921
- _additionalPayeeSecondarySalesPercentage
922
- );
923
-
924
- // assign project's splitter
925
- // @dev only call after all previous storage updates
926
- _assignSplitter(_projectId);
927
-
928
- // emit event for off-chain indexing
929
- emit AcceptedArtistAddressesAndSplits(_projectId);
930
- } else {
931
- proposedArtistAddressesAndSplitsHash[_projectId] = keccak256(
932
- abi.encode(
933
- _artistAddress,
934
- _additionalPayeePrimarySales,
935
- _additionalPayeePrimarySalesPercentage,
936
- _additionalPayeeSecondarySales,
937
- _additionalPayeeSecondarySalesPercentage
938
- )
939
- );
940
- }
907
+ V3EngineLib.proposeArtistPaymentAddressesAndSplits({
908
+ proposal: V3EngineLib.ArtistSplitProposal({
909
+ projectId: _projectId,
910
+ artistAddress: _artistAddress,
911
+ additionalPayeePrimarySales: _additionalPayeePrimarySales,
912
+ additionalPayeePrimarySalesPercentage: _additionalPayeePrimarySalesPercentage,
913
+ additionalPayeeSecondarySales: _additionalPayeeSecondarySales,
914
+ additionalPayeeSecondarySalesPercentage: _additionalPayeeSecondarySalesPercentage
915
+ }),
916
+ projectFinance: _projectIdToFinancials[_projectId],
917
+ proposedHashes: proposedArtistAddressesAndSplitsHash,
918
+ autoApprove: autoApproveArtistSplitProposals,
919
+ splitProvider: splitProvider
920
+ });
941
921
  }
942
922
 
943
923
  /**
@@ -979,45 +959,19 @@ contract GenArt721CoreV3_Engine is
979
959
  this.adminAcceptArtistAddressesAndSplits.selector
980
960
  );
981
961
  _onlyNonZeroAddress(_artistAddress);
982
- // checks
983
- if (
984
- proposedArtistAddressesAndSplitsHash[_projectId] !=
985
- keccak256(
986
- abi.encode(
987
- _artistAddress,
988
- _additionalPayeePrimarySales,
989
- _additionalPayeePrimarySalesPercentage,
990
- _additionalPayeeSecondarySales,
991
- _additionalPayeeSecondarySalesPercentage
992
- )
993
- )
994
- ) {
995
- revert GenArt721Error(ErrorCodes.MustMatchArtistProposal);
996
- }
997
- // effects
998
- ProjectFinance storage projectFinance = _projectIdToFinancials[
999
- _projectId
1000
- ];
1001
- projectFinance.artistAddress = _artistAddress;
1002
- projectFinance
1003
- .additionalPayeePrimarySales = _additionalPayeePrimarySales;
1004
- projectFinance.additionalPayeePrimarySalesPercentage = uint8(
1005
- _additionalPayeePrimarySalesPercentage
1006
- );
1007
- projectFinance
1008
- .additionalPayeeSecondarySales = _additionalPayeeSecondarySales;
1009
- projectFinance.additionalPayeeSecondarySalesPercentage = uint8(
1010
- _additionalPayeeSecondarySalesPercentage
1011
- );
1012
- // clear proposed values
1013
- proposedArtistAddressesAndSplitsHash[_projectId] = bytes32(0);
1014
-
1015
- // assign project's splitter
1016
- // @dev only call after all previous storage updates
1017
- _assignSplitter(_projectId);
1018
-
1019
- // emit event for off-chain indexing
1020
- emit AcceptedArtistAddressesAndSplits(_projectId);
962
+ V3EngineLib.adminAcceptArtistAddressesAndSplits({
963
+ proposal: V3EngineLib.ArtistSplitProposal({
964
+ projectId: _projectId,
965
+ artistAddress: _artistAddress,
966
+ additionalPayeePrimarySales: _additionalPayeePrimarySales,
967
+ additionalPayeePrimarySalesPercentage: _additionalPayeePrimarySalesPercentage,
968
+ additionalPayeeSecondarySales: _additionalPayeeSecondarySales,
969
+ additionalPayeeSecondarySalesPercentage: _additionalPayeeSecondarySalesPercentage
970
+ }),
971
+ projectFinance: _projectIdToFinancials[_projectId],
972
+ proposedHashes: proposedArtistAddressesAndSplitsHash,
973
+ splitProvider: splitProvider
974
+ });
1021
975
  }
1022
976
 
1023
977
  /**
@@ -1158,25 +1112,10 @@ contract GenArt721CoreV3_Engine is
1158
1112
  uint256 _projectId,
1159
1113
  string memory _projectArtistName
1160
1114
  ) external {
1161
- // if unlocked, only artist may update, if locked, only admin may update
1162
- // @dev valid project checked in _projectUnlocked function
1163
- if (_projectUnlocked(_projectId)) {
1164
- if (
1165
- msg.sender != _projectIdToFinancials[_projectId].artistAddress
1166
- ) {
1167
- revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1168
- }
1169
- } else {
1170
- if (
1171
- !adminACLAllowed(
1172
- msg.sender,
1173
- address(this),
1174
- this.updateProjectArtistName.selector
1175
- )
1176
- ) {
1177
- revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1178
- }
1179
- }
1115
+ _onlyArtistIfUnlockedElseAdminACL(
1116
+ _projectId,
1117
+ this.updateProjectArtistName.selector
1118
+ );
1180
1119
  _onlyNonEmptyString(_projectArtistName);
1181
1120
  projects[_projectId].artist = _projectArtistName;
1182
1121
  emit ProjectUpdated(
@@ -1283,24 +1222,10 @@ contract GenArt721CoreV3_Engine is
1283
1222
  string memory _projectDescription
1284
1223
  ) external {
1285
1224
  // checks
1286
- // if unlocked, only artist may update, if locked, only admin may update
1287
- if (_projectUnlocked(_projectId)) {
1288
- if (
1289
- msg.sender != _projectIdToFinancials[_projectId].artistAddress
1290
- ) {
1291
- revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1292
- }
1293
- } else {
1294
- if (
1295
- !adminACLAllowed(
1296
- msg.sender,
1297
- address(this),
1298
- this.updateProjectDescription.selector
1299
- )
1300
- ) {
1301
- revert GenArt721Error(ErrorCodes.OnlyArtistOrAdminIfLocked);
1302
- }
1303
- }
1225
+ _onlyArtistIfUnlockedElseAdminACL(
1226
+ _projectId,
1227
+ this.updateProjectDescription.selector
1228
+ );
1304
1229
  // effects
1305
1230
  // store description in contract bytecode, replacing reference address from
1306
1231
  // the old storage description with the newly created one
@@ -1544,17 +1469,9 @@ contract GenArt721CoreV3_Engine is
1544
1469
  _projectId,
1545
1470
  this.updateProjectScriptType.selector
1546
1471
  );
1547
- Project storage project = projects[_projectId];
1548
1472
  // require exactly one @ symbol in _scriptTypeAndVersion
1549
- if (
1550
- !_scriptTypeAndVersion.containsExactCharacterQty(
1551
- AT_CHARACTER_CODE,
1552
- uint8(1)
1553
- )
1554
- ) {
1555
- revert GenArt721Error(ErrorCodes.ScriptTypeAndVersionFormat);
1556
- }
1557
- project.scriptTypeAndVersion = _scriptTypeAndVersion;
1473
+ V3EngineLib.validateScriptTypeAndVersion(_scriptTypeAndVersion);
1474
+ projects[_projectId].scriptTypeAndVersion = _scriptTypeAndVersion;
1558
1475
  emit ProjectUpdated(
1559
1476
  _projectId,
1560
1477
  bytes32(uint256(ProjectUpdatedFields.FIELD_PROJECT_SCRIPT_TYPE))
@@ -1579,35 +1496,7 @@ contract GenArt721CoreV3_Engine is
1579
1496
  );
1580
1497
  _onlyNonEmptyString(_aspectRatio);
1581
1498
  // Perform more detailed input validation for aspect ratio.
1582
- bytes memory aspectRatioBytes = bytes(_aspectRatio);
1583
- uint256 bytesLength = aspectRatioBytes.length;
1584
- if (bytesLength > 11) {
1585
- revert GenArt721Error(ErrorCodes.AspectRatioTooLong);
1586
- }
1587
- bool hasSeenDecimalSeparator = false;
1588
- bool hasSeenNumber = false;
1589
- for (uint256 i; i < bytesLength; i++) {
1590
- bytes1 character = aspectRatioBytes[i];
1591
- // Allow as many #s as desired.
1592
- if (character >= 0x30 && character <= 0x39) {
1593
- // 9-0
1594
- // We need to ensure there is at least 1 `9-0` occurrence.
1595
- hasSeenNumber = true;
1596
- continue;
1597
- }
1598
- if (character == 0x2E) {
1599
- // .
1600
- // Allow no more than 1 `.` occurrence.
1601
- if (!hasSeenDecimalSeparator) {
1602
- hasSeenDecimalSeparator = true;
1603
- continue;
1604
- }
1605
- }
1606
- revert GenArt721Error(ErrorCodes.AspectRatioImproperFormat);
1607
- }
1608
- if (!hasSeenNumber) {
1609
- revert GenArt721Error(ErrorCodes.AspectRatioNoNumbers);
1610
- }
1499
+ V3EngineLib.validateAspectRatio(_aspectRatio);
1611
1500
 
1612
1501
  projects[_projectId].aspectRatio = _aspectRatio;
1613
1502
  emit ProjectUpdated(
@@ -1637,6 +1526,76 @@ contract GenArt721CoreV3_Engine is
1637
1526
  );
1638
1527
  }
1639
1528
 
1529
+ /**
1530
+ * @notice Set or clear the transfer hook for project `_projectId`.
1531
+ * Artist or Admin ACL. Reverts if the configuration is locked: either the
1532
+ * artist called `lockProjectTransferHook`, or the four-week project
1533
+ * metadata lock has elapsed while the hook is `address(0)`. After that
1534
+ * auto-lock, a hook that is already set remains configurable until the
1535
+ * artist calls `lockProjectTransferHook`. Clearing to `address(0)` after
1536
+ * auto-lock permanently forbids assigning a hook again.
1537
+ * WARNING: A reverting hook bricks transfers and mints for every token in
1538
+ * the project. A hook may execute arbitrary code, and a mutable proxy hook
1539
+ * can change behavior after it is set. Artists who do not want a hook may
1540
+ * leave it unset until auto-lock, or `lockProjectTransferHook` earlier.
1541
+ * @dev Hook configuration is implemented in `V3TransferHookLib` so Engine
1542
+ * and Engine Flex share one implementation while both remain under the
1543
+ * 24KB bytecode size limit.
1544
+ * @param _projectId Project ID.
1545
+ * @param _hook Hook contract, or `address(0)` to clear.
1546
+ */
1547
+ function configureProjectTransferHook(
1548
+ uint256 _projectId,
1549
+ address _hook
1550
+ ) external {
1551
+ _onlyValidProjectId(_projectId);
1552
+ _onlyArtistOrAdminACL(
1553
+ _projectId,
1554
+ this.configureProjectTransferHook.selector
1555
+ );
1556
+ V3TransferHookLib.configure({
1557
+ layout: _transferHookLayout,
1558
+ projectId: _projectId,
1559
+ hook: ITransferHook(_hook),
1560
+ projectUnlocked: _projectUnlocked(_projectId)
1561
+ });
1562
+ }
1563
+
1564
+ /**
1565
+ * @notice Permanently lock the transfer hook for project `_projectId` at
1566
+ * `_expectedHook`, which may be `address(0)`. Artist only. If locked at
1567
+ * `address(0)`, a hook can never be assigned. Reverts if already locked,
1568
+ * including when the four-week project metadata lock has already frozen
1569
+ * an unset hook.
1570
+ * @dev `_expectedHook` must match the project's currently configured hook.
1571
+ * Because this lock is permanent and the hook may be updated by either the
1572
+ * artist or the Admin ACL, requiring the expected value prevents a
1573
+ * `configureProjectTransferHook` call landing first from causing an
1574
+ * unintended hook to be permanently locked in.
1575
+ * WARNING: locking freezes the hook ADDRESS, not the hook's behavior. If
1576
+ * `_expectedHook` is an upgradeable proxy, its owner may still change what
1577
+ * runs on every transfer, and the project has no way to move away from it.
1578
+ * Locking is only a meaningful guarantee when the hook is immutable, or
1579
+ * when locking at `address(0)`.
1580
+ * @dev Implemented in `V3TransferHookLib` so Engine and Engine Flex share
1581
+ * one implementation while both remain under the 24KB bytecode size limit.
1582
+ * @param _projectId Project ID.
1583
+ * @param _expectedHook Hook the caller expects to lock in.
1584
+ */
1585
+ function lockProjectTransferHook(
1586
+ uint256 _projectId,
1587
+ address _expectedHook
1588
+ ) external {
1589
+ _onlyValidProjectId(_projectId);
1590
+ _onlyArtist(_projectId);
1591
+ V3TransferHookLib.lock({
1592
+ layout: _transferHookLayout,
1593
+ projectId: _projectId,
1594
+ expectedHook: _expectedHook,
1595
+ projectUnlocked: _projectUnlocked(_projectId)
1596
+ });
1597
+ }
1598
+
1640
1599
  /**
1641
1600
  * @notice Updates default base URI to `_defaultBaseURI`. The
1642
1601
  * contract-level defaultBaseURI is only used when initializing new
@@ -1903,6 +1862,33 @@ contract GenArt721CoreV3_Engine is
1903
1862
  projectBaseURI = projects[_projectId].projectBaseURI;
1904
1863
  }
1905
1864
 
1865
+ /**
1866
+ * @notice Transfer hook configuration for project `_projectId`.
1867
+ * @dev Reverts if `_projectId` is not a valid project on this contract.
1868
+ * @dev The effective lock is evaluated by `V3TransferHookLib` so that this
1869
+ * view, `configureProjectTransferHook`, and `lockProjectTransferHook` can
1870
+ * never disagree about whether a project is locked.
1871
+ * @param _projectId Project to be queried.
1872
+ * @return hook Hook address, or `address(0)` if none is configured.
1873
+ * @return locked True if the artist called `lockProjectTransferHook`, or
1874
+ * if the four-week project metadata lock has elapsed while the hook is
1875
+ * `address(0)`.
1876
+ */
1877
+ function projectTransferHookConfig(
1878
+ uint256 _projectId
1879
+ ) external view returns (address hook, bool locked) {
1880
+ V3TransferHookLib.ProjectTransferHookConfig
1881
+ storage config = _transferHookLayout.configs[_projectId];
1882
+ // @dev `_projectUnlocked` also enforces that `_projectId` is valid
1883
+ return (
1884
+ address(config.hook),
1885
+ V3TransferHookLib.isLocked({
1886
+ config: config,
1887
+ projectUnlocked: _projectUnlocked(_projectId)
1888
+ })
1889
+ );
1890
+ }
1891
+
1906
1892
  /**
1907
1893
  * @notice Backwards-compatible (pre-V3) function returning if `_minter` is
1908
1894
  * minterContract.
@@ -1948,36 +1934,21 @@ contract GenArt721CoreV3_Engine is
1948
1934
  * @return receiver address that should be sent the royalty payment
1949
1935
  * @return royaltyAmount the royalty payment amount for `_salePrice
1950
1936
  * @dev reverts if invalid _tokenId
1937
+ * @dev Implemented in `V3EngineLib` so Engine and Engine Flex share one
1938
+ * implementation while both remain under the 24KB bytecode size limit.
1951
1939
  */
1952
1940
  function royaltyInfo(
1953
1941
  uint256 _tokenId,
1954
1942
  uint256 _salePrice
1955
1943
  ) external view returns (address receiver, uint256 royaltyAmount) {
1956
1944
  _onlyValidTokenId(_tokenId);
1957
-
1958
- // populate receiver with project's royalty splitter
1959
- // @dev royalty splitter created upon project creation, so will always exist
1960
- // for valid token ID
1961
- uint256 projectId = tokenIdToProjectId(_tokenId);
1962
- ProjectFinance storage projectFinance = _projectIdToFinancials[
1963
- projectId
1964
- ];
1965
- receiver = projectFinance.royaltySplitter;
1966
-
1967
- // populate royaltyAmount with calculated royalty amount
1968
- // @dev important to cast to uint256 before multiplying to avoid overflow
1969
- uint256 totalRoyaltyBPS = (100 *
1970
- uint256(projectFinance.secondaryMarketRoyaltyPercentage)) +
1971
- projectFinance.platformProviderSecondarySalesBPS +
1972
- projectFinance.renderProviderSecondarySalesBPS;
1973
- // @dev totalRoyaltyBPS guaranteed to be <= 10,000,
1974
- if (totalRoyaltyBPS > 10_000) {
1975
- revert GenArt721Error(ErrorCodes.OverMaxSumOfBPS);
1976
- }
1977
- // @dev overflow automatically checked in solidity 0.8
1978
- // @dev totalRoyaltyBPS guaranteed to be <= 10_000,
1979
- // so overflow only possible with unreasonably high _salePrice values near uint256 max
1980
- royaltyAmount = (_salePrice * totalRoyaltyBPS) / 10_000;
1945
+ return
1946
+ V3EngineLib.royaltyInfo({
1947
+ projectFinance: _projectIdToFinancials[
1948
+ tokenIdToProjectId(_tokenId)
1949
+ ],
1950
+ salePrice: _salePrice
1951
+ });
1981
1952
  }
1982
1953
 
1983
1954
  /**
@@ -2012,6 +1983,8 @@ contract GenArt721CoreV3_Engine is
2012
1983
  * revenue is zero, the corresponding address will be address(0). It is up
2013
1984
  * to the contract performing the revenue split to handle this
2014
1985
  * appropriately.
1986
+ * @dev Implemented in `V3EngineLib` so Engine and Engine Flex share one
1987
+ * implementation while both remain under the 24KB bytecode size limit.
2015
1988
  */
2016
1989
  function getPrimaryRevenueSplits(
2017
1990
  uint256 _projectId,
@@ -2030,41 +2003,15 @@ contract GenArt721CoreV3_Engine is
2030
2003
  address payable additionalPayeePrimaryAddress_
2031
2004
  )
2032
2005
  {
2033
- ProjectFinance storage projectFinance = _projectIdToFinancials[
2034
- _projectId
2035
- ];
2036
- // calculate revenues – this is a three-way split between the
2037
- // render provider, the platform provider, and the artist, and
2038
- // is safe to perform this given that in the case of loss of
2039
- // precision Solidity will round down.
2040
- uint256 projectFunds = _price;
2041
- renderProviderRevenue_ =
2042
- (_price * uint256(_renderProviderPrimarySalesPercentage)) /
2043
- ONE_HUNDRED;
2044
- // renderProviderRevenue_ percentage is always <=100, so guaranteed to never underflow
2045
- projectFunds -= renderProviderRevenue_;
2046
- platformProviderRevenue_ =
2047
- (_price * uint256(_platformProviderPrimarySalesPercentage)) /
2048
- ONE_HUNDRED;
2049
- // platformProviderRevenue_ percentage is always <=100, so guaranteed to never underflow
2050
- projectFunds -= platformProviderRevenue_;
2051
- additionalPayeePrimaryRevenue_ =
2052
- (projectFunds *
2053
- projectFinance.additionalPayeePrimarySalesPercentage) /
2054
- ONE_HUNDRED;
2055
- // projectIdToAdditionalPayeePrimarySalesPercentage is always
2056
- // <=100, so guaranteed to never underflow
2057
- artistRevenue_ = projectFunds - additionalPayeePrimaryRevenue_;
2058
- // set addresses from storage
2059
- renderProviderAddress_ = renderProviderPrimarySalesAddress;
2060
- platformProviderAddress_ = platformProviderPrimarySalesAddress;
2061
- if (artistRevenue_ > 0) {
2062
- artistAddress_ = projectFinance.artistAddress;
2063
- }
2064
- if (additionalPayeePrimaryRevenue_ > 0) {
2065
- additionalPayeePrimaryAddress_ = projectFinance
2066
- .additionalPayeePrimarySales;
2067
- }
2006
+ return
2007
+ V3EngineLib.getPrimaryRevenueSplits({
2008
+ projectFinance: _projectIdToFinancials[_projectId],
2009
+ price: _price,
2010
+ renderProviderPrimarySalesPercentage: _renderProviderPrimarySalesPercentage,
2011
+ platformProviderPrimarySalesPercentage: _platformProviderPrimarySalesPercentage,
2012
+ renderProviderPrimarySalesAddress: renderProviderPrimarySalesAddress,
2013
+ platformProviderPrimarySalesAddress: platformProviderPrimarySalesAddress
2014
+ });
2068
2015
  }
2069
2016
 
2070
2017
  /**
@@ -2164,6 +2111,64 @@ contract GenArt721CoreV3_Engine is
2164
2111
  super.supportsInterface(interfaceId);
2165
2112
  }
2166
2113
 
2114
+ /**
2115
+ * @dev After ownership is written, dispatch the project's transfer hook
2116
+ * for non-mint transfers. Mint dispatch happens in `mint_Ecf` after hash
2117
+ * assignment so the hook can read `tokenIdToHash`.
2118
+ * Reverts if a transfer hook is already executing, blocking reentrant
2119
+ * transfers from a hook.
2120
+ */
2121
+ function _update(
2122
+ address to,
2123
+ uint256 tokenId,
2124
+ address auth
2125
+ ) internal override returns (address) {
2126
+ if (_transferHookLayout.executing) {
2127
+ revert GenArt721Error(ErrorCodes.TransferHookReentrancy);
2128
+ }
2129
+ address from = super._update(to, tokenId, auth);
2130
+ if (from != address(0)) {
2131
+ _dispatchTransferHook({
2132
+ from: from,
2133
+ to: to,
2134
+ tokenId: tokenId,
2135
+ operator: _msgSender()
2136
+ });
2137
+ }
2138
+ return from;
2139
+ }
2140
+
2141
+ /**
2142
+ * @notice Call the project's transfer hook if one is configured.
2143
+ * @dev Projects with no hook return after a single SLOAD of the project's
2144
+ * config slot, with no DELEGATECALL. Combined with the `executing` SLOAD
2145
+ * in `_update`, a transfer on a contract using no hooks costs roughly
2146
+ * 4,200 gas more than it did prior to v3.3. A transfer that does dispatch
2147
+ * a hook additionally pays a ~20,000 gas SSTORE to set the reentrancy
2148
+ * flag, plus the DELEGATECALL and the hook's own execution.
2149
+ */
2150
+ function _dispatchTransferHook(
2151
+ address from,
2152
+ address to,
2153
+ uint256 tokenId,
2154
+ address operator
2155
+ ) internal {
2156
+ ITransferHook hook = _transferHookLayout
2157
+ .configs[tokenId / ONE_MILLION]
2158
+ .hook;
2159
+ if (address(hook) == address(0)) {
2160
+ return;
2161
+ }
2162
+ V3TransferHookLib.callHook({
2163
+ layout: _transferHookLayout,
2164
+ hook: hook,
2165
+ tokenId: tokenId,
2166
+ from: from,
2167
+ to: to,
2168
+ operator: operator
2169
+ });
2170
+ }
2171
+
2167
2172
  /**
2168
2173
  * @notice Forbids new projects from being created
2169
2174
  * @dev only performs operation and emits event if contract is not already
@@ -2314,39 +2319,16 @@ contract GenArt721CoreV3_Engine is
2314
2319
  * financials, so ensure storage has been updated before calling this
2315
2320
  * @dev This function includes a trusted interaction that is entrusted to
2316
2321
  * not reenter this contract.
2322
+ * @dev Implemented in `V3EngineLib` so Engine and Engine Flex share one
2323
+ * implementation while both remain under the 24KB bytecode size limit.
2317
2324
  * @param projectId Project ID to be updated.
2318
2325
  */
2319
2326
  function _assignSplitter(uint256 projectId) internal {
2320
- ProjectFinance storage projectFinance = _projectIdToFinancials[
2327
+ V3EngineLib.assignSplitter(
2328
+ _projectIdToFinancials[projectId],
2329
+ splitProvider,
2321
2330
  projectId
2322
- ];
2323
- // assign project's royalty splitter
2324
- // @dev loads values from storage, so need to ensure storage has been updated
2325
- address royaltySplitter = splitProvider.getOrCreateSplitter(
2326
- ISplitProviderV0.SplitInputs({
2327
- platformProviderSecondarySalesAddress: projectFinance
2328
- .platformProviderSecondarySalesAddress,
2329
- platformProviderSecondarySalesBPS: projectFinance
2330
- .platformProviderSecondarySalesBPS,
2331
- renderProviderSecondarySalesAddress: projectFinance
2332
- .renderProviderSecondarySalesAddress,
2333
- renderProviderSecondarySalesBPS: projectFinance
2334
- .renderProviderSecondarySalesBPS,
2335
- artistTotalRoyaltyPercentage: projectFinance
2336
- .secondaryMarketRoyaltyPercentage,
2337
- artist: projectFinance.artistAddress,
2338
- additionalPayee: projectFinance.additionalPayeeSecondarySales,
2339
- additionalPayeePercentage: projectFinance
2340
- .additionalPayeeSecondarySalesPercentage
2341
- })
2342
2331
  );
2343
-
2344
- projectFinance.royaltySplitter = royaltySplitter;
2345
-
2346
- emit ProjectRoyaltySplitterUpdated({
2347
- projectId: projectId,
2348
- royaltySplitter: royaltySplitter
2349
- });
2350
2332
  }
2351
2333
 
2352
2334
  /**
@@ -2447,8 +2429,13 @@ contract GenArt721CoreV3_Engine is
2447
2429
  // set AdminACL management contract as owner
2448
2430
  _transferOwnership(adminACLContract_);
2449
2431
  // initialize default base URI
2432
+ // @dev offloaded to V3EngineLib to keep `Strings.toHexString` out of
2433
+ // the size-constrained cores; this runs once, at initialization
2450
2434
  _updateDefaultBaseURI(
2451
- string.concat(defaultBaseURIHost, address(this).toHexString(), "/")
2435
+ V3EngineLib.buildDefaultBaseURI({
2436
+ host: defaultBaseURIHost,
2437
+ coreContract: address(this)
2438
+ })
2452
2439
  );
2453
2440
  // initialize next project ID
2454
2441
  _nextProjectId = engineConfiguration.startingProjectId;