@artblocks/contracts 1.0.4 → 1.1.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 (120) hide show
  1. package/README.md +2 -2
  2. package/artifacts/contracts/AdminACLV1.sol/AdminACLV1.json +2 -2
  3. package/artifacts/contracts/DependencyRegistryV0.sol/DependencyRegistryV0.json +97 -10
  4. package/artifacts/contracts/GenArt721CoreV3.sol/GenArt721CoreV3.json +4 -4
  5. package/artifacts/contracts/engine/V3/GenArt721CoreV3_Engine.sol/GenArt721CoreV3_Engine.json +4 -9
  6. package/artifacts/contracts/engine/V3/GenArt721CoreV3_Engine_Flex.sol/GenArt721CoreV3_Engine_Flex.json +4 -9
  7. package/artifacts/contracts/engine/V3/forks/GenArt721CoreV3_Engine_Flex_PROOF.sol/GenArt721CoreV3_Engine_Flex_PROOF.json +4 -9
  8. package/artifacts/contracts/engine/V3/forks/PROHIBITION/GenArt721CoreV3_Engine_Flex_PROHIBITION.sol/GenArt721CoreV3_Engine_Flex_PROHIBITION.json +4 -9
  9. package/artifacts/contracts/engine-registry/CoreRegistryV1.sol/CoreRegistryV1.json +12 -12
  10. package/artifacts/contracts/explorations/GenArt721CoreV3_Explorations.sol/GenArt721CoreV3_Explorations.json +4 -4
  11. package/artifacts/contracts/interfaces/v0.8.x/ICoreRegistryV1.sol/ICoreRegistryV1.json +6 -6
  12. package/artifacts/contracts/interfaces/v0.8.x/IDependencyRegistryV0.sol/IDependencyRegistryV0.json +19 -0
  13. package/artifacts/contracts/interfaces/v0.8.x/IMinterFilterV1.sol/IMinterFilterV1.json +22 -22
  14. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterDAExpSettlementV0.sol/ISharedMinterDAExpSettlementV0.json +8 -101
  15. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterDAExpV0.sol/ISharedMinterDAExpV0.json +1 -57
  16. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterDALinV0.sol/ISharedMinterDALinV0.json +1 -57
  17. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterDAV0.sol/ISharedMinterDAV0.json +2 -21
  18. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterHolderERC20V0.sol/ISharedMinterHolderERC20V0.json +158 -0
  19. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterHolderV0.sol/ISharedMinterHolderV0.json +15 -90
  20. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterMerkleV0.sol/ISharedMinterMerkleV0.json +10 -36
  21. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterSEAV0.sol/ISharedMinterSEAV0.json +4 -236
  22. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterSimplePurchaseV0.sol/ISharedMinterSimplePurchaseV0.json +5 -5
  23. package/artifacts/contracts/interfaces/v0.8.x/ISharedMinterV0.sol/ISharedMinterV0.json +7 -423
  24. package/artifacts/contracts/interfaces/v0.8.x/ISharedRandomizerV0.sol/ISharedRandomizerV0.json +17 -17
  25. package/artifacts/contracts/libs/v0.8.x/ABHelpers.sol/ABHelpers.json +2 -2
  26. package/artifacts/contracts/libs/v0.8.x/AuthLib.sol/AuthLib.json +2 -2
  27. package/artifacts/contracts/libs/v0.8.x/Bytes32Strings.sol/Bytes32Strings.json +2 -2
  28. package/artifacts/contracts/libs/v0.8.x/minter-libs/DAExpLib.sol/DAExpLib.json +60 -3
  29. package/artifacts/contracts/libs/v0.8.x/minter-libs/DALib.sol/DALib.json +30 -0
  30. package/artifacts/contracts/libs/v0.8.x/minter-libs/DALinLib.sol/DALinLib.json +60 -3
  31. package/artifacts/contracts/libs/v0.8.x/minter-libs/GenericMinterEventsLib.sol/GenericMinterEventsLib.json +346 -0
  32. package/artifacts/contracts/libs/v0.8.x/minter-libs/MaxInvocationsLib.sol/MaxInvocationsLib.json +29 -3
  33. package/artifacts/contracts/libs/v0.8.x/minter-libs/MerkleLib.sol/MerkleLib.json +30 -3
  34. package/artifacts/contracts/libs/v0.8.x/minter-libs/PolyptychLib.sol/PolyptychLib.json +2 -2
  35. package/artifacts/contracts/libs/v0.8.x/minter-libs/SEALib.sol/SEALib.json +254 -3
  36. package/artifacts/contracts/libs/v0.8.x/minter-libs/SetPriceLib.sol/SetPriceLib.json +48 -3
  37. package/artifacts/contracts/libs/v0.8.x/minter-libs/SettlementExpLib.sol/SettlementExpLib.json +41 -3
  38. package/artifacts/contracts/libs/v0.8.x/minter-libs/SplitFundsLib.sol/SplitFundsLib.json +35 -3
  39. package/artifacts/contracts/libs/v0.8.x/minter-libs/TokenHolderLib.sol/TokenHolderLib.json +79 -3
  40. package/artifacts/contracts/minter-suite/MinterFilter/MinterFilterV1.sol/MinterFilterV1.json +2 -2
  41. package/artifacts/contracts/minter-suite/MinterFilter/MinterFilterV2.sol/MinterFilterV2.json +41 -41
  42. package/artifacts/contracts/minter-suite/Minters/MinterDAExpHolderV5.sol/MinterDAExpHolderV5.json +66 -632
  43. package/artifacts/contracts/minter-suite/Minters/MinterDAExpSettlementV2.sol/MinterDAExpSettlementV2.json +2 -20
  44. package/artifacts/contracts/minter-suite/Minters/MinterDAExpSettlementV3.sol/MinterDAExpSettlementV3.json +67 -594
  45. package/artifacts/contracts/minter-suite/Minters/MinterDAExpV5.sol/MinterDAExpV5.json +33 -524
  46. package/artifacts/contracts/minter-suite/Minters/MinterDALinHolderV5.sol/MinterDALinHolderV5.json +66 -632
  47. package/artifacts/contracts/minter-suite/Minters/MinterDALinV5.sol/MinterDALinV5.json +33 -524
  48. package/artifacts/contracts/minter-suite/Minters/MinterSEAV1.sol/MinterSEAV1.json +51 -717
  49. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceERC20V5.sol/MinterSetPriceERC20V5.json +58 -454
  50. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceHolderV5.sol/MinterSetPriceHolderV5.json +61 -552
  51. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceMerkleV5.sol/MinterSetPriceMerkleV5.json +55 -497
  52. package/artifacts/contracts/minter-suite/Minters/MinterSetPricePolyptychERC20V5.sol/MinterSetPricePolyptychERC20V5.json +110 -571
  53. package/artifacts/contracts/minter-suite/Minters/MinterSetPricePolyptychV5.sol/MinterSetPricePolyptychV5.json +69 -560
  54. package/artifacts/contracts/minter-suite/Minters/MinterSetPriceV5.sol/MinterSetPriceV5.json +28 -444
  55. package/artifacts/contracts/mock/DummySharedMinter.sol/DummySharedMinter.json +2 -2
  56. package/artifacts/contracts/mock/GenArt721CoreV3_Engine_IncorrectCoreType.sol/GenArt721CoreV3_Engine_IncorrectCoreType.json +4 -9
  57. package/artifacts/contracts/mock/OriginRegisterMock.sol/OriginRegisterMock.json +2 -2
  58. package/artifacts/contracts/mock/ReentrancyHolderMockShared.sol/ReentrancyHolderMockShared.json +136 -0
  59. package/artifacts/contracts/mock/ReentrancyMerkleMockShared.sol/ReentrancyMerkleMockShared.json +105 -0
  60. package/artifacts/contracts/mock/ReentrancyMockShared.sol/ReentrancyMockShared.json +100 -0
  61. package/artifacts/contracts/mock/ReentrancySEAMockShared.sol/ReentrancySEAAutoBidderMockShared.json +69 -0
  62. package/artifacts/contracts/randomizer/shared/SharedRandomizerV0.sol/SharedRandomizerV0.json +19 -19
  63. package/contracts/DependencyRegistryV0.sol +84 -16
  64. package/contracts/archive/readme.md +16 -0
  65. package/contracts/engine/README.md +21 -0
  66. package/contracts/engine/V3/GenArt721CoreV3_Engine.sol +4 -10
  67. package/contracts/engine/V3/GenArt721CoreV3_Engine_Flex.sol +4 -10
  68. package/contracts/engine/V3/forks/GenArt721CoreV3_Engine_Flex_PROOF.sol +4 -10
  69. package/contracts/engine/V3/forks/PROHIBITION/GenArt721CoreV3_Engine_Flex_PROHIBITION.sol +4 -10
  70. package/contracts/engine-registry/CoreRegistryV1.sol +58 -65
  71. package/contracts/interfaces/v0.8.x/ICoreRegistryV1.sol +6 -8
  72. package/contracts/interfaces/v0.8.x/IDependencyRegistryV0.sol +3 -0
  73. package/contracts/interfaces/v0.8.x/IMinterFilterV1.sol +25 -25
  74. package/contracts/interfaces/v0.8.x/ISharedMinterDAExpSettlementV0.sol +11 -20
  75. package/contracts/interfaces/v0.8.x/ISharedMinterDAExpV0.sol +1 -14
  76. package/contracts/interfaces/v0.8.x/ISharedMinterDALinV0.sol +1 -15
  77. package/contracts/interfaces/v0.8.x/ISharedMinterDAV0.sol +2 -8
  78. package/contracts/interfaces/v0.8.x/ISharedMinterHolderERC20V0.sol +47 -0
  79. package/contracts/interfaces/v0.8.x/ISharedMinterHolderV0.sol +15 -43
  80. package/contracts/interfaces/v0.8.x/ISharedMinterMerkleV0.sol +10 -20
  81. package/contracts/interfaces/v0.8.x/ISharedMinterSEAV0.sol +4 -67
  82. package/contracts/interfaces/v0.8.x/ISharedMinterSimplePurchaseV0.sol +5 -5
  83. package/contracts/interfaces/v0.8.x/ISharedMinterV0.sol +7 -155
  84. package/contracts/interfaces/v0.8.x/ISharedRandomizerV0.sol +37 -37
  85. package/contracts/libs/v0.8.x/ABHelpers.sol +14 -14
  86. package/contracts/libs/v0.8.x/AuthLib.sol +101 -102
  87. package/contracts/libs/v0.8.x/Bytes32Strings.sol +5 -5
  88. package/contracts/libs/v0.8.x/minter-libs/DAExpLib.sol +163 -38
  89. package/contracts/libs/v0.8.x/minter-libs/DALib.sol +26 -0
  90. package/contracts/libs/v0.8.x/minter-libs/DALinLib.sol +144 -37
  91. package/contracts/libs/v0.8.x/minter-libs/GenericMinterEventsLib.sol +171 -0
  92. package/contracts/libs/v0.8.x/minter-libs/MaxInvocationsLib.sol +250 -110
  93. package/contracts/libs/v0.8.x/minter-libs/MerkleLib.sol +257 -48
  94. package/contracts/libs/v0.8.x/minter-libs/PolyptychLib.sol +138 -58
  95. package/contracts/libs/v0.8.x/minter-libs/SEALib.sol +778 -103
  96. package/contracts/libs/v0.8.x/minter-libs/SetPriceLib.sol +135 -13
  97. package/contracts/libs/v0.8.x/minter-libs/SettlementExpLib.sol +567 -187
  98. package/contracts/libs/v0.8.x/minter-libs/SplitFundsLib.sol +480 -322
  99. package/contracts/libs/v0.8.x/minter-libs/TokenHolderLib.sol +214 -76
  100. package/contracts/minter-suite/MinterFilter/MinterFilterV2.sol +347 -304
  101. package/contracts/minter-suite/Minters/MinterDAExpHolderV5.sol +391 -491
  102. package/contracts/minter-suite/Minters/MinterDAExpSettlementV2.sol +1 -54
  103. package/contracts/minter-suite/Minters/MinterDAExpSettlementV3.sol +388 -628
  104. package/contracts/minter-suite/Minters/MinterDAExpV5.sol +212 -273
  105. package/contracts/minter-suite/Minters/MinterDALinHolderV5.sol +393 -488
  106. package/contracts/minter-suite/Minters/MinterDALinV5.sol +220 -277
  107. package/contracts/minter-suite/Minters/MinterSEAV1.sol +327 -664
  108. package/contracts/minter-suite/Minters/MinterSetPriceERC20V5.sol +278 -303
  109. package/contracts/minter-suite/Minters/MinterSetPriceHolderV5.sol +355 -446
  110. package/contracts/minter-suite/Minters/MinterSetPriceMerkleV5.sol +328 -416
  111. package/contracts/minter-suite/Minters/MinterSetPricePolyptychERC20V5.sol +538 -622
  112. package/contracts/minter-suite/Minters/MinterSetPricePolyptychV5.sol +429 -553
  113. package/contracts/minter-suite/Minters/MinterSetPriceV5.sol +180 -227
  114. package/contracts/mock/GenArt721CoreV3_Engine_IncorrectCoreType.sol +3 -10
  115. package/contracts/mock/ReentrancyHolderMockShared.sol +59 -0
  116. package/contracts/mock/ReentrancyMerkleMockShared.sol +58 -0
  117. package/contracts/mock/ReentrancyMockShared.sol +48 -0
  118. package/contracts/mock/ReentrancySEAMockShared.sol +40 -0
  119. package/contracts/randomizer/shared/SharedRandomizerV0.sol +78 -70
  120. package/package.json +39 -33
