@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
@@ -0,0 +1,429 @@
1
+ // SPDX-License-Identifier: LGPL-3.0-only
2
+ // Created By: Art Blocks Inc.
3
+
4
+ pragma solidity ^0.8.0;
5
+
6
+ /**
7
+ * @title EnumerableSetUint16
8
+ * @author Art Blocks Inc.
9
+ * @notice Gas-optimized enumerable set library for uint16 values with assembly optimizations.
10
+ * @dev This library efficiently packs uint16 values into shared uint256 storage slots,
11
+ * storing up to 16 uint16 values per slot. This significantly reduces gas costs compared
12
+ * to OpenZeppelin's EnumerableSet.UintSet which stores each value in its own slot.
13
+ *
14
+ * The library maintains:
15
+ * - A packed array where each uint256 slot contains up to 16 uint16 values (stored as value+1)
16
+ * - An index mapping for O(1) lookups (maps value -> packed position)
17
+ *
18
+ * Values are stored as (value + 1) to distinguish empty slots (0) from actual values.
19
+ * This means the maximum storable value is 65534 (not 65535).
20
+ *
21
+ * Count is derived on-demand by examining the last slot to find the highest populated position.
22
+ * This eliminates an SSTORE operation on every add/remove, significantly reducing gas costs.
23
+ *
24
+ * Assembly is used extensively for:
25
+ * - Efficient bit manipulation operations
26
+ * - Optimized storage access patterns
27
+ * - Reduced memory operations
28
+ * - Binary search for finding highest offset
29
+ *
30
+ * Interface is compatible with OpenZeppelin's EnumerableSet.UintSet, but specifically
31
+ * for uint16 values.
32
+ */
33
+ library EnumerableSetUint16 {
34
+ /**
35
+ * @dev Structure to hold the set data.
36
+ *
37
+ * Storage layout:
38
+ * - _values: Array of uint256 where each element packs 16 uint16 values (stored as value+1)
39
+ * - _indexesPacked: Packed mapping where each uint256 contains 16 positions (16 bits each)
40
+ *
41
+ * Position encoding: 16 bits per position = (slotIndex << 4) | offsetInSlot + 1
42
+ * - Bits 0-11: slotIndex (supports up to 4096 slots = 65,536 values)
43
+ * - Bits 12-15: offsetInSlot (0-15)
44
+ * - +1 makes it 1-indexed so 0 means "not present"
45
+ *
46
+ * Packing in _indexesPacked:
47
+ * - Key: value >> 4 (bucket index - groups of 16 values)
48
+ * - Value: uint256 containing 16 packed 16-bit positions
49
+ * - Position in bucket: value & 0xF (determines which 16-bit segment)
50
+ */
51
+ struct Uint16Set {
52
+ // Array of packed uint256 slots, each containing up to 16 uint16 values (as value+1)
53
+ uint256[] _values;
54
+ // Packed mapping: each uint256 holds 16 positions (16 bits each) for 16 consecutive values
55
+ // Bucket (value>>4) maps to uint256 with 16 positions at (value&0xF)*16 bits
56
+ mapping(uint16 => uint256) _indexesPacked;
57
+ }
58
+
59
+ /**
60
+ * @dev Add a value to a set. O(1).
61
+ * Returns true if the value was added to the set, that is if it was not
62
+ * already present.
63
+ * @param value The uint16 value to add. Must be < 65535 (max uint16 - 1).
64
+ */
65
+ function add(Uint16Set storage set, uint16 value) internal returns (bool) {
66
+ require(
67
+ value < type(uint16).max,
68
+ "EnumerableSetUint16: value too large"
69
+ );
70
+
71
+ if (contains(set, value)) {
72
+ return false;
73
+ }
74
+
75
+ uint256 count = length(set);
76
+ uint256 slotIndex;
77
+ uint256 offsetInSlot;
78
+
79
+ assembly {
80
+ // slotIndex = count >> 4 (count / 16)
81
+ slotIndex := shr(4, count)
82
+ // offsetInSlot = count & 0xF (count % 16)
83
+ offsetInSlot := and(count, 0xF)
84
+ }
85
+
86
+ // Ensure the slot exists
87
+ if (slotIndex >= set._values.length) {
88
+ set._values.push(0);
89
+ }
90
+
91
+ // Pack the value+1 into the slot using assembly
92
+ assembly {
93
+ // Calculate storage slot for _values[slotIndex]
94
+ mstore(0x00, set.slot)
95
+ let valuesSlot := keccak256(0x00, 0x20)
96
+ let targetSlot := add(valuesSlot, slotIndex)
97
+
98
+ // Load current slot value
99
+ let slot := sload(targetSlot)
100
+
101
+ // Calculate shift amount: offsetInSlot * 16
102
+ let shiftAmount := shl(4, offsetInSlot)
103
+
104
+ // Create mask: 0xFFFF << shiftAmount
105
+ let mask := shl(shiftAmount, 0xFFFF)
106
+
107
+ // Clear the target position and insert value+1
108
+ // slot = (slot & ~mask) | ((value + 1) << shiftAmount)
109
+ slot := or(and(slot, not(mask)), shl(shiftAmount, add(value, 1)))
110
+
111
+ // Store back
112
+ sstore(targetSlot, slot)
113
+ }
114
+
115
+ // Store the position (1-indexed) in packed format
116
+ // Position encodes: ((slotIndex << 4) | offsetInSlot) + 1
117
+ uint256 position;
118
+ assembly {
119
+ position := add(or(shl(4, slotIndex), offsetInSlot), 1)
120
+ }
121
+ _setPackedIndex(set._indexesPacked, value, position);
122
+
123
+ return true;
124
+ }
125
+
126
+ /**
127
+ * @dev Removes a value from a set. O(1).
128
+ * Returns true if the value was removed from the set, that is if it was
129
+ * present.
130
+ */
131
+ function remove(
132
+ Uint16Set storage set,
133
+ uint16 value
134
+ ) internal returns (bool) {
135
+ uint256 valueIndex = _getPackedIndex(set._indexesPacked, value);
136
+
137
+ if (valueIndex == 0) {
138
+ return false; // Value not in set
139
+ }
140
+
141
+ uint256 lastIndex = length(set) - 1;
142
+ uint256 valuePosition = valueIndex - 1;
143
+
144
+ // Calculate last slot position (used in both branches)
145
+ uint256 lastSlotIndex;
146
+ uint256 lastOffsetInSlot;
147
+ assembly {
148
+ lastSlotIndex := shr(4, lastIndex)
149
+ lastOffsetInSlot := and(lastIndex, 0xF)
150
+ }
151
+
152
+ if (lastIndex != valuePosition) {
153
+ uint256 lastValuePlusOne;
154
+
155
+ assembly {
156
+ // Load last value
157
+ mstore(0x00, set.slot)
158
+ let valuesSlot := keccak256(0x00, 0x20)
159
+ let lastSlot := sload(add(valuesSlot, lastSlotIndex))
160
+
161
+ // Extract last value: (lastSlot >> (lastOffsetInSlot * 16)) & 0xFFFF
162
+ lastValuePlusOne := and(
163
+ shr(shl(4, lastOffsetInSlot), lastSlot),
164
+ 0xFFFF
165
+ )
166
+ }
167
+
168
+ // Move last value to the removed value's position
169
+ uint256 valueSlotIndex;
170
+ uint256 valueOffsetInSlot;
171
+
172
+ assembly {
173
+ valueSlotIndex := shr(4, valuePosition)
174
+ valueOffsetInSlot := and(valuePosition, 0xF)
175
+
176
+ // Calculate storage slot
177
+ mstore(0x00, set.slot)
178
+ let valuesSlot := keccak256(0x00, 0x20)
179
+ let targetSlot := add(valuesSlot, valueSlotIndex)
180
+
181
+ // Load current slot
182
+ let slot := sload(targetSlot)
183
+
184
+ // Calculate shift and mask
185
+ let shiftAmount := shl(4, valueOffsetInSlot)
186
+ let mask := shl(shiftAmount, 0xFFFF)
187
+
188
+ // Update slot: (slot & ~mask) | (lastValuePlusOne << shiftAmount)
189
+ slot := or(
190
+ and(slot, not(mask)),
191
+ shl(shiftAmount, lastValuePlusOne)
192
+ )
193
+
194
+ // Store back
195
+ sstore(targetSlot, slot)
196
+ }
197
+
198
+ // Update the moved value's index
199
+ _setPackedIndex(
200
+ set._indexesPacked,
201
+ uint16(lastValuePlusOne - 1),
202
+ valueIndex
203
+ );
204
+ }
205
+
206
+ // Clear the last position
207
+ bool shouldPop;
208
+
209
+ assembly {
210
+ // Calculate storage slot
211
+ mstore(0x00, set.slot)
212
+ let valuesSlot := keccak256(0x00, 0x20)
213
+ let targetSlot := add(valuesSlot, lastSlotIndex)
214
+
215
+ // Load current slot
216
+ let slot := sload(targetSlot)
217
+
218
+ // Clear the position: slot & ~(0xFFFF << (lastOffsetInSlot * 16))
219
+ let shiftAmount := shl(4, lastOffsetInSlot)
220
+ let mask := shl(shiftAmount, 0xFFFF)
221
+ slot := and(slot, not(mask))
222
+
223
+ // Store back
224
+ sstore(targetSlot, slot)
225
+
226
+ // Check if we should pop: slot is zero
227
+ shouldPop := iszero(slot)
228
+ }
229
+
230
+ // Pop the array if the last slot is now empty
231
+ if (shouldPop && lastSlotIndex == set._values.length - 1) {
232
+ set._values.pop();
233
+ }
234
+
235
+ // Delete the removed value's packed index
236
+ _setPackedIndex(set._indexesPacked, value, 0);
237
+
238
+ return true;
239
+ }
240
+
241
+ /**
242
+ * @dev Returns true if the value is in the set. O(1).
243
+ */
244
+ function contains(
245
+ Uint16Set storage set,
246
+ uint16 value
247
+ ) internal view returns (bool) {
248
+ return _getPackedIndex(set._indexesPacked, value) != 0;
249
+ }
250
+
251
+ /**
252
+ * @dev Returns the number of values in the set. O(1) amortized.
253
+ * Uses binary search to find the highest populated position in the last slot.
254
+ */
255
+ function length(
256
+ Uint16Set storage set
257
+ ) internal view returns (uint256 result) {
258
+ uint256 valuesLength = set._values.length;
259
+
260
+ if (valuesLength == 0) {
261
+ return 0;
262
+ }
263
+
264
+ uint256 lastSlot = set._values[valuesLength - 1];
265
+
266
+ // Use binary search to find highest non-zero 16-bit segment
267
+ uint256 highestOffset;
268
+ assembly {
269
+ let slot := lastSlot
270
+ highestOffset := 0
271
+
272
+ // Binary search for highest non-zero segment
273
+ // Check upper half (bits 128-255)
274
+ let upper := shr(128, slot)
275
+ if gt(upper, 0) {
276
+ highestOffset := 8
277
+ slot := upper
278
+ }
279
+
280
+ // Check upper 4 positions of current 8-position range
281
+ upper := shr(64, slot)
282
+ if gt(upper, 0) {
283
+ highestOffset := add(highestOffset, 4)
284
+ slot := upper
285
+ }
286
+
287
+ // Check upper 2 positions of current 4-position range
288
+ upper := shr(32, slot)
289
+ if gt(upper, 0) {
290
+ highestOffset := add(highestOffset, 2)
291
+ slot := upper
292
+ }
293
+
294
+ // Check upper 1 position of current 2-position range
295
+ upper := shr(16, slot)
296
+ if gt(upper, 0) {
297
+ highestOffset := add(highestOffset, 1)
298
+ }
299
+ }
300
+
301
+ // Calculate total length: ((valuesLength - 1) * 16) + highestOffset + 1
302
+ return ((valuesLength - 1) << 4) + highestOffset + 1;
303
+ }
304
+
305
+ /**
306
+ * @dev Returns the value stored at position `index` in the set. O(1).
307
+ *
308
+ * Note that there are no guarantees on the ordering of values inside the
309
+ * array, and it may change when more values are added or removed.
310
+ *
311
+ * Requirements:
312
+ * - `index` must be strictly less than {length}.
313
+ */
314
+ function at(
315
+ Uint16Set storage set,
316
+ uint256 index
317
+ ) internal view returns (uint16) {
318
+ require(
319
+ index < length(set),
320
+ "EnumerableSetUint16: index out of bounds"
321
+ );
322
+
323
+ uint256 result;
324
+ assembly {
325
+ // slotIndex = index >> 4
326
+ let slotIndex := shr(4, index)
327
+ // offsetInSlot = index & 0xF
328
+ let offsetInSlot := and(index, 0xF)
329
+
330
+ // Load slot value
331
+ mstore(0x00, set.slot)
332
+ let valuesSlot := keccak256(0x00, 0x20)
333
+ let slot := sload(add(valuesSlot, slotIndex))
334
+
335
+ // Extract value: (slot >> (offsetInSlot * 16)) & 0xFFFF - 1
336
+ result := sub(and(shr(shl(4, offsetInSlot), slot), 0xFFFF), 1)
337
+ }
338
+
339
+ return uint16(result);
340
+ }
341
+
342
+ /**
343
+ * @dev Returns an array containing all values in the set. O(N).
344
+ *
345
+ * WARNING: This operation will copy the entire storage to memory, which can be quite expensive.
346
+ * This is designed to mostly be used by view accessors that are queried without any gas fees.
347
+ * Developers should keep in mind that this function has an unbounded cost, and using it as part
348
+ * of a state-changing function may render the function uncallable if the set grows to a point
349
+ * where copying to memory consumes too much gas to fit in a block.
350
+ */
351
+ function values(
352
+ Uint16Set storage set
353
+ ) internal view returns (uint256[] memory) {
354
+ uint256 count = length(set);
355
+ uint256[] memory result = new uint256[](count);
356
+
357
+ for (uint256 i = 0; i < count; i++) {
358
+ result[i] = at(set, i);
359
+ }
360
+
361
+ return result;
362
+ }
363
+
364
+ /**
365
+ * @dev Internal helper to get a packed index for a value.
366
+ * @param packed The packed index mapping.
367
+ * @param value The uint16 value to look up.
368
+ * @return position The position (1-indexed, 0 means not present).
369
+ */
370
+ function _getPackedIndex(
371
+ mapping(uint16 => uint256) storage packed,
372
+ uint16 value
373
+ ) private view returns (uint256 position) {
374
+ assembly {
375
+ // bucketIndex = value >> 4
376
+ let bucketIndex := shr(4, value)
377
+ // posInBucket = value & 0xF
378
+ let posInBucket := and(value, 0xF)
379
+
380
+ // Calculate storage slot for packed[bucketIndex]
381
+ mstore(0x00, bucketIndex)
382
+ mstore(0x20, packed.slot)
383
+ let bucketSlot := keccak256(0x00, 0x40)
384
+
385
+ // Load bucket
386
+ let bucket := sload(bucketSlot)
387
+
388
+ // Extract position: (bucket >> (posInBucket * 16)) & 0xFFFF
389
+ position := and(shr(shl(4, posInBucket), bucket), 0xFFFF)
390
+ }
391
+ }
392
+
393
+ /**
394
+ * @dev Internal helper to set a packed index for a value.
395
+ * @param packed The packed index mapping.
396
+ * @param value The uint16 value to set.
397
+ * @param position The position to store (1-indexed, 0 means remove).
398
+ */
399
+ function _setPackedIndex(
400
+ mapping(uint16 => uint256) storage packed,
401
+ uint16 value,
402
+ uint256 position
403
+ ) private {
404
+ assembly {
405
+ // bucketIndex = value >> 4
406
+ let bucketIndex := shr(4, value)
407
+ // posInBucket = value & 0xF
408
+ let posInBucket := and(value, 0xF)
409
+
410
+ // Calculate storage slot for packed[bucketIndex]
411
+ mstore(0x00, bucketIndex)
412
+ mstore(0x20, packed.slot)
413
+ let bucketSlot := keccak256(0x00, 0x40)
414
+
415
+ // Load current bucket
416
+ let bucket := sload(bucketSlot)
417
+
418
+ // Calculate shift and mask
419
+ let shiftAmount := shl(4, posInBucket)
420
+ let mask := shl(shiftAmount, 0xFFFF)
421
+
422
+ // Update bucket: (bucket & ~mask) | (position << shiftAmount)
423
+ bucket := or(and(bucket, not(mask)), shl(shiftAmount, position))
424
+
425
+ // Store back
426
+ sstore(bucketSlot, bucket)
427
+ }
428
+ }
429
+ }
@@ -0,0 +1,221 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.20;
3
+
4
+ /**
5
+ * @title FeistelWalkLib
6
+ * @author Art Blocks Inc.
7
+ * @notice Uniform once-over traversal of [0..N) via a seeded Feistel permutation.
8
+ * @dev Designed for off-chain eth_call sampling (e.g., pick K=100 from N≈10k).
9
+ * - No duplicates, full coverage if you iterate k=0..N-1
10
+ * - O(1) per index; O(K) to sample K items
11
+ * - Works for any N (uses cycle-walking from next power-of-two domain)
12
+ * - Not cryptographic; optimized for gas efficiency with good mixing
13
+ * Uses 2 Feistel rounds with 64-bit round keys (k0, k1) derived from the seed.
14
+ * Additional keys (k2, k3) reserved for potential future use.
15
+ *
16
+ * The Feistel domain is exactly 2^logM = M (the next power of two >= N) for both
17
+ * even and odd logM, achieved with an UNBALANCED split in `_feistelOnPow2Domain`
18
+ * (`a = logM/2`, `b = logM - a`, `a + b = logM`). This keeps M <= 2N, so the
19
+ * cycle-walk in-range probability is >= ~0.5 and a full traversal (k = 0..N-1) is
20
+ * a true permutation of [0..N) with no duplicates or drops.
21
+ */
22
+ library FeistelWalkLib {
23
+ uint256 private constant MAX_CYCLE_WALKS = 32;
24
+ // -------------------------------------------------------------------------
25
+ // Public API
26
+ // -------------------------------------------------------------------------
27
+
28
+ /// @notice Immutable traversal plan (deterministic from (seed, N)).
29
+ /// @dev Build once per call, then stream with `index(plan, k)` or batch via `sample(plan, K)`.
30
+ struct Plan {
31
+ uint256 N; // pool size (>= 1)
32
+ uint256 M; // next power-of-two >= N (<= 2N)
33
+ uint256 logM; // log2(M) - precomputed to avoid repeated calculation
34
+ uint256 rounds; // Feistel rounds (2 for gas-efficient mixing)
35
+ uint64 k0; // Round key 0
36
+ uint64 k1; // Round key 1
37
+ }
38
+
39
+ /// @notice Build a Feistel permutation plan over [0..N).
40
+ /// @param seed Arbitrary seed (domain-separate upstream if you like).
41
+ /// @param N Domain size; must be > 0.
42
+ function makePlan(
43
+ bytes32 seed,
44
+ uint256 N
45
+ ) internal pure returns (Plan memory p) {
46
+ require(N > 0, "FeistelWalkLib:N=0");
47
+ p.N = N;
48
+ p.M = _nextPow2(N); // <= 2N
49
+ p.logM = _log2ceil(p.M); // precompute to avoid repeated calculation
50
+ p.rounds = 2; // 2 rounds provides good mixing with lower gas cost
51
+
52
+ // Derive round keys for 2-round Feistel
53
+ p.k0 = uint64(
54
+ uint256(keccak256(abi.encodePacked(seed, "feistel.k0", N)))
55
+ );
56
+ p.k1 = uint64(
57
+ uint256(keccak256(abi.encodePacked(seed, "feistel.k1", N)))
58
+ );
59
+ }
60
+
61
+ /// @notice Stream the k-th index in the seeded permutation.
62
+ /// @dev Requires 0 <= k < N. O(1) arithmetic; bounded cycle-walk if N not power of two.
63
+ function index(
64
+ Plan memory p,
65
+ uint256 k
66
+ ) internal pure returns (uint256 idx) {
67
+ require(k < p.N, "FeistelWalkLib:k>=N");
68
+ if (p.N == 1) return 0; // trivial domain
69
+
70
+ // Permute k into [0..N) using Feistel over [0..M) + cycle-walking
71
+ return _feistelPermuteRange(k, p.N, p.M, p.logM, p.rounds, p.k0, p.k1);
72
+ }
73
+
74
+ /// @notice Return up to K indices from the permutation (k = 0..K-1).
75
+ /// @dev If K > N, it clamps to N. Allocates an array of size K'.
76
+ function sample(
77
+ Plan memory p,
78
+ uint256 K
79
+ ) internal pure returns (uint256[] memory out) {
80
+ if (K > p.N) K = p.N;
81
+ out = new uint256[](K);
82
+ unchecked {
83
+ for (uint256 i = 0; i < K; ++i) {
84
+ out[i] = index(p, i);
85
+ }
86
+ }
87
+ }
88
+
89
+ // -------------------------------------------------------------------------
90
+ // Internal: Feistel on arbitrary N via power-of-two domain + cycle-walk
91
+ // -------------------------------------------------------------------------
92
+
93
+ /// @dev Permute x∈[0..N) by embedding into [0..M) (M power of two), running Feistel,
94
+ /// then cycle-walking until result < N. With M < 2N, p = N/M ≥ ~0.5 in worst case.
95
+ /// Hard-cap at MAX_CYCLE_WALKS to guarantee bounded work; on overflow, return `x`.
96
+ function _feistelPermuteRange(
97
+ uint256 x,
98
+ uint256 N,
99
+ uint256 M,
100
+ uint256 logM,
101
+ uint256 rounds,
102
+ uint64 k0,
103
+ uint64 k1
104
+ ) private pure returns (uint256) {
105
+ if (N == 1) return 0; // trivial domain
106
+ uint256 y = x;
107
+ unchecked {
108
+ for (uint256 i = 0; i < MAX_CYCLE_WALKS; ++i) {
109
+ uint256 z = _feistelOnPow2Domain(y, M, logM, rounds, k0, k1);
110
+ if (z < N) return z; // landed inside domain
111
+ y = z; // cycle-walk and try again
112
+ }
113
+ }
114
+ // Ultra-rare guard: deterministic in-domain fallback (keeps progress).
115
+ return x;
116
+ }
117
+
118
+ /// @dev Feistel permutation over [0..M) where M is a power of two.
119
+ /// Split into a low half (a bits) and a high half (b bits) with
120
+ /// a + b = logM, and apply the round function twice for good mixing.
121
+ /// Using an UNBALANCED split (a = logM/2, b = logM - a) keeps the domain
122
+ /// exactly 2^logM = M for both even and odd logM. A balanced split
123
+ /// (half = (logM + 1) / 2) would span 2*half = logM + 1 bits for odd logM
124
+ /// and therefore permute [0, 2M) instead of [0, M); the wider domain pushes
125
+ /// the cycle-walk past its cap for N just above a power of two and triggers
126
+ /// the identity `return x` fallback, breaking the bijection (duplicate /
127
+ /// missing elements). Each round masks its output to the width of the half
128
+ /// it writes, so every round is invertible and the whole map is a bijection
129
+ /// over [0, M). For even logM, a == b and this is identical to a balanced
130
+ /// split.
131
+ function _feistelOnPow2Domain(
132
+ uint256 x,
133
+ uint256 M,
134
+ uint256 logM,
135
+ uint256 /* rounds */,
136
+ uint64 k0,
137
+ uint64 k1
138
+ ) private pure returns (uint256) {
139
+ if (M == 1) return 0; // degenerate
140
+ if (M == 2) {
141
+ // Special case: 2-element domain, use key to determine permutation
142
+ return ((k0 & 1) == 0) ? x : (1 - x);
143
+ }
144
+
145
+ // Full assembly for maximum gas efficiency
146
+ uint256 result;
147
+ assembly {
148
+ // Unbalanced Feistel: low half is `a` bits, high half is `b` bits,
149
+ // with a + b = logM (so the domain is exactly 2^logM = M).
150
+ let a := div(logM, 2)
151
+ let b := sub(logM, a)
152
+ let maskA := sub(shl(a, 1), 1)
153
+ let maskB := sub(shl(b, 1), 1)
154
+
155
+ // Split into L (low, a bits) and R (high, b bits)
156
+ let L := and(x, maskA)
157
+ let R := and(shr(a, x), maskB)
158
+
159
+ // Round 0: R (b bits) -> a-bit register
160
+ let F := and(R, 0xFFFFFFFFFFFFFFFF)
161
+ F := xor(F, k0)
162
+ F := xor(F, shl(13, F))
163
+ F := xor(F, shr(7, F))
164
+ F := xor(F, shl(17, F))
165
+ F := xor(F, shr(5, F))
166
+
167
+ let newR := and(xor(L, F), maskA) // a bits
168
+ L := R // b bits
169
+ R := newR // a bits
170
+
171
+ // Round 1: R (a bits) -> b-bit register
172
+ F := and(R, 0xFFFFFFFFFFFFFFFF)
173
+ F := xor(F, xor(k1, 1))
174
+ F := xor(F, shl(13, F))
175
+ F := xor(F, shr(7, F))
176
+ F := xor(F, shl(17, F))
177
+ F := xor(F, shr(5, F))
178
+
179
+ newR := and(xor(L, F), maskB) // b bits
180
+ L := R // a bits
181
+ R := newR // b bits
182
+
183
+ // Recombine: R (b bits) high, L (a bits) low => a + b = logM bits
184
+ result := or(shl(a, R), L)
185
+ }
186
+ return result;
187
+ }
188
+
189
+ // -------------------------------------------------------------------------
190
+ // Internal: Bit helpers
191
+ // -------------------------------------------------------------------------
192
+
193
+ /// @dev Next power of two ≥ x. For x==0, returns 1.
194
+ function _nextPow2(uint256 x) private pure returns (uint256) {
195
+ if (x <= 1) return 1;
196
+ unchecked {
197
+ x -= 1;
198
+ x |= x >> 1;
199
+ x |= x >> 2;
200
+ x |= x >> 4;
201
+ x |= x >> 8;
202
+ x |= x >> 16;
203
+ x |= x >> 32;
204
+ x |= x >> 64;
205
+ x |= x >> 128;
206
+ return x + 1;
207
+ }
208
+ }
209
+
210
+ /// @dev ceil(log2(x)) for x≥1. (Number of bits to represent x-1.)
211
+ function _log2ceil(uint256 x) private pure returns (uint256 n) {
212
+ require(x > 0, "log2ceil(0)");
213
+ unchecked {
214
+ x -= 1;
215
+ while (x > 0) {
216
+ x >>= 1;
217
+ ++n;
218
+ }
219
+ }
220
+ }
221
+ }