@artblocks/contracts 1.2.0 → 1.3.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 (219) hide show
  1. package/README.md +22 -38
  2. package/artifacts/contracts/AdminACLV1.sol/AdminACLV1.json +2 -2
  3. package/artifacts/contracts/BytecodeStorageReaders/BytecodeStorageReaderContractV2.sol/BytecodeStorageReaderContractV2.json +201 -0
  4. package/artifacts/contracts/BytecodeStorageReaders/BytecodeStorageReaderContractV2_Web3Call.sol/BytecodeStorageReaderContractV2_Web3Call.json +201 -0
  5. package/artifacts/contracts/BytecodeStorageReaders/UniversalBytecodeStorageReader.sol/UniversalBytecodeStorageReader.json +154 -0
  6. package/artifacts/contracts/BytecodeStorageV2Writer.sol/BytecodeStorageV2Writer.json +87 -0
  7. package/artifacts/contracts/DependencyRegistryV0.sol/DependencyRegistryV0.json +174 -55
  8. package/artifacts/contracts/GenArt721CoreV3_Curated.sol/GenArt721CoreV3_Curated.json +2493 -0
  9. package/artifacts/contracts/OwnedCreate2FactoryV0.sol/OwnedCreate2FactoryV0.json +311 -0
  10. package/artifacts/contracts/archive/GenArt721CoreV3.sol/GenArt721CoreV3.json +15 -2
  11. package/artifacts/contracts/archive/GenArt721CoreV3_Explorations.sol/GenArt721CoreV3_Explorations.json +15 -2
  12. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExp/MinterDAExpV2.sol/MinterDAExpV2.json +2 -2
  13. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExp/MinterDAExpV3.sol/MinterDAExpV3.json +2 -2
  14. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExp/MinterDAExpV4.sol/MinterDAExpV4.json +2 -2
  15. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExpSettlement/MinterDAExpSettlementV0.sol/MinterDAExpSettlementV0.json +2 -2
  16. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExpSettlement/MinterDAExpSettlementV1.sol/MinterDAExpSettlementV1.json +2 -2
  17. package/artifacts/contracts/archive/minter-suite/Minters/MinterDAExpSettlement/MinterDAExpSettlementV2.sol/MinterDAExpSettlementV2.json +2 -2
  18. package/artifacts/contracts/archive/minter-suite/Minters/MinterDALin/MinterDALinV2.sol/MinterDALinV2.json +2 -2
  19. package/artifacts/contracts/archive/minter-suite/Minters/MinterDALin/MinterDALinV3.sol/MinterDALinV3.json +2 -2
  20. package/artifacts/contracts/archive/minter-suite/Minters/MinterDALin/MinterDALinV4.sol/MinterDALinV4.json +2 -2
  21. package/artifacts/contracts/archive/minter-suite/Minters/MinterHolder/MinterHolderV1.sol/MinterHolderV1.json +2 -2
  22. package/artifacts/contracts/archive/minter-suite/Minters/MinterHolder/MinterHolderV2.sol/MinterHolderV2.json +2 -2
  23. package/artifacts/contracts/archive/minter-suite/Minters/MinterHolder/MinterHolderV3.sol/MinterHolderV3.json +2 -2
  24. package/artifacts/contracts/archive/minter-suite/Minters/MinterHolder/MinterHolderV4.sol/MinterHolderV4.json +2 -2
  25. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV1.sol/MinterMerkleV1.json +2 -2
  26. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV2.sol/MinterMerkleV2.json +2 -2
  27. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV3.sol/MinterMerkleV3.json +2 -2
  28. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV4.sol/MinterMerkleV4.json +2 -2
  29. package/artifacts/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV5.sol/MinterMerkleV5.json +2 -2
  30. package/artifacts/contracts/archive/minter-suite/Minters/MinterPolyptych/MinterPolyptychV0.sol/IGenArt721CoreContractV3WithRandomizer.json +37 -0
  31. package/artifacts/contracts/archive/minter-suite/Minters/MinterPolyptych/MinterPolyptychV0.sol/MinterPolyptychV0.json +2 -2
  32. package/artifacts/contracts/archive/minter-suite/Minters/MinterSEA/MinterSEAV0.sol/MinterSEAV0.json +2 -2
  33. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPrice/MinterSetPriceV2.sol/MinterSetPriceV2.json +2 -2
  34. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPrice/MinterSetPriceV3.sol/MinterSetPriceV3.json +2 -2
  35. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPrice/MinterSetPriceV4.sol/MinterSetPriceV4.json +2 -2
  36. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V2.sol/MinterSetPriceERC20V2.json +2 -2
  37. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V3.sol/MinterSetPriceERC20V3.json +2 -2
  38. package/artifacts/contracts/archive/minter-suite/Minters/MinterSetPriceERC20/MinterSetPriceERC20V4.sol/MinterSetPriceERC20V4.json +2 -2
  39. package/artifacts/contracts/engine/V3/EngineFactoryV0.sol/EngineFactoryV0.json +20 -2
  40. package/artifacts/contracts/engine/V3/GenArt721CoreV3_Engine.sol/GenArt721CoreV3_Engine.json +48 -12
  41. package/artifacts/contracts/engine/V3/GenArt721CoreV3_Engine_Flex.sol/GenArt721CoreV3_Engine_Flex.json +76 -40
  42. package/artifacts/contracts/engine/V3/forks/GenArt721CoreV3_Engine_Flex_PROOF.sol/GenArt721CoreV3_Engine_Flex_PROOF.json +15 -2
  43. package/artifacts/contracts/engine/V3/forks/PROHIBITION/AdminACLV0_PROHIBITION.sol/AdminACLV0_PROHIBITION.json +2 -2
  44. package/artifacts/contracts/engine/V3/forks/PROHIBITION/GenArt721CoreV3_Engine_Flex_PROHIBITION.sol/GenArt721CoreV3_Engine_Flex_PROHIBITION.json +15 -2
  45. package/artifacts/contracts/engine/V3/forks/PROHIBITION/interfaces/IGenArt721CoreContractV3_Engine_Flex_PROHIBITION.sol/IGenArt721CoreContractV3_Engine_Flex_PROHIBITION.json +37 -0
  46. package/artifacts/contracts/engine-registry/CoreRegistryV1.sol/CoreRegistryV1.json +2 -2
  47. package/artifacts/contracts/generator/AddressChunks.sol/AddressChunks.json +10 -0
  48. package/artifacts/contracts/generator/GenArt721GeneratorV0.sol/GenArt721GeneratorV0.json +333 -0
  49. package/artifacts/contracts/generator/GenArt721GeneratorV0.sol/ILegacyGenArt721CoreV2_PBAB_Flex.json +47 -0
  50. package/artifacts/contracts/interfaces/v0.8.x/IBytecodeStorageReader.sol/IBytecodeStorageReader.json +7 -7
  51. package/artifacts/contracts/interfaces/v0.8.x/IBytecodeStorageReaderV2.sol/IBytecodeStorageReaderV2.json +7 -7
  52. package/artifacts/contracts/interfaces/v0.8.x/IBytecodeStorageReader_Base.sol/IBytecodeStorageReader_Base.json +30 -0
  53. package/artifacts/contracts/interfaces/v0.8.x/ICoreRegistryV1.sol/ICoreRegistryV1.json +13 -0
  54. package/artifacts/contracts/interfaces/v0.8.x/IDelegateRegistry.sol/IDelegateRegistry.json +820 -0
  55. package/artifacts/contracts/interfaces/v0.8.x/IDependencyRegistryV0.sol/IDependencyRegistryV0.json +183 -0
  56. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3.sol/IGenArt721CoreContractV3.json +37 -0
  57. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Base.sol/IGenArt721CoreContractV3_Base.json +37 -0
  58. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine.sol/IGenArt721CoreContractV3_Engine.json +42 -0
  59. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex.sol/IGenArt721CoreContractV3_Engine_Flex.json +42 -0
  60. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex_PreV3p2.sol/IGenArt721CoreContractV3_Engine_Flex_PreV3p2.json +37 -0
  61. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_PreV3p2.sol/IGenArt721CoreContractV3_Engine_PreV3p2.json +37 -0
  62. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreProjectScriptV0.sol/IGenArt721CoreProjectScriptV0.json +59 -0
  63. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreProjectScriptV1.sol/IGenArt721CoreProjectScriptV1.json +64 -0
  64. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreTokenHashProviderV0.sol/IGenArt721CoreTokenHashProviderV0.json +30 -0
  65. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721CoreTokenHashProviderV1.sol/IGenArt721CoreTokenHashProviderV1.json +30 -0
  66. package/artifacts/contracts/interfaces/v0.8.x/IGenArt721GeneratorV0.sol/IGenArt721GeneratorV0.json +63 -0
  67. package/artifacts/contracts/interfaces/v0.8.x/IOwnedCreate2FactoryV0.sol/IOwnedCreate2FactoryV0.json +74 -0
  68. package/artifacts/contracts/interfaces/v0.8.x/IPMPAugmentHook.sol/IPMPAugmentHook.json +83 -0
  69. package/artifacts/contracts/interfaces/v0.8.x/IPMPConfigureHook.sol/IPMPConfigureHook.json +80 -0
  70. package/artifacts/contracts/interfaces/v0.8.x/IPMPV0.sol/IPMPV0.json +402 -0
  71. package/artifacts/contracts/interfaces/v0.8.x/ISeaDropShimForContract.sol/ISeaDropShimForContract.json +37 -0
  72. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterMinPriceV0.sol/ISharedMinterMinPriceV0.json +37 -0
  73. package/artifacts/contracts/interfaces/v0.8.x/IUniversalBytecodeStorageReader.sol/IUniversalBytecodeStorageReader.json +69 -0
  74. package/artifacts/contracts/interfaces/v0.8.x/IWeb3Call.sol/IWeb3Call.json +47 -0
  75. package/artifacts/contracts/interfaces/v0.8.x/integration-refs/OpenSea/ERC721SeaDropStructsErrorsAndEvents.sol/ERC721SeaDropStructsErrorsAndEvents.json +43 -0
  76. package/artifacts/contracts/interfaces/v0.8.x/integration-refs/OpenSea/INonFungibleSeaDropToken.sol/INonFungibleSeaDropToken.json +715 -0
  77. package/artifacts/contracts/interfaces/v0.8.x/integration-refs/OpenSea/ISeaDrop.sol/ISeaDrop.json +1571 -0
  78. package/artifacts/contracts/interfaces/v0.8.x/integration-refs/OpenSea/ISeaDropTokenContractMetadata.sol/ISeaDropTokenContractMetadata.json +345 -0
  79. package/artifacts/contracts/interfaces/v0.8.x/integration-refs/OpenSea/SeaDropErrorsAndEvents.sol/SeaDropErrorsAndEvents.json +717 -0
  80. package/artifacts/contracts/libs/integration-refs/delegation-registry/DelegateRegistry.sol/DelegateRegistry.json +846 -0
  81. package/artifacts/contracts/libs/integration-refs/delegation-registry/libraries/RegistryHashes.sol/RegistryHashes.json +10 -0
  82. package/artifacts/contracts/libs/integration-refs/delegation-registry/libraries/RegistryOps.sol/RegistryOps.json +10 -0
  83. package/artifacts/contracts/libs/integration-refs/delegation-registry/libraries/RegistryStorage.sol/RegistryStorage.json +10 -0
  84. package/artifacts/contracts/libs/v0.8.x/AuthLib.sol/AuthLib.json +2 -2
  85. package/artifacts/contracts/libs/v0.8.x/Bytes32Strings.sol/Bytes32Strings.json +2 -2
  86. package/artifacts/contracts/libs/v0.8.x/DependencyRegistryStorageLib.sol/DependencyRegistryStorageLib.json +2 -2
  87. package/artifacts/contracts/libs/v0.8.x/ImmutableStringArray.sol/ImmutableStringArray.json +10 -0
  88. package/artifacts/contracts/libs/v0.8.x/JsonStatic.sol/JsonStatic.json +10 -0
  89. package/artifacts/contracts/libs/v0.8.x/V3FlexLib.sol/V3FlexLib.json +9 -22
  90. package/artifacts/contracts/libs/v0.8.x/minter-libs/MaxInvocationsLib.sol/MaxInvocationsLib.json +2 -2
  91. package/artifacts/contracts/libs/v0.8.x/minter-libs/MinPriceLib.sol/MinPriceLib.json +24 -0
  92. package/artifacts/contracts/libs/v0.8.x/minter-libs/PolyptychLib.sol/PolyptychLib.json +2 -2
  93. package/artifacts/contracts/libs/v0.8.x/minter-libs/RAMLib.sol/RAMLib.json +2 -2
  94. package/artifacts/contracts/libs/v0.8.x/minter-libs/SEALib.sol/SEALib.json +2 -2
  95. package/artifacts/contracts/libs/v0.8.x/minter-libs/SettlementExpLib.sol/SettlementExpLib.json +2 -2
  96. package/artifacts/contracts/libs/v0.8.x/minter-libs/SplitFundsLib.sol/SplitFundsLib.json +2 -2
  97. package/artifacts/contracts/minter-suite/MinterFilter/MinterFilterV1.sol/MinterFilterV1.json +2 -2
  98. package/artifacts/contracts/minter-suite/MinterFilter/MinterFilterV2.sol/MinterFilterV2.json +2 -2
  99. package/artifacts/contracts/minter-suite/Minters/MinterDAExpHolderV5.sol/MinterDAExpHolderV5.json +2 -2
  100. package/artifacts/contracts/minter-suite/Minters/MinterDAExpSettlementV3.sol/MinterDAExpSettlementV3.json +2 -2
  101. package/artifacts/contracts/minter-suite/Minters/MinterDAExpV5.sol/MinterDAExpV5.json +2 -2
  102. package/artifacts/contracts/minter-suite/Minters/MinterDALinHolderV5.sol/MinterDALinHolderV5.json +2 -2
  103. package/artifacts/contracts/minter-suite/Minters/MinterDALinV5.sol/MinterDALinV5.json +2 -2
  104. package/artifacts/contracts/minter-suite/Minters/MinterMinPriceMerkleV0.sol/MinterMinPriceMerkleV0.json +664 -0
  105. package/artifacts/contracts/minter-suite/Minters/MinterMinPriceV0.sol/MinterMinPriceV0.json +387 -0
  106. package/artifacts/contracts/minter-suite/Minters/MinterRAMV0.sol/MinterRAMV0.json +2 -2
  107. package/artifacts/contracts/minter-suite/Minters/MinterSEAV1.sol/MinterSEAV1.json +2 -2
  108. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceERC20V5.sol/MinterSetPriceERC20V5.json +2 -2
  109. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceHolderV5.sol/MinterSetPriceHolderV5.json +2 -2
  110. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceMerkleV5.sol/MinterSetPriceMerkleV5.json +2 -2
  111. package/artifacts/contracts/minter-suite/Minters/MinterSetPricePolyptychERC20V5.sol/MinterSetPricePolyptychERC20V5.json +2 -2
  112. package/artifacts/contracts/minter-suite/Minters/MinterSetPricePolyptychV5.sol/MinterSetPricePolyptychV5.json +2 -2
  113. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceV5.sol/MinterSetPriceV5.json +2 -2
  114. package/artifacts/contracts/minter-suite/Minters/one-off/MinterSetPriceV5_SingleCore.sol/MinterSetPriceV5_SingleCore.json +2 -2
  115. package/artifacts/contracts/minter-suite/Minters/one-off/SeaDropXArtBlocksShim.sol/SeaDropXArtBlocksShim.json +1206 -0
  116. package/artifacts/contracts/mock/BytecodeV1LibCallsMock.sol/BytecodeV1LibCallsMock.json +2 -2
  117. package/artifacts/contracts/mock/BytecodeV2LibCallsMock.sol/BytecodeV2LibCallsMock.json +2 -2
  118. package/artifacts/contracts/mock/DummySharedMinter.sol/DummySharedMinter.json +2 -2
  119. package/artifacts/contracts/mock/ERC20MockAltDecimals.sol/ERC20MockAltDecimals.json +318 -0
  120. package/artifacts/contracts/mock/ForceSendMock.sol/ForceSendMock.json +2 -2
  121. package/artifacts/contracts/mock/GenArt721CoreV3_Engine_IncorrectCoreType.sol/GenArt721CoreV3_Engine_IncorrectCoreType.json +2 -2
  122. package/artifacts/contracts/mock/ImmutableStringArrayMock.sol/ImmutableStringArrayMock.json +69 -0
  123. package/artifacts/contracts/mock/MockAdminACLV0_PROHIBITION.sol/MockAdminACLV0Events_PROHIBITION.json +2 -2
  124. package/artifacts/contracts/mock/MockFileStore.sol/MockFileStore.json +35 -0
  125. package/artifacts/contracts/mock/MockPMPAugmentHook.sol/MockPMPAugmentHook.json +214 -0
  126. package/artifacts/contracts/mock/MockPMPConfigureHook.sol/MockPMPConfigureHook.json +236 -0
  127. package/artifacts/contracts/mock/OriginRegisterMock.sol/OriginRegisterMock.json +2 -2
  128. package/artifacts/contracts/mock/RandomizerV2_NoAssignMock.sol/RandomizerV2_NoAssignMock.json +2 -2
  129. package/artifacts/contracts/randomizer/deprecated/PolyptychRandomizerV0.sol/BasicPolyptychRandomizerV0.json +2 -2
  130. package/artifacts/contracts/randomizer/deprecated/RandomizerV2.sol/BasicRandomizerV2.json +2 -2
  131. package/artifacts/contracts/randomizer/shared/SharedRandomizerV0.sol/SharedRandomizerV0.json +2 -2
  132. package/artifacts/contracts/web3call/PMPV0.sol/PMPV0.json +629 -0
  133. package/artifacts/contracts/web3call/Web3Call.sol/Web3Call.json +66 -0
  134. package/artifacts/contracts/web3call/augment-hooks/AbstractPMPAugmentHook.sol/AbstractPMPAugmentHook.json +83 -0
  135. package/artifacts/contracts/web3call/augment-hooks/InjectBaseGasFee.sol/InjectBaseGasFee.json +83 -0
  136. package/artifacts/contracts/web3call/augment-hooks/InjectChromieSquiggleFloorPrice.sol/IUniswapV2Pair.json +60 -0
  137. package/artifacts/contracts/web3call/augment-hooks/InjectChromieSquiggleFloorPrice.sol/InjectChromieSquiggleFloorPrice.json +107 -0
  138. package/artifacts/contracts/web3call/augment-hooks/InjectIsNounsDaoMember.sol/InjectIsNounsDaoMember.json +96 -0
  139. package/artifacts/contracts/web3call/augment-hooks/InjectIsProjectFullyMinted.sol/InjectIsProjectFullyMinted.json +83 -0
  140. package/artifacts/contracts/web3call/augment-hooks/InjectPolyptychTokenHash.sol/InjectPolyptychTokenHash.json +141 -0
  141. package/artifacts/contracts/web3call/augment-hooks/InjectTokenHashSeed.sol/InjectTokenHashSeed.json +99 -0
  142. package/artifacts/contracts/web3call/augment-hooks/InjectTokenOwner.sol/InjectTokenOwner.json +99 -0
  143. package/artifacts/contracts/web3call/augment-hooks/InjectTokenOwnerEthBalance.sol/InjectTokenOwnerEthBalance.json +83 -0
  144. package/artifacts/contracts/web3call/augment-hooks/InjectUSDCTotalSupply.sol/InjectUSDCTotalSupply.json +107 -0
  145. package/artifacts/contracts/web3call/configure-hooks/abstractPMPConfigureHook.sol/AbstractPMPConfigureHook.json +80 -0
  146. package/contracts/BytecodeStorageReaders/BytecodeStorageReaderContractV2.sol +103 -0
  147. package/contracts/BytecodeStorageReaders/BytecodeStorageReaderContractV2_Web3Call.sol +128 -0
  148. package/contracts/BytecodeStorageReaders/UniversalBytecodeStorageReader.sol +70 -0
  149. package/contracts/BytecodeStorageV2Writer.sol +69 -0
  150. package/contracts/DependencyRegistryV0.sol +296 -88
  151. package/contracts/GenArt721CoreV3_Curated.sol +133 -0
  152. package/contracts/OwnedCreate2FactoryV0.sol +173 -0
  153. package/contracts/engine/V3/EngineFactoryV0.sol +10 -2
  154. package/contracts/engine/V3/GenArt721CoreV3_Engine.sol +139 -70
  155. package/contracts/engine/V3/GenArt721CoreV3_Engine_Flex.sol +148 -72
  156. package/contracts/generator/AddressChunks.sol +106 -0
  157. package/contracts/generator/GenArt721GeneratorV0.sol +1163 -0
  158. package/contracts/generator/scripty-support/Scripty.sol +5 -0
  159. package/contracts/interfaces/v0.8.x/IBytecodeStorageReader.sol +34 -36
  160. package/contracts/interfaces/v0.8.x/IBytecodeStorageReaderV2.sol +5 -3
  161. package/contracts/interfaces/v0.8.x/IBytecodeStorageReader_Base.sol +20 -0
  162. package/contracts/interfaces/v0.8.x/ICoreRegistryV1.sol +5 -0
  163. package/contracts/interfaces/v0.8.x/IDelegateRegistry.sol +318 -0
  164. package/contracts/interfaces/v0.8.x/IDependencyRegistryV0.sol +96 -0
  165. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Base.sol +13 -2
  166. package/contracts/interfaces/v0.8.x/IGenArt721CoreContractV3_Engine.sol +3 -1
  167. package/contracts/interfaces/v0.8.x/IGenArt721CoreProjectScriptV0.sol +22 -0
  168. package/contracts/interfaces/v0.8.x/IGenArt721CoreProjectScriptV1.sol +23 -0
  169. package/contracts/interfaces/v0.8.x/IGenArt721CoreTokenHashProviderV0.sol +11 -0
  170. package/contracts/interfaces/v0.8.x/IGenArt721CoreTokenHashProviderV1.sol +9 -0
  171. package/contracts/interfaces/v0.8.x/IGenArt721GeneratorV0.sol +14 -0
  172. package/contracts/interfaces/v0.8.x/IOwnedCreate2FactoryV0.sol +40 -0
  173. package/contracts/interfaces/v0.8.x/IPMPAugmentHook.sol +31 -0
  174. package/contracts/interfaces/v0.8.x/IPMPConfigureHook.sol +25 -0
  175. package/contracts/interfaces/v0.8.x/IPMPV0.sol +224 -0
  176. package/contracts/interfaces/v0.8.x/ISeaDropShimForContract.sol +19 -0
  177. package/contracts/interfaces/v0.8.x/ISharedMinterMinPriceV0.sol +22 -0
  178. package/contracts/interfaces/v0.8.x/ISharedMinterRequired.sol +10 -4
  179. package/contracts/interfaces/v0.8.x/IUniversalBytecodeStorageReader.sol +33 -0
  180. package/contracts/interfaces/v0.8.x/IWeb3Call.sol +28 -0
  181. package/contracts/interfaces/v0.8.x/integration-refs/OpenSea/ERC721SeaDropStructsErrorsAndEvents.sol +58 -0
  182. package/contracts/interfaces/v0.8.x/integration-refs/OpenSea/INonFungibleSeaDropToken.sol +186 -0
  183. package/contracts/interfaces/v0.8.x/integration-refs/OpenSea/ISeaDrop.sol +337 -0
  184. package/contracts/interfaces/v0.8.x/integration-refs/OpenSea/ISeaDropTokenContractMetadata.sol +152 -0
  185. package/contracts/interfaces/v0.8.x/integration-refs/OpenSea/SeaDropErrorsAndEvents.sol +320 -0
  186. package/contracts/interfaces/v0.8.x/integration-refs/OpenSea/SeaDropStructs.sol +146 -0
  187. package/contracts/libs/integration-refs/delegation-registry/DelegateRegistry.sol +753 -0
  188. package/contracts/libs/integration-refs/delegation-registry/libraries/RegistryHashes.sol +359 -0
  189. package/contracts/libs/integration-refs/delegation-registry/libraries/RegistryOps.sol +31 -0
  190. package/contracts/libs/integration-refs/delegation-registry/libraries/RegistryStorage.sol +87 -0
  191. package/contracts/libs/v0.8.x/Bytes32Strings.sol +20 -0
  192. package/contracts/libs/v0.8.x/DependencyRegistryStorageLib.sol +14 -3
  193. package/contracts/libs/v0.8.x/ImmutableStringArray.sol +289 -0
  194. package/contracts/libs/v0.8.x/JsonStatic.sol +373 -0
  195. package/contracts/libs/v0.8.x/V3FlexLib.sol +16 -4
  196. package/contracts/libs/v0.8.x/minter-libs/MinPriceLib.sol +64 -0
  197. package/contracts/libs/v0.8.x/minter-libs/SplitFundsLib.sol +107 -0
  198. package/contracts/minter-suite/Minters/MinterMinPriceMerkleV0.sol +765 -0
  199. package/contracts/minter-suite/Minters/MinterMinPriceV0.sol +462 -0
  200. package/contracts/minter-suite/Minters/one-off/SeaDropXArtBlocksShim.sol +869 -0
  201. package/contracts/mock/ERC20MockAltDecimals.sol +31 -0
  202. package/contracts/mock/ImmutableStringArrayMock.sol +47 -0
  203. package/contracts/mock/MockFileStore.sol +22 -0
  204. package/contracts/mock/MockPMPAugmentHook.sol +170 -0
  205. package/contracts/mock/MockPMPConfigureHook.sol +78 -0
  206. package/contracts/web3call/PMPV0.sol +1125 -0
  207. package/contracts/web3call/Web3Call.sol +25 -0
  208. package/contracts/web3call/augment-hooks/AbstractPMPAugmentHook.sol +46 -0
  209. package/contracts/web3call/augment-hooks/InjectBaseGasFee.sol +57 -0
  210. package/contracts/web3call/augment-hooks/InjectChromieSquiggleFloorPrice.sol +103 -0
  211. package/contracts/web3call/augment-hooks/InjectIsNounsDaoMember.sol +66 -0
  212. package/contracts/web3call/augment-hooks/InjectIsProjectFullyMinted.sol +73 -0
  213. package/contracts/web3call/augment-hooks/InjectPolyptychTokenHash.sol +88 -0
  214. package/contracts/web3call/augment-hooks/InjectTokenHashSeed.sol +62 -0
  215. package/contracts/web3call/augment-hooks/InjectTokenOwner.sol +60 -0
  216. package/contracts/web3call/augment-hooks/InjectTokenOwnerEthBalance.sol +61 -0
  217. package/contracts/web3call/augment-hooks/InjectUSDCTotalSupply.sol +69 -0
  218. package/contracts/web3call/configure-hooks/abstractPMPConfigureHook.sol +41 -0
  219. package/package.json +23 -21