@@ -1,10 +1,12 @@
1
1
  // SPDX-License-Identifier: LGPL-3.0-only
2
2
  // Created By: Art Blocks Inc.
3
3
 
4
- import "@openzeppelin-4.7/contracts/utils/cryptography/MerkleProof.sol";
5
-
6
4
  pragma solidity ^0.8.0;
7
5
 
6
+ import {GenericMinterEventsLib} from "./GenericMinterEventsLib.sol";
7
+
8
+ import {MerkleProof} from "@openzeppelin-4.7/contracts/utils/cryptography/MerkleProof.sol";
9
+
8
10
  /**
9
11
  * @title Art Blocks Merkle Library
10
12
  * @notice This library is designed to manage and verify merkle based gating for Art Blocks projects.
@@ -16,6 +18,27 @@ pragma solidity ^0.8.0;
16
18
  library MerkleLib {
17
19
  using MerkleProof for bytes32[];
18
20
 
21
+ /// Events specific to this library ///
22
+ /**
23
+ * @notice Notifies of the contract's default maximum mints allowed per
24
+ * user for a given project, on this minter. This value can be overridden
25
+ * by the artist of any project at any time.
26
+ * @param defaultMaxInvocationsPerAddress The default maximum mints allowed
27
+ */
28
+ event DefaultMaxInvocationsPerAddress(
29
+ uint256 defaultMaxInvocationsPerAddress
30
+ );
31
+ /**
32
+ * @notice Notifies of the contracts' current delegation registry address.
33
+ * @param delegationRegistry The address of the delegation registry
34
+ */
35
+ event DelegationRegistryUpdated(address delegationRegistry);
36
+
37
+ // position of Merkle Lib storage, using a diamond storage pattern for this
38
+ // library
39
+ bytes32 constant MERKLE_LIB_STORAGE_POSITION =
40
+ keccak256("merklelib.storage");
41
+
19
42
  /// @notice Default maximum invocations per address
20
43
  uint256 internal constant DEFAULT_MAX_INVOCATIONS_PER_ADDRESS = 1;
21
44
  bytes32 internal constant CONFIG_MERKLE_ROOT = "merkleRoot";
@@ -37,86 +60,215 @@ library MerkleLib {
37
60
  // The root of the Merkle tree for this project.
38
61
  bytes32 merkleRoot;
39
62
  // The number of current invocations for this project from a given user address.
40
- mapping(address => uint256) userMintInvocations;
63
+ mapping(address user => uint256 mintInvocations) userMintInvocations;
64
+ }
65
+
66
+ // Diamond storage pattern is used in this library
67
+ struct MerkleLibStorage {
68
+ mapping(address coreContract => mapping(uint256 projectId => MerkleProjectConfig)) merkleProjectConfigs;
41
69
  }
42
70
 
43
71
  /**
44
72
  * @notice Sets the maximum number of invocations per address for a project.
45
- * @param _projectConfig Merkle project config.
46
- * @param _maxInvocationsPerAddress The maximum number of invocations per address.
73
+ * @param projectId The ID of the project to set the maximum invocations for.
74
+ * @param coreContract The address of the core contract.
75
+ * @param maxInvocationsPerAddress The maximum number of invocations per address.
47
76
  */