@@ -0,0 +1,1163 @@
1
+ // SPDX-License-Identifier: LGPL-3.0-only
2
+ pragma solidity 0.8.22;
3
+
4
+ import "../interfaces/v0.8.x/IDependencyRegistryV0.sol";
5
+ import "../interfaces/v0.8.x/IGenArt721CoreProjectScriptV0.sol";
6
+ import "../interfaces/v0.8.x/IGenArt721CoreProjectScriptV1.sol";
7
+ import "../interfaces/v0.8.x/IGenArt721CoreTokenHashProviderV0.sol";
8
+ import "../interfaces/v0.8.x/IGenArt721CoreTokenHashProviderV1.sol";
9
+ import "../interfaces/v0.8.x/IGenArt721GeneratorV0.sol";
10
+ import {IGenArt721CoreContractV3_Engine_Flex} from "../interfaces/v0.8.x/IGenArt721CoreContractV3_Engine_Flex.sol";
11
+ import {IUniversalBytecodeStorageReader} from "../interfaces/v0.8.x/IUniversalBytecodeStorageReader.sol";
12
+ import {IWeb3Call} from "../interfaces/v0.8.x/IWeb3Call.sol";
13
+
14
+ import "../libs/v0.8.x/Bytes32Strings.sol";
15
+ import {JsonStatic} from "../libs/v0.8.x/JsonStatic.sol";
16
+ import {ABHelpers} from "../libs/v0.8.x/ABHelpers.sol";
17
+ import {AddressChunks} from "./AddressChunks.sol";
18
+
19
+ import {Base64} from "@openzeppelin-5.0/contracts/utils/Base64.sol";
20
+ import "@openzeppelin-4.7/contracts/utils/Strings.sol";
21
+ import "@openzeppelin-4.8/contracts-upgradeable/proxy/utils/Initializable.sol";
22
+
23
+ import {IScriptyBuilderV2, HTMLRequest, HTMLTagType, HTMLTag} from "scripty.sol/contracts/scripty/interfaces/IScriptyBuilderV2.sol";
24
+
25
+ // @dev legacy interface for V2 flex contracts - used to get external legacy asset dependencies
26
+ interface ILegacyGenArt721CoreV2_PBAB_Flex {
27
+ enum LegacyExternalAssetDependencyType {
28
+ IPFS,
29
+ ARWEAVE
30
+ }
31
+ // legacy struct for V2 flex contracts
32
+ struct LegacyExternalAssetDependencyWithoutData {
33
+ string cid;
34
+ LegacyExternalAssetDependencyType dependencyType;
35
+ }
36
+
37
+ function projectExternalAssetDependencyByIndex(
38
+ uint256 _projectId,
39
+ uint256 _index
40
+ ) external view returns (LegacyExternalAssetDependencyWithoutData memory);
41
+ }
42
+
43
+ /**
44
+ * @title GenArt721GeneratorV0
45
+ * @author Art Blocks Inc.
46
+ * @notice This contract is used to generate the HTML for Art Blocks tokens
47
+ * by combining the dependency script, project script, token data. It utilizes
48
+ * the ScriptyBuilder contract to generate the HTML.
49
+ */
50
+ contract GenArt721GeneratorV0 is Initializable, IGenArt721GeneratorV0 {
51
+ using Bytes32Strings for bytes32;
52
+ using Bytes32Strings for string;
53
+ using JsonStatic for JsonStatic.Json;
54
+
55
+ // @dev This is an upgradable contract so we need to maintain
56
+ // the order of the variables to ensure we don't overwrite
57
+ // storage when upgrading.
58
+ IDependencyRegistryV0 public dependencyRegistry;
59
+ IScriptyBuilderV2 public scriptyBuilder;
60
+ address public gunzipScriptBytecodeAddress;
61
+ IUniversalBytecodeStorageReader public universalBytecodeStorageReader;
62
+
63
+ // @dev contants do not use sequential storage slots, and may be added/removed from upgradeable contracts
64
+ bytes32 constant JS_AT_NA_BYTES32 =
65
+ 0x6a73406e61000000000000000000000000000000000000000000000000000000; // "js@na"
66
+ bytes32 constant SVG_AT_NA_BYTES32 =
67
+ 0x737667406e610000000000000000000000000000000000000000000000000000; // "svg@na"
68
+
69
+ function _onlySupportedCoreContract(address coreContract) internal view {
70
+ require(
71
+ dependencyRegistry.isSupportedCoreContract(coreContract),
72
+ "Unsupported core contract"
73
+ );
74
+ }
75
+
76
+ function _onlyDependencyRegistryAdminACL(bytes4 selector) internal {
77
+ require(
78
+ dependencyRegistry.adminACLAllowed({
79
+ sender: msg.sender,
80
+ contract_: address(this),
81
+ selector: selector
82
+ }),
83
+ "Only DependencyRegistry AdminACL"
84
+ );
85
+ }
86
+
87
+ /**
88
+ * @notice Initializer for the GenArt721GeneratorV0 contract.
89
+ * @param _dependencyRegistry The address of the DependencyRegistry
90
+ * contract to be used for retrieving dependency scripts.
91
+ * @param _scriptyBuilder The address of the ScriptyBuilderV2 contract
92
+ * to be used for generating the HTML for tokens.
93
+ * @param _gunzipScriptBytecodeAddress The address of the gunzip script bytecode
94
+ * storage contract used to gunzip the dependency scripts in the browser.
95
+ * @param _universalBytecodeStorageReader The address of the universal bytecode storage reader contract.
96
+ */
97
+ function initialize(
98
+ address _dependencyRegistry,
99
+ address _scriptyBuilder,
100
+ address _gunzipScriptBytecodeAddress,
101
+ address _universalBytecodeStorageReader
102
+ ) public initializer {
103
+ dependencyRegistry = IDependencyRegistryV0(_dependencyRegistry);
104
+ scriptyBuilder = IScriptyBuilderV2(_scriptyBuilder);
105
+ gunzipScriptBytecodeAddress = _gunzipScriptBytecodeAddress;
106
+ universalBytecodeStorageReader = IUniversalBytecodeStorageReader(
107
+ _universalBytecodeStorageReader
108
+ );
109
+
110
+ emit DependencyRegistryUpdated(_dependencyRegistry);
111
+ emit ScriptyBuilderUpdated(_scriptyBuilder);
112
+ emit GunzipScriptBytecodeAddressUpdated(_gunzipScriptBytecodeAddress);
113
+ emit UniversalBytecodeStorageReaderUpdated(
114
+ _universalBytecodeStorageReader
115
+ );
116
+ }
117
+
118
+ /**
119
+ * @notice Set the DependencyRegistry contract address.
120
+ * @param _dependencyRegistry The address of the DependencyRegistry
121
+ * contract to be used for retrieving dependency scripts.
122
+ * @dev This function is gated to only the DependencyRegistry AdminACL.
123
+ * If an address is passed that does not implement the adminACLAllowed
124
+ * function, we will lose access to the write functions on this contract.
125
+ */
126
+ function updateDependencyRegistry(address _dependencyRegistry) external {
127
+ _onlyDependencyRegistryAdminACL(this.updateDependencyRegistry.selector);
128
+
129
+ dependencyRegistry = IDependencyRegistryV0(_dependencyRegistry);
130
+ emit DependencyRegistryUpdated(_dependencyRegistry);
131
+ }
132
+
133
+ /**
134
+ * @notice Set the ScriptyBuilder contract address.
135
+ * @param _scriptyBuilder The address of the ScriptyBuilderV2 contract
136
+ * to be used for generating the HTML for tokens.
137
+ * @dev This function is gated to only the DependencyRegistry AdminACL.
138
+ */
139
+ function updateScriptyBuilder(address _scriptyBuilder) external {
140
+ _onlyDependencyRegistryAdminACL(this.updateScriptyBuilder.selector);
141
+
142
+ scriptyBuilder = IScriptyBuilderV2(_scriptyBuilder);
143
+ emit ScriptyBuilderUpdated(_scriptyBuilder);
144
+ }
145
+
146
+ /**
147
+ * @notice Set the gunzip script address.
148
+ * @param _gunzipScriptBytecodeAddress The address of the gunzip script bytecode
149
+ * storage contract used to gunzip the dependency scripts in the browser.
150
+ * @dev This function is gated to only the DependencyRegistry AdminACL.
151
+ */
152
+ function updateGunzipScriptBytecodeAddress(
153
+ address _gunzipScriptBytecodeAddress
154
+ ) external {
155
+ _onlyDependencyRegistryAdminACL(
156
+ this.updateGunzipScriptBytecodeAddress.selector
157
+ );
158
+
159
+ gunzipScriptBytecodeAddress = _gunzipScriptBytecodeAddress;
160
+ emit GunzipScriptBytecodeAddressUpdated(_gunzipScriptBytecodeAddress);
161
+ }
162
+
163
+ /**
164
+ * @notice Set the universalBytecodeStorageReader contract address.
165
+ * @param _universalBytecodeStorageReader The address of the universal bytecode storage reader contract.
166
+ * @dev This function is gated to only the DependencyRegistry AdminACL.
167
+ */
168
+ function updateUniversalBytecodeStorageReader(
169
+ address _universalBytecodeStorageReader
170
+ ) external {
171
+ _onlyDependencyRegistryAdminACL(
172
+ this.updateUniversalBytecodeStorageReader.selector
173
+ );
174
+
175
+ universalBytecodeStorageReader = IUniversalBytecodeStorageReader(
176
+ _universalBytecodeStorageReader
177
+ );
178
+ emit UniversalBytecodeStorageReaderUpdated(
179
+ _universalBytecodeStorageReader
180
+ );
181
+ }
182
+
183
+ /**
184
+ * @notice Get the dependency script for a given dependency name and version string.
185
+ * @param dependencyNameAndVersion The name and version of the dependency
186
+ * to retrieve the script for.
187
+ * @return The dependency script stiched together from all of the script chunks as a string.
188
+ * @dev This function will revert if the dependency name and version is not
189
+ * supported by the DependencyRegistry or if the script storage version is
190
+ * not supported.
191
+ */
192
+ function getDependencyScript(
193
+ string memory dependencyNameAndVersion
194
+ ) external view returns (string memory) {
195
+ bytes memory dependencyScript = _getDependencyScriptBytes(
196
+ dependencyNameAndVersion.stringToBytes32()
197
+ );
198
+
199
+ return string(dependencyScript);
200
+ }
201
+
202
+ /**
203
+ * @notice Get the project script for a given core contract address and
204
+ * project ID.
205
+ * @param coreContract The address of the core contract to retrieve
206
+ * the project script from.
207
+ * @param projectId The ID of the project to retrieve the script for.
208
+ * @return The project script stiched together from all of the script chunks as a string.
209
+ * @dev This function will revert if the core contract address is not
210
+ * supported by the DependencyRegistry or if the contract at the address
211
+ * does not implement the IGenArt721CoreProjectScriptV0 or IGenArt721CoreProjectScriptV1.
212
+ */
213
+ function getProjectScript(
214
+ address coreContract,
215
+ uint256 projectId
216
+ ) external view returns (string memory) {
217
+ bytes memory projectScript = _getProjectScriptBytes(
218
+ coreContract,
219
+ projectId
220
+ );
221
+
222
+ return string(projectScript);
223
+ }
224
+
225
+ /**
226
+ * @notice Get the data URI for the HTML for a given token (e.g. data:text/html;base64,[html])
227
+ * @param coreContract The address of the core contract the token belongs to.
228
+ * @param tokenId The ID of the token to retrieve the HTML for.
229
+ * @return The data URI for the HTML for the token.
230
+ */
231
+ function getTokenHtmlBase64EncodedDataUri(
232
+ address coreContract,
233
+ uint256 tokenId
234
+ ) external view returns (string memory) {
235
+ HTMLRequest memory htmlRequest = _getTokenHtmlRequest(
236
+ coreContract,
237
+ tokenId
238
+ );
239
+ string memory base64EncodedHTMLDataURI = scriptyBuilder
240
+ .getEncodedHTMLString(htmlRequest);
241
+
242
+ return base64EncodedHTMLDataURI;
243
+ }
244
+
245
+ /**
246
+ * @notice Get the HTML for a given token.
247
+ * @param coreContract The address of the core contract the token belongs to.
248
+ * @param tokenId The ID of the token to retrieve the HTML for.
249
+ * @return The HTML for the token.
250
+ */
251
+ function getTokenHtml(
252
+ address coreContract,
253
+ uint256 tokenId
254
+ ) external view returns (string memory) {
255
+ HTMLRequest memory htmlRequest = _getTokenHtmlRequest(
256
+ coreContract,
257
+ tokenId
258
+ );
259
+ string memory html = scriptyBuilder.getHTMLString(htmlRequest);
260
+
261
+ return html;
262
+ }
263
+
264
+ /**
265
+ * @notice Gets summary of details of how on-chain a project is.
266
+ * @param coreContract The core contract address to query.
267
+ * @param projectId The project ID to query.
268
+ * @return dependencyFullyOnChain Whether the project's dependency is fully on-chain.
269
+ * @return injectsDecentralizedStorageNetworkAssets Whether the project injects decentralized storage network assets.
270
+ * @return hasOffChainFlexDepRegDependencies True if the project uses flex assets of type ART_BLOCKS_DEPENDENCY_REGISTRY
271
+ * that are not fully on-chain; false otherwise.
272
+ */
273
+ function getOnChainStatus(
274
+ address coreContract,
275
+ uint256 projectId
276
+ )
277
+ external
278
+ view
279
+ returns (
280
+ bool dependencyFullyOnChain,
281
+ bool injectsDecentralizedStorageNetworkAssets,
282
+ bool hasOffChainFlexDepRegDependencies
283
+ )
284
+ {
285
+ // get dependency name and version
286
+ bytes32 dependencyNameAndVersion = dependencyRegistry
287
+ .getDependencyNameAndVersionForProject(coreContract, projectId)
288
+ .stringToBytes32();
289
+ dependencyFullyOnChain = _getIsDependencyOnChain(
290
+ dependencyNameAndVersion
291
+ );
292
+
293
+ // iterate over project's flex dependencies to check if they are fully on-chain
294
+ if (_getIsFlex(coreContract)) {
295
+ // @dev all flex (V2, V3) contracts have the function projectExternalAssetDependencyCount()
296
+ uint256 externalAssetDependencyCount = IGenArt721CoreContractV3_Engine_Flex(
297
+ coreContract
298
+ ).projectExternalAssetDependencyCount({_projectId: projectId});
299
+ for (uint256 i = 0; i < externalAssetDependencyCount; i++) {
300
+ // get external asset dependency with data
301
+ IGenArt721CoreContractV3_Engine_Flex.ExternalAssetDependencyWithData
302
+ memory externalAssetDependencyWithData = _getProjectExternalAssetDependencyByIndex({
303
+ coreContract: coreContract,
304
+ projectId: projectId,
305
+ index: i
306
+ });
307
+ // if ipfs or arweave, label injectsDecentralizedStorageNetworkAssets as true
308
+ if (
309
+ externalAssetDependencyWithData.dependencyType ==
310
+ IGenArt721CoreContractV3_Engine_Flex
311
+ .ExternalAssetDependencyType
312
+ .IPFS ||
313
+ externalAssetDependencyWithData.dependencyType ==
314
+ IGenArt721CoreContractV3_Engine_Flex
315
+ .ExternalAssetDependencyType
316
+ .ARWEAVE
317
+ ) {
318
+ // if any dependency is IPFS or ARWEAVE, label injectsDecentralizedStorageNetworkAssets as true
319
+ injectsDecentralizedStorageNetworkAssets = true;
320
+ } else if (
321
+ externalAssetDependencyWithData.dependencyType ==
322
+ IGenArt721CoreContractV3_Engine_Flex
323
+ .ExternalAssetDependencyType
324
+ .ART_BLOCKS_DEPENDENCY_REGISTRY
325
+ ) {
326
+ // get the bytes representation of the dependencyRegistryAsset
327
+ bytes32 currentDependencyNameAndVersion = externalAssetDependencyWithData
328
+ .cid
329
+ .stringToBytes32();
330
+ bool currentDependencyFullyOnChain = _getIsDependencyOnChain(
331
+ currentDependencyNameAndVersion
332
+ );
333
+ if (!(currentDependencyFullyOnChain)) {
334
+ // return (true, true, true);
335
+ // // if any dependency is not fully on-chain, label usesDependencyRegistryFlexAssetsNotFullyOnChain as true
336
+ hasOffChainFlexDepRegDependencies = true;
337
+ }
338
+ }
339
+ }
340
+ }
341
+
342
+ // @dev all return values previously populated or remain at initial values of false
343
+ }
344
+
345
+ /**
346
+ * @notice Get the dependency script for a given dependency name and version.
347
+ * @param dependencyNameAndVersion The name and version of the dependency
348
+ * to retrieve the script for.
349
+ * @return The dependency script stiched together from all of the script chunks.
350
+ * @dev This function will revert if the dependency name and version is not
351
+ * supported by the DependencyRegistry or if the script storage version is
352
+ * not supported.
353
+ */
354
+ function _getDependencyScriptBytes(
355
+ bytes32 dependencyNameAndVersion
356
+ ) internal view returns (bytes memory) {
357
+ uint256 scriptCount = dependencyRegistry.getDependencyScriptCount(
358
+ dependencyNameAndVersion
359
+ );
360
+
361
+ if (scriptCount == 0) {
362
+ return "";
363
+ }
364
+
365
+ address[] memory scriptBytecodeAddresses = new address[](scriptCount);
366
+
367
+ for (uint256 i = 0; i < scriptCount; i++) {
368
+ scriptBytecodeAddresses[i] = dependencyRegistry
369
+ .getDependencyScriptBytecodeAddress(
370
+ dependencyNameAndVersion,
371
+ i
372
+ );
373
+ }
374
+
375
+ // @dev We concatenate the script chunks together with assembly
376
+ // in AddressChunks for gas efficiency.
377
+ return
378
+ AddressChunks.mergeChunks(
379
+ scriptBytecodeAddresses,
380
+ address(universalBytecodeStorageReader)
381
+ );
382
+ }
383
+
384
+ /**
385
+ * @notice Get the project script for a given core contract address and
386
+ * project ID.
387
+ * @param coreContract The address of the core contract to retrieve
388
+ * the project script from.
389
+ * @param projectId The ID of the project to retrieve the script for.
390
+ * @return The project script stiched together from all of the script chunks.
391
+ * @dev This function will revert if the core contract address is not
392
+ * supported by the DependencyRegistry or if the contract at the address
393
+ * does not implement the IGenArt721CoreProjectScriptV0 or IGenArt721CoreProjectScriptV1.
394
+ */
395
+ function _getProjectScriptBytes(
396
+ address coreContract,
397
+ uint256 projectId
398
+ ) internal view returns (bytes memory) {
399
+ _onlySupportedCoreContract(coreContract);
400
+
401
+ // @dev Attempt to get project script info from V3 and up core contracts first.
402
+ try
403
+ IGenArt721CoreProjectScriptV1(coreContract).projectScriptDetails(
404
+ projectId
405
+ )
406
+ returns (string memory, string memory, uint256 scriptCount) {
407
+ if (scriptCount == 0) {
408
+ return "";
409
+ }
410
+
411
+ address[] memory scriptBytecodeAddresses = new address[](
412
+ scriptCount
413
+ );
414
+
415
+ for (uint256 i = 0; i < scriptCount; i++) {
416
+ scriptBytecodeAddresses[i] = IGenArt721CoreProjectScriptV1(
417
+ coreContract
418
+ ).projectScriptBytecodeAddressByIndex(projectId, i);
419
+ }
420
+
421
+ // @dev We concatenate the script chunks together with assembly
422
+ // in AddressChunks for gas efficiency.
423
+ return
424
+ AddressChunks.mergeChunks(
425
+ scriptBytecodeAddresses,
426
+ address(universalBytecodeStorageReader)
427
+ );
428
+ } catch {
429
+ // Noop try again for older contracts.
430
+ }
431
+
432
+ // @dev If we failed to get the project script info try again using the interface
433
+ // for V2 and older core contracts.
434
+ try
435
+ IGenArt721CoreProjectScriptV0(coreContract).projectScriptInfo(
436
+ projectId
437
+ )
438
+ returns (string memory, uint256 scriptCount) {
439
+ if (scriptCount == 0) {
440
+ return "";
441
+ }
442
+
443
+ string memory script;
444
+ for (uint256 i = 0; i < scriptCount; i++) {
445
+ string memory scriptChunk = IGenArt721CoreProjectScriptV0(
446
+ coreContract
447
+ ).projectScriptByIndex(projectId, i);
448
+ script = string.concat(script, scriptChunk);
449
+ }
450
+
451
+ return bytes(script);
452
+ } catch {
453
+ revert("Unable to retrieve project script info");
454
+ }
455
+ }
456
+
457
+ /**
458
+ * @notice Get the isFlex status for a given core contract.
459
+ * @dev uses the existence of preferredIPFSGateway function as indicator for flex contracts.
460
+ * @param coreContract The core contract address to check if it is a flex contract.
461
+ */
462
+ function _getIsFlex(address coreContract) internal view returns (bool) {
463
+ try
464
+ // @dev all flex (V2, V3) contracts have this function, so use as isFlex indicator
465
+ IGenArt721CoreContractV3_Engine_Flex(coreContract)
466
+ .preferredIPFSGateway()
467
+ returns (string memory) {
468
+ // if contract did not revert, interpret it is a flex contract
469
+ return true;
470
+ } catch {
471
+ // if contract reverted, interpret it is not a flex contract
472
+ return false;
473
+ }
474
+ }
475
+
476
+ /**
477
+ * @notice Get if a flex contract is a V2 flex contract.
478
+ * Assumes that the core contract is a flex contract.
479
+ * @param flexCoreContract The core contract address to check if it is a V2 flex contract.
480
+ * @return isV2Flex Whether the core contract is a V2 flex contract.
481
+ */
482
+ function _getIsV2Flex(
483
+ address flexCoreContract
484
+ ) internal view returns (bool) {
485
+ // @dev all flex (V2, V3) contracts have the function coreType(),
486
+ // and all V2 flex contracts have the coreType "GenArt721CoreV2_ENGINE_FLEX"
487
+ string memory coreType = IGenArt721CoreContractV3_Engine_Flex(
488
+ flexCoreContract
489
+ ).coreType();
490
+ return
491
+ keccak256(abi.encodePacked(coreType)) ==
492
+ keccak256(abi.encodePacked("GenArt721CoreV2_ENGINE_FLEX"));
493
+ }
494
+
495
+ /**
496
+ * @notice Get the external asset dependency for a given project and index.
497
+ * @dev This function handles both V2 and V3 flex contracts, and converts the legacy V2 external asset dependency
498
+ * type to the V3 external asset dependency type, as the V3 type is a superset of the V2 type.
499
+ * @param coreContract The core contract address the project belongs to.
500
+ * @param projectId The ID of the project to retrieve the external asset dependency for.
501
+ * @param index The index of the external asset dependency to retrieve.
502
+ * @return The external asset dependency for the project and index.
503
+ */
504
+ function _getProjectExternalAssetDependencyByIndex(
505
+ address coreContract,
506
+ uint256 projectId,
507
+ uint256 index
508
+ )
509
+ internal
510
+ view
511
+ returns (
512
+ IGenArt721CoreContractV3_Engine_Flex.ExternalAssetDependencyWithData
513
+ memory
514
+ )
515
+ {
516
+ // pre-allocate generic externalAssetDependencyWithData to avoid dynamic memory allocation
517
+ IGenArt721CoreContractV3_Engine_Flex.ExternalAssetDependencyWithData
518
+ memory externalAssetDependencyWithData = IGenArt721CoreContractV3_Engine_Flex
519
+ .ExternalAssetDependencyWithData({
520
+ cid: "",
521
+ dependencyType: IGenArt721CoreContractV3_Engine_Flex
522
+ .ExternalAssetDependencyType
523
+ .IPFS, // default to IPFS, index 0 of enum
524
+ bytecodeAddress: address(0),
525
+ data: ""
526
+ });
527
+ // @dev flex V2 and V3 have different return types for the function projectExternalAssetDependencyByIndex - must branch logic
528
+ // @dev reference change in return type between V2 and V3 here: https://github.com/ArtBlocks/artblocks-contracts/pull/450
529
+ // @dev acknowledge that this could be function input parameter to avoid one call per dependency, but
530
+ // stack to deep error limits memoization opportunity in functions calling this function
531
+ if (_getIsV2Flex(coreContract)) {
532
+ ILegacyGenArt721CoreV2_PBAB_Flex.LegacyExternalAssetDependencyWithoutData
533
+ memory legacyExternalAssetDependencyWithoutData = ILegacyGenArt721CoreV2_PBAB_Flex(
534
+ coreContract
535
+ ).projectExternalAssetDependencyByIndex({
536
+ _projectId: projectId,
537
+ _index: index
538
+ });
539
+ // populate external asset dependency json object
540
+ externalAssetDependencyWithData
541
+ .cid = legacyExternalAssetDependencyWithoutData.cid;
542
+ // @dev legacy external asset dependency types are a subset of V3 external asset dependency types,
543
+ // so we can safely cast the legacy type to the V3 type
544
+ externalAssetDependencyWithData
545
+ .dependencyType = IGenArt721CoreContractV3_Engine_Flex
546
+ .ExternalAssetDependencyType(
547
+ uint256(
548
+ legacyExternalAssetDependencyWithoutData.dependencyType
549
+ )
550
+ );
551
+ // leave data as empty string - V2 contracts do not support data
552
+ } else {
553
+ externalAssetDependencyWithData = IGenArt721CoreContractV3_Engine_Flex(
554
+ coreContract
555
+ ).projectExternalAssetDependencyByIndex({
556
+ _projectId: projectId,
557
+ _index: index
558
+ });
559
+ }
560
+ return externalAssetDependencyWithData;
561
+ }
562
+
563
+ /**
564
+ * @notice get external asset dependency and populate json keys and values,
565
+ * as well as any dependency name and version if the dependency is an
566
+ * ART_BLOCKS_DEPENDENCY_REGISTRY dependency.
567
+ * @param coreContract The core contract address the project belongs to.
568
+ * @param tokenId The ID of the token to retrieve the external asset dependency for.
569
+ * @param index The index of the external asset dependency to retrieve.
570
+ */
571
+ function _getExternalAssetDependencyKeysAndValues(
572
+ address coreContract,
573
+ uint256 tokenId,
574
+ uint256 index
575
+ )
576
+ internal
577
+ view
578
+ returns (
579
+ string[] memory /*keys*/,
580
+ JsonStatic.Json[] memory /*values*/,
581
+ bytes32 /*dependencyNameAndVersion*/
582
+ )
583
+ {
584
+ // get project id from token id
585
+ uint256 projectId = ABHelpers.tokenIdToProjectId(tokenId);
586
+ // default as not an art blocks dependency registry dependency
587
+ bytes32 dependencyNameAndVersion; // default as not an art blocks dependency registry dependency
588
+ // each external asset dependency has 3 fields, so pre-allocate array to avoid dynamic memory allocation
589
+ JsonStatic.Json[] memory dependencyValues = JsonStatic.newValuesArray(
590
+ 3
591
+ );
592
+ string[] memory dependencyKeys = JsonStatic.newKeysArray(3);
593
+ // get external asset dependency with data
594
+ IGenArt721CoreContractV3_Engine_Flex.ExternalAssetDependencyWithData
595
+ memory externalAssetDependencyWithData = _getProjectExternalAssetDependencyByIndex({
596
+ coreContract: coreContract,
597
+ projectId: projectId,
598
+ index: index
599
+ });
600
+ // populate external asset dependency json object
601
+ dependencyKeys[0] = "dependency_type";
602
+ dependencyValues[0] = JsonStatic.newStringElement({
603
+ value: _dependencyTypeToString(
604
+ externalAssetDependencyWithData.dependencyType
605
+ ),
606
+ stringEncodingFlag: JsonStatic.StringEncodingFlag.NONE
607
+ });
608
+ dependencyKeys[1] = "cid";
609
+ dependencyValues[1] = JsonStatic.newStringElement({
610
+ value: externalAssetDependencyWithData.cid,
611
+ stringEncodingFlag: JsonStatic.StringEncodingFlag.NONE
612
+ });
613
+ dependencyKeys[2] = "data";
614
+ if (
615
+ externalAssetDependencyWithData.dependencyType ==
616
+ IGenArt721CoreContractV3_Engine_Flex
617
+ .ExternalAssetDependencyType
618
+ .ONCHAIN
619
+ ) {
620
+ if (
621
+ keccak256(
622
+ abi.encodePacked(externalAssetDependencyWithData.data)
623
+ ) == keccak256(abi.encodePacked("#web3call_contract#")) // @dev special string indicating a web3call contract
624
+ ) {
625
+ // treat as a web3call contract, inject token parameters based on the web3call contract
626
+ // @dev prepend with "#web3call#" to indicate that the data should be decoded as a web3call
627
+ // with base64 encoded key/value pairs
628
+ dependencyValues[2] = JsonStatic.newStringElement({
629
+ value: string.concat(
630
+ "#web3call#",
631
+ _getWeb3CallParameters({
632
+ web3callContract: externalAssetDependencyWithData
633
+ .bytecodeAddress,
634
+ coreContract: coreContract,
635
+ tokenId: tokenId
636
+ })
637
+ ),
638
+ stringEncodingFlag: JsonStatic.StringEncodingFlag.NONE // we base64 encode everything in the _getWeb3CallParameters function
639
+ });
640
+ } else {
641
+ // @dev typical ONCHAIN dependency, assign data for ONCHAIN dependencies
642
+ dependencyValues[2] = JsonStatic.newStringElement({
643
+ value: externalAssetDependencyWithData.data,
644
+ stringEncodingFlag: JsonStatic.StringEncodingFlag.BASE64
645
+ });
646
+ }
647
+ } else {
648
+ dependencyValues[2] = JsonStatic.newStringElement({
649
+ value: "", // empty string for non-ONCHAIN dependencies
650
+ stringEncodingFlag: JsonStatic.StringEncodingFlag.BASE64
651
+ });
652
+ if (
653
+ externalAssetDependencyWithData.dependencyType ==
654
+ IGenArt721CoreContractV3_Engine_Flex
655
+ .ExternalAssetDependencyType
656
+ .ART_BLOCKS_DEPENDENCY_REGISTRY
657
+ ) {
658
+ // get the bytes representation of the dependencyRegistryAsset
659
+ dependencyNameAndVersion = externalAssetDependencyWithData
660
+ .cid
661
+ .stringToBytes32();
662
+ }
663
+ }
664
+ return (dependencyKeys, dependencyValues, dependencyNameAndVersion);
665
+ }
666
+
667
+ /**
668
+ * @notice Get the token data for a given token.
669
+ * @param coreContract The core contract address the token belongs to.
670
+ * @param tokenId The ID of the token to retrieve the data for.
671
+ * @return tokenDataJson The token data as a JSON string as bytes.
672
+ * @return dependencyRegistryAssetNameAndVersions Any dependency registry asset name and versions
673
+ * as bytes32 (will contain default-value bytes32 if not an ART_BLOCKS_DEPENDENCY_REGISTRY dependency).
674
+ */
675
+ function _getTokenDataAndDependencyRegistryAssets(
676
+ address coreContract,
677
+ uint256 tokenId
678
+ )
679
+ internal
680
+ view
681
+ returns (
682
+ bytes memory tokenDataJson,
683
+ bytes32[] memory dependencyRegistryAssetNameAndVersions
684
+ )
685
+ {
686
+ // get any flex assets
687
+ bool isFlex = _getIsFlex({coreContract: coreContract});
688
+
689
+ // build tokenData json object
690
+ string[] memory tokenDataKeys = isFlex
691
+ ? JsonStatic.newKeysArray(5)
692
+ : JsonStatic.newKeysArray(2);
693
+ JsonStatic.Json[] memory tokenDataValues = isFlex
694
+ ? JsonStatic.newValuesArray(5)
695
+ : JsonStatic.newValuesArray(2);
696
+
697
+ // token id
698
+ tokenDataKeys[0] = "tokenId";
699
+ tokenDataValues[0] = JsonStatic.newStringElement({
700
+ value: Strings.toString(tokenId),
701
+ stringEncodingFlag: JsonStatic.StringEncodingFlag.NONE
702
+ });
703
+
704
+ // token hash
705
+ // @dev block scope to avoid stack too deep error
706
+ {
707
+ // @dev Attempt to get token hash from V1 and up core contracts first.
708
+ (bytes32 tokenHash, bool isV0CoreContract) = _getTokenHash(
709
+ coreContract,
710
+ tokenId
711
+ );
712
+ if (isV0CoreContract) {
713
+ // @dev V0 contracts return an array of hashes, with only one hash
714
+ tokenDataKeys[1] = "hashes";
715
+ JsonStatic.Json[] memory tokenDataValuesHashes = JsonStatic
716
+ .newValuesArray(1);
717
+ tokenDataValuesHashes[0] = JsonStatic.newStringElement({
718
+ value: Strings.toHexString(uint256(tokenHash)),
719
+ stringEncodingFlag: JsonStatic.StringEncodingFlag.NONE
720
+ });
721
+ tokenDataValues[1] = JsonStatic.newArrayElement({
722
+ values: tokenDataValuesHashes
723
+ });
724
+ } else {
725
+ tokenDataKeys[1] = "hash";
726
+ tokenDataValues[1] = JsonStatic.newStringElement({
727
+ value: Strings.toHexString(uint256(tokenHash)),
728
+ stringEncodingFlag: JsonStatic.StringEncodingFlag.NONE
729
+ });
730
+ }
731
+ }
732
+
733
+ // flex contracts have additional fields
734
+ dependencyRegistryAssetNameAndVersions = new bytes32[](0); // default if no assets or not flex
735
+ if (isFlex) {
736
+ // preferredIPFSGateway
737
+ tokenDataKeys[2] = "preferredArweaveGateway";
738
+ // @dev all flex (V2, V3) contracts have the function preferredArweaveGateway()
739
+ tokenDataValues[2] = JsonStatic.newStringElement({
740
+ value: IGenArt721CoreContractV3_Engine_Flex(coreContract)
741
+ .preferredArweaveGateway(),
742
+ stringEncodingFlag: JsonStatic.StringEncodingFlag.NONE
743
+ });
744
+
745
+ // preferredArweaveGateway
746
+ tokenDataKeys[3] = "preferredIPFSGateway";
747
+ // @dev all flex (V2, V3) contracts have the function preferredIPFSGateway()
748
+ tokenDataValues[3] = JsonStatic.newStringElement({
749
+ value: IGenArt721CoreContractV3_Engine_Flex(coreContract)
750
+ .preferredIPFSGateway(),
751
+ stringEncodingFlag: JsonStatic.StringEncodingFlag.NONE
752
+ });
753
+
754
+ // externalAssetDependencies (variable length array)
755
+ tokenDataKeys[4] = "externalAssetDependencies";
756
+ // @dev pre-allocate array to avoid dynamic memory allocation of variable-length array
757
+ uint256 projectId = ABHelpers.tokenIdToProjectId(tokenId);
758
+ // @dev all flex (V2, V3) contracts have the function projectExternalAssetDependencyCount()
759
+ uint256 externalAssetDependencyCount = IGenArt721CoreContractV3_Engine_Flex(
760
+ coreContract
761
+ ).projectExternalAssetDependencyCount({_projectId: projectId});
762
+ JsonStatic.Json[] memory externalAssetDependencies = JsonStatic
763
+ .newValuesArray(externalAssetDependencyCount);
764
+ // populate the type and version of all ART_BLOCKS_DEPENDENCY_REGISTRY dependencies
765
+ dependencyRegistryAssetNameAndVersions = new bytes32[](
766
+ externalAssetDependencyCount
767
+ );
768
+ for (uint256 i = 0; i < externalAssetDependencyCount; i++) {
769
+ (
770
+ string[] memory dependencyKeys,
771
+ JsonStatic.Json[] memory dependencyValues,
772
+ bytes32 dependencyNameAndVersion
773
+ ) = _getExternalAssetDependencyKeysAndValues({
774
+ coreContract: coreContract,
775
+ tokenId: tokenId,
776
+ index: i
777
+ });
778
+ // handle ART_BLOCKS_DEPENDENCY_REGISTRY dependency type
779
+ if (dependencyNameAndVersion != bytes32(0)) {
780
+ dependencyRegistryAssetNameAndVersions[
781
+ i
782
+ ] = dependencyNameAndVersion;
783
+ }
784
+
785
+ // build tokenData json object
786
+ externalAssetDependencies[i] = JsonStatic.newObjectElement({
787
+ keys: dependencyKeys,
788
+ values: dependencyValues
789
+ });
790
+ }
791
+
792
+ // assign externalAssetDependencies array to tokenDataValues
793
+ tokenDataValues[4] = JsonStatic.newArrayElement(
794
+ externalAssetDependencies
795
+ );
796
+ }
797
+
798
+ // build tokenData json object
799
+ JsonStatic.Json memory tokenData = JsonStatic.newObjectElement({
800
+ keys: tokenDataKeys,
801
+ values: tokenDataValues
802
+ });
803
+
804
+ // return tokenData as bytes-encoded JSON string via write function
805
+ return (
806
+ bytes(tokenData.write()),
807
+ dependencyRegistryAssetNameAndVersions
808
+ );
809
+ }
810
+
811
+ /**
812
+ * @notice populates an empty HTMLTag with script information for a given dependency.
813
+ * Assumes the dependency is available on the dependencyRegistry.
814
+ * Populates the script via on-chain information if available, otherwise injects script tag with src
815
+ * pointing to the preferred CDN.
816
+ * @param dependencyNameAndVersion The name and version of the dependency to populate the script for.
817
+ * @param htmlTag The HTMLTag to populate with the script information, memory reference; modified in place.
818
+ */
819
+ function _populateDependencyScriptHtmlTag(
820
+ bytes32 dependencyNameAndVersion,
821
+ HTMLTag memory htmlTag
822
+ ) internal view {
823
+ // Get script count and preferred CDN for the dependency.
824
+ (
825
+ ,
826
+ ,
827
+ string memory preferredCDN,
828
+ ,
829
+ ,
830
+ ,
831
+ ,
832
+ ,
833
+ uint24 scriptCount
834
+ ) = dependencyRegistry.getDependencyDetails(dependencyNameAndVersion);
835
+
836
+ // If no scripts on-chain, load the script from the preferred CDN.
837
+ if (scriptCount == 0) {
838
+ bool cdnAvailable = bytes(preferredCDN).length > 0;
839
+ // If no CDN is available, we don't need to add any tags.
840
+ // Expected for dependencies like "js@na" and "svg@na".
841
+ htmlTag.tagOpen = cdnAvailable
842
+ ? abi.encodePacked(
843
+ '<script type="text/javascript" src="',
844
+ preferredCDN,
845
+ '">'
846
+ )
847
+ : bytes("");
848
+ htmlTag.tagClose = bytes(cdnAvailable ? "</script>" : "");
849
+ } else {
850
+ bytes memory dependencyScript = _getDependencyScriptBytes(
851
+ dependencyNameAndVersion
852
+ );
853
+ htmlTag.tagContent = dependencyScript;
854
+ htmlTag.tagType = HTMLTagType.scriptGZIPBase64DataURI; // <script type="text/javascript+gzip" src="data:text/javascript;base64,[script]"></script>
855
+ }
856
+ }
857
+
858
+ /**
859
+ * @notice Get the HTMLRequest for a given token.
860
+ * @param coreContract The core contract address the token belongs to.
861
+ * @param tokenId The ID of the token to retrieve the HTMLRequest for.
862
+ * @return The HTMLRequest for the token.
863
+ */
864
+ function _getTokenHtmlRequest(
865
+ address coreContract,
866
+ uint256 tokenId
867
+ ) internal view returns (HTMLRequest memory) {
868
+ _onlySupportedCoreContract(coreContract);
869
+
870
+ uint256 projectId = ABHelpers.tokenIdToProjectId(tokenId);
871
+ // This will revert for older contracts that do not have an override set.
872
+ bytes32 dependencyNameAndVersion = dependencyRegistry
873
+ .getDependencyNameAndVersionForProject(coreContract, projectId)
874
+ .stringToBytes32();
875
+
876
+ // Create head tags
877
+ // pre-fetch data to properly allocate memory for HTML tags
878
+ (
879
+ bytes memory tokenDataJson,
880
+ bytes32[] memory dependencyRegistryAssetNameAndVersions
881
+ ) = _getTokenDataAndDependencyRegistryAssets({
882
+ coreContract: coreContract,
883
+ tokenId: tokenId
884
+ });
885
+ // @dev memoize length for efficiency
886
+ uint256 dependencyRegistryAssetNamesAndVersionsLength = dependencyRegistryAssetNameAndVersions
887
+ .length;
888
+ // @dev length is 2 (style, tokenData) + number of external asset dependencies
889
+ HTMLTag[] memory headTags = new HTMLTag[](
890
+ 2 + dependencyRegistryAssetNamesAndVersionsLength
891
+ );
892
+ headTags[0].tagOpen = "<style>";
893
+ headTags[0]
894
+ .tagContent = "html{height:100%}body{min-height:100%;margin:0;padding:0}canvas{padding:0;margin:auto;display:block;position:absolute;top:0;bottom:0;left:0;right:0}";
895
+ headTags[0].tagClose = "</style>";
896
+
897
+ // @dev decode any base64 encoded flex data in the browser while parsing the json
898
+ headTags[1].tagContent = abi.encodePacked(
899
+ "let tokenData = JSON.parse(`",
900
+ tokenDataJson,
901
+ '`, (key, value) => key === "data" && value !== null ? value.startsWith("#web3call#") ? Object.entries(JSON.parse(atob(value.slice(10)))).reduce((acc, [k, v]) => ((acc[atob(k)] = atob(v)), acc), {}) : atob(value) : value);'
902
+ );
903
+ headTags[1].tagType = HTMLTagType.script;
904
+ for (
905
+ uint256 i = 0;
906
+ i < dependencyRegistryAssetNamesAndVersionsLength;
907
+ i++
908
+ ) {
909
+ // skip if empty (not a dependency registry asset)
910
+ // @dev okay to have empty html tags - they will be ignored
911
+ if (dependencyRegistryAssetNameAndVersions[i] == bytes32(0)) {
912
+ continue;
913
+ }
914
+ // populate head tags with dependency registry scripts
915
+ _populateDependencyScriptHtmlTag(
916
+ dependencyRegistryAssetNameAndVersions[i],
917
+ headTags[2 + i]
918
+ );
919
+ }
920
+
921
+ // Create body tags
922
+ HTMLTag[] memory bodyTags = new HTMLTag[](4);
923
+
924
+ // Dependency script tag
925
+ _populateDependencyScriptHtmlTag(dependencyNameAndVersion, bodyTags[0]);
926
+
927
+ // @dev We expect all of our dependencies to be added gzip'd and base64 encoded
928
+ // so we need to include this so we can gunzip them in the browser.
929
+ bodyTags[1].name = "gunzipScripts-0.0.1.js";
930
+ bodyTags[1].tagType = HTMLTagType.scriptBase64DataURI; // <script src="data:text/javascript;base64,[script]"></script>
931
+ bodyTags[1].tagContent = bytes(
932
+ universalBytecodeStorageReader.readFromBytecode(
933
+ gunzipScriptBytecodeAddress
934
+ )
935
+ );
936
+
937
+ HTMLTag memory canvasTag = _createCanvasTagIfNeeded(
938
+ dependencyNameAndVersion
939
+ );
940
+
941
+ bool isProcessingDep = dependencyNameAndVersion ==
942
+ bytes32("processing-js@1.4.6");
943
+
944
+ bytes memory projectScript = _getProjectScriptBytes(
945
+ coreContract,
946
+ projectId
947
+ );
948
+
949
+ HTMLTag memory projectScriptTag = HTMLTag({
950
+ tagOpen: isProcessingDep
951
+ ? bytes("<script type='application/processing'>")
952
+ : bytes("<script>"),
953
+ tagClose: bytes("</script>"),
954
+ tagType: HTMLTagType.useTagOpenAndClose,
955
+ name: "",
956
+ contractAddress: address(0),
957
+ contractData: "",
958
+ tagContent: projectScript
959
+ });
960
+
961
+ if (isProcessingDep) {
962
+ bodyTags[2] = projectScriptTag;
963
+ bodyTags[3] = canvasTag;
964
+ } else {
965
+ bodyTags[3] = projectScriptTag;
966
+ bodyTags[2] = canvasTag;
967
+ }
968
+
969
+ HTMLRequest memory htmlRequest;
970
+ htmlRequest.headTags = headTags;
971
+ htmlRequest.bodyTags = bodyTags;
972
+
973
+ return htmlRequest;
974
+ }
975
+
976
+ /**
977
+ * @dev Helper function to get token hash with fallback support
978
+ * @return tokenHash The hash for the token
979
+ * @return isV0CoreContract Whether the contract is a V0 core contract
980
+ */
981
+ function _getTokenHash(
982
+ address coreContract,
983
+ uint256 tokenId
984
+ ) private view returns (bytes32 tokenHash, bool isV0CoreContract) {
985
+ // Try V1+ contracts first
986
+ try
987
+ IGenArt721CoreTokenHashProviderV1(coreContract).tokenIdToHash(
988
+ tokenId
989
+ )
990
+ returns (bytes32 hash) {
991
+ if (hash != bytes32(0)) {
992
+ return (hash, false);
993
+ }
994
+ } catch {}
995
+
996
+ // Fallback to V0 contracts
997
+ try
998
+ IGenArt721CoreTokenHashProviderV0(coreContract).showTokenHashes(
999
+ tokenId
1000
+ )
1001
+ returns (bytes32[] memory hashes) {
1002
+ require(hashes[0] != bytes32(0), "Invalid token hash");
1003
+ return (hashes[0], true);
1004
+ } catch {
1005
+ revert("Unable to retrieve token hash");
1006
+ }
1007
+ }
1008
+
1009
+ /**
1010
+ * @dev Helper function to check if a dependency is on chain.
1011
+ * @param dependencyNameAndVersion The name and version of the dependency to check.
1012
+ */
1013
+ function _getIsDependencyOnChain(
1014
+ bytes32 dependencyNameAndVersion
1015
+ ) internal view returns (bool availableOnChain) {
1016
+ // special case for "js@na" and "svg@na" - consider fully on chain
1017
+ if (
1018
+ dependencyNameAndVersion == JS_AT_NA_BYTES32 ||
1019
+ dependencyNameAndVersion == SVG_AT_NA_BYTES32
1020
+ ) {
1021
+ return true;
1022
+ }
1023
+ // query and return result of dependency registry for on-chain status
1024
+ (, , , , , , , availableOnChain, ) = dependencyRegistry
1025
+ .getDependencyDetails(dependencyNameAndVersion);
1026
+ }
1027
+
1028
+ /**
1029
+ * @dev Helper function to get the web3call parameters for a given token.
1030
+ * Assumes the contract supports the IWeb3Call interface.
1031
+ * @param web3callContract The address of the contract to call.
1032
+ * @param coreContract The address of the core contract.
1033
+ * @param tokenId The ID of the token.
1034
+ * @return The web3call parameters for the token as a json string, keys and values encoded
1035
+ * as base64 strings, then the entire json string is encoded as base64.
1036
+ */
1037
+ function _getWeb3CallParameters(
1038
+ address web3callContract,
1039
+ address coreContract,
1040
+ uint256 tokenId
1041
+ ) internal view returns (string memory) {
1042
+ // get the onchain data for the contract
1043
+ IWeb3Call.TokenParam[] memory tokenParams = IWeb3Call(web3callContract)
1044
+ .getTokenParams({coreContract: coreContract, tokenId: tokenId});
1045
+ uint256 tokenParamsLength = tokenParams.length;
1046
+ // build key/value arrays for the token params
1047
+ string[] memory keys = JsonStatic.newKeysArray(tokenParamsLength);
1048
+ JsonStatic.Json[] memory values = JsonStatic.newValuesArray(
1049
+ tokenParamsLength
1050
+ );
1051
+ for (uint256 i = 0; i < tokenParamsLength; i++) {
1052
+ // @dev encode the key here as base64 string, to handle any special characters
1053
+ IWeb3Call.TokenParam memory tokenParam = tokenParams[i];
1054
+ keys[i] = Base64.encode(bytes(tokenParam.key));
1055
+ values[i] = JsonStatic.newStringElement({
1056
+ value: (tokenParam.value),
1057
+ stringEncodingFlag: JsonStatic.StringEncodingFlag.BASE64
1058
+ });
1059
+ }
1060
+ // use JsonStatic to build a printable json object from the key/value arrays
1061
+ JsonStatic.Json memory tokenParamsJson = JsonStatic.newObjectElement({
1062
+ keys: keys,
1063
+ values: values
1064
+ });
1065
+ // @dev base64 encode the entire json object for consistent encoding of data field
1066
+ return Base64.encode(bytes(tokenParamsJson.write()));
1067
+ }
1068
+
1069
+ /**
1070
+ * @dev Helper function to get a canvas tag or an empty tag depending on the dependency name.
1071
+ * @return The canvas tag or an empty tag.
1072
+ */
1073
+ function _createCanvasTagIfNeeded(
1074
+ bytes32 dependencyNameAndVersion
1075
+ ) internal pure returns (HTMLTag memory) {
1076
+ // Extract dependency name before @ symbol
1077
+ uint atSignIndex;
1078
+ for (uint i = 0; i < dependencyNameAndVersion.length; i++) {
1079
+ if (dependencyNameAndVersion[i] == "@") {
1080
+ atSignIndex = i;
1081
+ break;
1082
+ }
1083
+ }
1084
+
1085
+ bytes memory nameBeforeAt = new bytes(atSignIndex);
1086
+ for (uint i = 0; i < atSignIndex; i++) {
1087
+ nameBeforeAt[i] = dependencyNameAndVersion[i];
1088
+ }
1089
+ string memory depNameStr = string(nameBeforeAt);
1090
+
1091
+ // Check if dependency needs canvas
1092
+ bytes32 nameHash = keccak256(nameBeforeAt);
1093
+ if (
1094
+ nameHash == keccak256(bytes("js")) ||
1095
+ nameHash == keccak256(bytes("babylon")) ||
1096
+ nameHash == keccak256(bytes("tone")) ||
1097
+ nameHash == keccak256(bytes("zdog")) ||
1098
+ nameHash == keccak256(bytes("processing-js"))
1099
+ ) {
1100
+ return
1101
+ HTMLTag({
1102
+ tagOpen: abi.encodePacked(
1103
+ "<canvas id='",
1104
+ depNameStr,
1105
+ "-canvas'>"
1106
+ ),
1107
+ tagClose: bytes("</canvas>"),
1108
+ tagType: HTMLTagType.useTagOpenAndClose,
1109
+ name: "",
1110
+ contractAddress: address(0),
1111
+ contractData: "",
1112
+ tagContent: ""
1113
+ });
1114
+ } else {
1115
+ return
1116
+ HTMLTag({
1117
+ tagOpen: "",
1118
+ tagClose: "",
1119
+ tagType: HTMLTagType.useTagOpenAndClose,
1120
+ name: "",
1121
+ contractAddress: address(0),
1122
+ contractData: "",
1123
+ tagContent: ""
1124
+ });
1125
+ }
1126
+ }
1127
+
1128
+ function _dependencyTypeToString(
1129
+ IGenArt721CoreContractV3_Engine_Flex.ExternalAssetDependencyType dependencyType
1130
+ ) internal pure returns (string memory) {
1131
+ if (
1132
+ dependencyType ==
1133
+ IGenArt721CoreContractV3_Engine_Flex
1134
+ .ExternalAssetDependencyType
1135
+ .IPFS
1136
+ ) {
1137
+ return "IPFS";
1138
+ } else if (
1139
+ dependencyType ==
1140
+ IGenArt721CoreContractV3_Engine_Flex
1141
+ .ExternalAssetDependencyType
1142
+ .ARWEAVE
1143
+ ) {
1144
+ return "ARWEAVE";
1145
+ } else if (
1146
+ dependencyType ==
1147
+ IGenArt721CoreContractV3_Engine_Flex
1148
+ .ExternalAssetDependencyType
1149
+ .ONCHAIN
1150
+ ) {
1151
+ return "ONCHAIN";
1152
+ } else if (
1153
+ dependencyType ==
1154
+ IGenArt721CoreContractV3_Engine_Flex
1155
+ .ExternalAssetDependencyType
1156
+ .ART_BLOCKS_DEPENDENCY_REGISTRY
1157
+ ) {
1158
+ return "ART_BLOCKS_DEPENDENCY_REGISTRY";
1159
+ } else {
1160
+ return "UNKNOWN"; // never expected to happen
1161
+ }
1162
+ }
1163
+ }