48
77
  function setProjectInvocationsPerAddress(
49
- MerkleProjectConfig storage _projectConfig,
50
- uint24 _maxInvocationsPerAddress
78
+ uint256 projectId,
79
+ address coreContract,
80
+ uint24 maxInvocationsPerAddress
51
81
  ) internal {
52
- _projectConfig.useMaxInvocationsPerAddressOverride = true;
53
- _projectConfig
54
- .maxInvocationsPerAddressOverride = _maxInvocationsPerAddress;
82
+ MerkleProjectConfig
83
+ storage merkleProjectConfig = getMerkleProjectConfig({
84
+ projectId: projectId,
85
+ coreContract: coreContract
86
+ });
87
+ merkleProjectConfig.useMaxInvocationsPerAddressOverride = true;
88
+ merkleProjectConfig
89
+ .maxInvocationsPerAddressOverride = maxInvocationsPerAddress;
90
+ emit GenericMinterEventsLib.ConfigValueSet({
91
+ projectId: projectId,
92
+ coreContract: coreContract,
93
+ key: CONFIG_USE_MAX_INVOCATIONS_PER_ADDRESS_OVERRIDE,
94
+ value: true
95
+ });
96
+ emit GenericMinterEventsLib.ConfigValueSet({
97
+ projectId: projectId,
98
+ coreContract: coreContract,
99
+ key: CONFIG_MAX_INVOCATIONS_OVERRIDE,
100
+ value: uint256(maxInvocationsPerAddress)
101
+ });
55
102
  }
56
103
 
57
104
  /**
58
105
  * @notice Updates the Merkle root of a project.
59
- * @param _projectConfig Merkle project config.
60
- * @param _root The new Merkle root.
106
+ * @param projectId The ID of the project to update.
107
+ * @param coreContract The address of the core contract.
108
+ * @param root The new Merkle root.
61
109
  */
62
110
  function updateMerkleRoot(
63
- MerkleProjectConfig storage _projectConfig,
64
- bytes32 _root
111
+ uint256 projectId,
112
+ address coreContract,
113
+ bytes32 root
114
+ ) internal {
115
+ require(root != bytes32(0), "Root must be provided");
116
+ MerkleProjectConfig
117
+ storage merkleProjectConfig = getMerkleProjectConfig({
118
+ projectId: projectId,
119
+ coreContract: coreContract
120
+ });
121
+ merkleProjectConfig.merkleRoot = root;
122
+ emit GenericMinterEventsLib.ConfigValueSet({
123
+ projectId: projectId,
124
+ coreContract: coreContract,
125
+ key: CONFIG_MERKLE_ROOT,
126
+ value: root
127
+ });
128
+ }
129
+
130
+ /**
131
+ * @notice Checks that a given proof is valid for the vault address, and
132
+ * also checks that the vault address has not exceeded the maximum number
133
+ * of invocations per address for the project.
134
+ * Reverts if the proof is invalid or if the vault address has exceeded the
135
+ * maximum number of invocations per address for the project.
136
+ * @param projectId project id to check
137
+ * @param coreContract core contract address to check
138
+ * @param proof Merkle proof to check
139
+ * @param vault address to check proof against
140
+ */
141
+ function preMintChecks(
142
+ uint256 projectId,
143
+ address coreContract,
144
+ bytes32[] calldata proof,
145
+ address vault
146
+ ) internal view {
147
+ MerkleProjectConfig
148
+ storage merkleProjectConfig = getMerkleProjectConfig({
149
+ projectId: projectId,
150
+ coreContract: coreContract
151
+ });
152
+ // require valid Merkle proof
153
+ require(
154
+ _verifyAddress({
155
+ proofRoot: merkleProjectConfig.merkleRoot,
156
+ proof: proof,
157
+ address_: vault
158
+ }),
159
+ "Invalid Merkle proof"
160
+ );
161
+
162
+ // limit mints per address by project
163
+ uint256 maxProjectInvocationsPerAddress = projectMaxInvocationsPerAddress(
164
+ merkleProjectConfig
165
+ );
166
+
167
+ // note that mint limits index off of the `vault` (when applicable)
168
+ require(
169
+ merkleProjectConfig.userMintInvocations[vault] <
170
+ maxProjectInvocationsPerAddress ||
171
+ maxProjectInvocationsPerAddress == 0,
172
+ "Max invocations reached"
173
+ );
174
+ }
175
+
176
+ /**
177
+ * @notice Updates the number of invocations for the `vault` address on the
178
+ * given project.
179
+ * @param projectId Project Id to mint on
180
+ * @param coreContract Core contract address to mint on
181
+ * @param vault Address being used to mint (the allowlisted address)
182
+ */
183
+ function mintEffects(
184
+ uint256 projectId,
185
+ address coreContract,
186
+ address vault
65
187
  ) internal {
66
- require(_root != bytes32(0), "Must provide root");
67
- _projectConfig.merkleRoot = _root;
188
+ MerkleProjectConfig
189
+ storage merkleProjectConfig = getMerkleProjectConfig({
190
+ projectId: projectId,
191
+ coreContract: coreContract
192
+ });
193
+ // increment mint invocations for vault address
194
+ unchecked {
195
+ // this will never overflow since user's invocations on a project
196
+ // are limited by the project's max invocations
197
+ merkleProjectConfig.userMintInvocations[vault]++;
198
+ }
68
199
  }
69
200
 
70
201
  /**
71
202
  * @notice Hashes an address.
72
- * @param _address The address to hash.
203
+ * @param address_ The address to hash.
73
204
  * @return The hash of the address.
74
205
  */
75
- function hashAddress(address _address) internal pure returns (bytes32) {
76
- return keccak256(abi.encodePacked(_address));
206
+ function hashAddress(address address_) internal pure returns (bytes32) {
207
+ return keccak256(abi.encodePacked(address_));
77
208
  }
78
209
 
79
210
  /**
80
211
  * @notice Processes a proof for an address.
81
- * @param _proof The proof to process.
82
- * @param _address The address to process the proof for.
212
+ * @param proof The proof to process.
213
+ * @param address_ The address to process the proof for.
83
214
  * @return The resulting hash from processing the proof.
84
215
  */
85
216
  function processProofForAddress(
86
- bytes32[] calldata _proof,
87
- address _address
217
+ bytes32[] calldata proof,
218
+ address address_
88
219
  ) internal pure returns (bytes32) {
89
- return _proof.processProofCalldata(hashAddress(_address));
220
+ return proof.processProofCalldata(hashAddress(address_));
90
221
  }
91
222
 
92
223
  /**
93
- * @notice Verifies an address against a proof.
94
- * @param _proofRoot The root of the proof to verify against.
95
- * @param _proof The proof to verify.
96
- * @param _address The address to verify.
97
- * @return True if the address is verified, false otherwise.
224
+ * @notice Returns the maximum number of invocations per address for a project.
225
+ * @param projectConfig The merkle project config to check.
226
+ * @return The maximum number of invocations per address.
98
227
  */
99
- function verifyAddress(
100
- bytes32 _proofRoot,
101
- bytes32[] calldata _proof,
102
- address _address
103
- ) internal pure returns (bool) {
104
- return _proof.verifyCalldata(_proofRoot, hashAddress(_address));
228
+ function projectMaxInvocationsPerAddress(
229
+ MerkleProjectConfig storage projectConfig
230
+ ) internal view returns (uint256) {
231
+ if (projectConfig.useMaxInvocationsPerAddressOverride) {
232
+ return uint256(projectConfig.maxInvocationsPerAddressOverride);
233
+ } else {
234
+ return DEFAULT_MAX_INVOCATIONS_PER_ADDRESS;
235
+ }
105
236
  }
106
237
 
107
238
  /**
108
239
  * @notice Returns the maximum number of invocations per address for a project.
109
- * @param _projectConfig The merkle project config to check.
240
+ * @param projectId Project Id to get config for
241
+ * @param coreContract Core contract address to get config for
110
242
  * @return The maximum number of invocations per address.
111
243
  */
112
244
  function projectMaxInvocationsPerAddress(
113
- MerkleProjectConfig storage _projectConfig
245
+ uint256 projectId,
246
+ address coreContract
114
247
  ) internal view returns (uint256) {
115
- if (_projectConfig.useMaxInvocationsPerAddressOverride) {
116
- return uint256(_projectConfig.maxInvocationsPerAddressOverride);
117
- } else {
118
- return DEFAULT_MAX_INVOCATIONS_PER_ADDRESS;
119
- }
248
+ MerkleProjectConfig storage projectConfig = getMerkleProjectConfig({
249
+ projectId: projectId,
250
+ coreContract: coreContract
251
+ });
252
+ return projectMaxInvocationsPerAddress(projectConfig);
253
+ }
254
+
255
+ /**
256
+ * @notice Returns the number of invocations for a given address on a given
257
+ * project.
258
+ * @param projectId Project Id to query
259
+ * @param coreContract Core contract address to query
260
+ * @param purchaser Address to query
261
+ */
262
+ function projectUserMintInvocations(
263
+ uint256 projectId,
264
+ address coreContract,
265
+ address purchaser
266
+ ) internal view returns (uint256) {
267
+ MerkleProjectConfig storage projectConfig = getMerkleProjectConfig({
268
+ projectId: projectId,
269
+ coreContract: coreContract
270
+ });
271
+ return projectConfig.userMintInvocations[purchaser];
120
272
  }
121
273
 
122
274
  /**
@@ -125,17 +277,27 @@ library MerkleLib {
125
277
  * addresses are only limited by the project's maximum invocations, and a
126
278
  * dummy value of zero is returned for `mintInvocationsRemaining`.
127
279
  * If `projectLimitsMintInvocationsPerAddress` is true, the quantity of
128
- * remaining mint invocations for address `_address` is returned as
280
+ * remaining mint invocations for address `address` is returned as
129
281
  * `mintInvocationsRemaining`.
130
282
  * Note that mint invocations per address can be changed at any time by the
131
283
  * artist of a project.
132
284
  * Also note that all mint invocations are limited by a project's maximum
133
285
  * invocations as defined on the core contract. This function may return
134
286
  * a value greater than the project's remaining invocations.
287
+ * @param projectId Project Id to get remaining invocations on
288
+ * @param coreContract Core contract address of project
289
+ * @param address_ Address to get remaining invocations for
290
+ * @return projectLimitsMintInvocationsPerAddress If true, the project
291
+ * limits mint invocations per address. If false, the project does not
292
+ * limit mint invocations per address.
293
+ * @return mintInvocationsRemaining The number of remaining mint invocations
294
+ * for address `address_`. If `projectLimitsMintInvocationsPerAddress` is
295
+ * false, this value is always dummy zero.
135
296
  */
136
297
  function projectRemainingInvocationsForAddress(
137
- MerkleProjectConfig storage _projectConfig,
138
- address _address
298
+ uint256 projectId,
299
+ address coreContract,
300
+ address address_
139
301
  )
140
302
  internal
141
303
  view
@@ -144,8 +306,12 @@ library MerkleLib {
144
306
  uint256 mintInvocationsRemaining
145
307
  )
146
308
  {
309
+ MerkleProjectConfig storage projectConfig = getMerkleProjectConfig({
310
+ projectId: projectId,
311
+ coreContract: coreContract
312
+ });
147
313
  uint256 maxInvocationsPerAddress = projectMaxInvocationsPerAddress(
148
- _projectConfig
314
+ projectConfig
149
315
  );
150
316
  if (maxInvocationsPerAddress == 0) {
151
317
  // project does not limit mint invocations per address, so leave
@@ -155,8 +321,8 @@ library MerkleLib {
155
321
  // documentation.
156
322
  } else {
157
323
  projectLimitsMintInvocationsPerAddress = true;
158
- uint256 userMintInvocations = _projectConfig.userMintInvocations[
159
- _address
324
+ uint256 userMintInvocations = projectConfig.userMintInvocations[
325
+ address_
160
326
  ];
161
327
  // if user has not reached max invocations per address, return
162
328
  // remaining invocations
@@ -172,4 +338,47 @@ library MerkleLib {
172
338
  // `mintInvocationsRemaining` at solidity initial value of zero
173
339
  }
174
340
  }
341
+
342
+ /**
343
+ * Loads the MerkleProjectConfig for a given project and core contract.
344
+ * @param projectId Project Id to get config for
345
+ * @param coreContract Core contract address to get config for
346
+ */
347
+ function getMerkleProjectConfig(
348
+ uint256 projectId,
349
+ address coreContract
350
+ ) internal view returns (MerkleProjectConfig storage) {
351
+ return s().merkleProjectConfigs[coreContract][projectId];
352
+ }
353
+
354
+ /**
355
+ * @notice Return the storage struct for reading and writing. This library
356
+ * uses a diamond storage pattern when managing storage.
357
+ * @return storageStruct The MerkleLibStorage struct.
358
+ */
359
+ function s()
360
+ internal
361
+ pure
362
+ returns (MerkleLibStorage storage storageStruct)
363
+ {
364
+ bytes32 position = MERKLE_LIB_STORAGE_POSITION;
365
+ assembly ("memory-safe") {
366
+ storageStruct.slot := position
367
+ }
368
+ }
369
+
370
+ /**
371
+ * @notice Verifies an address against a proof.
372
+ * @param proofRoot The root of the proof to verify agaisnst.
373
+ * @param proof The proof to verify.
374
+ * @param address_ The address to verify.
375
+ * @return True if the address is verified, false otherwise.
376
+ */
377
+ function _verifyAddress(
378
+ bytes32 proofRoot,
379
+ bytes32[] calldata proof,
380
+ address address_
381
+ ) private pure returns (bool) {
382
+ return proof.verifyCalldata(proofRoot, hashAddress(address_));
383
+ }
175
384
  }