@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,11 +1,13 @@
1
1
  // SPDX-License-Identifier: LGPL-3.0-only
2
2
  // Created By: Art Blocks Inc.
3
3
 
4
- import "../../../interfaces/v0.8.x/IGenArt721CoreContractV3_Base.sol";
4
+ pragma solidity ^0.8.0;
5
5
 
6
- import "@openzeppelin-4.7/contracts/utils/math/Math.sol";
6
+ import {IGenArt721CoreContractV3_Base} from "../../../interfaces/v0.8.x/IGenArt721CoreContractV3_Base.sol";
7
7
 
8
- pragma solidity ^0.8.0;
8
+ import {ABHelpers} from "../ABHelpers.sol";
9
+
10
+ import {Math} from "@openzeppelin-4.7/contracts/utils/math/Math.sol";
9
11
 
10
12
  /**
11
13
  * @title Art Blocks Max Invocations Library
@@ -19,6 +21,24 @@ pragma solidity ^0.8.0;
19
21
  */
20
22
 
21
23
  library MaxInvocationsLib {
24
+ /**
25
+ * @notice Local max invocations for project `projectId`, tied to core contract `coreContractAddress`,
26
+ * updated to `maxInvocations`.
27
+ * @param projectId The id of the project.
28
+ * @param coreContract The address of the core contract.
29
+ * @param maxInvocations The new max invocations limit.
30
+ */
31
+ event ProjectMaxInvocationsLimitUpdated(
32
+ uint256 indexed projectId,
33
+ address indexed coreContract,
34
+ uint256 maxInvocations
35
+ );
36
+
37
+ // position of Max Invocations Lib storage, using a diamond storage pattern
38
+ // for this library
39
+ bytes32 constant MAX_INVOCATIONS_LIB_STORAGE_POSITION =
40
+ keccak256("maxinvocationslib.storage");
41
+
22
42
  uint256 internal constant ONE_MILLION = 1_000_000;
23
43
 
24
44
  /**
@@ -29,66 +49,92 @@ library MaxInvocationsLib {
29
49
  uint24 maxInvocations;
30
50
  }
31
51
 
52
+ // Diamond storage pattern is used in this library
53
+ struct MaxInvocationsLibStorage {
54
+ mapping(address coreContract => mapping(uint256 projectId => MaxInvocationsProjectConfig)) maxInvocationsProjectConfigs;
55
+ }
56
+
32
57
  /**
33
58
  * @notice Syncs project's max invocations to core contract value.
34
- * @param _projectId The id of the project.
35
- * @param _coreContract The address of the core contract.
36
- * @param maxInvocationsProjectConfig Data structure that holds max invocations project configuration.
37
- * @return uint256 the updated max invocations.
59
+ * @param projectId The id of the project.
60
+ * @param coreContract The address of the core contract.
38
61
  */
39
62
  function syncProjectMaxInvocationsToCore(
40
- uint256 _projectId,
41
- address _coreContract,
42
- MaxInvocationsProjectConfig storage maxInvocationsProjectConfig
43
- ) internal returns (uint256) {
44
- uint256 maxInvocations;
45
- uint256 invocations;
46
- (invocations, maxInvocations, , , , ) = IGenArt721CoreContractV3_Base(
47
- _coreContract
48
- ).projectStateData(_projectId);
63
+ uint256 projectId,
64
+ address coreContract
65
+ ) internal {
66
+ (
67
+ uint256 coreInvocations,
68
+ uint256 coreMaxInvocations
69
+ ) = coreContractInvocationData({
70
+ projectId: projectId,
71
+ coreContract: coreContract
72
+ });
49
73
  // update storage with results
50
- maxInvocationsProjectConfig.maxInvocations = uint24(maxInvocations);
74
+ MaxInvocationsProjectConfig
75
+ storage maxInvocationsProjectConfig = getMaxInvocationsProjectConfig({
76
+ projectId: projectId,
77
+ coreContract: coreContract
78
+ });
79
+ maxInvocationsProjectConfig.maxInvocations = uint24(coreMaxInvocations);
51
80
 
52
81
  // We need to ensure maxHasBeenInvoked is correctly set after manually syncing the
53
82
  // local maxInvocations value with the core contract's maxInvocations value.
54
83
  // This synced value of maxInvocations from the core contract will always be greater
55
84
  // than or equal to the previous value of maxInvocations stored locally.
56
85
  maxInvocationsProjectConfig.maxHasBeenInvoked =
57
- invocations == maxInvocations;
58
- return maxInvocations;
86
+ coreInvocations == coreMaxInvocations;
87
+
88
+ emit ProjectMaxInvocationsLimitUpdated({
89
+ projectId: projectId,
90
+ coreContract: coreContract,
91
+ maxInvocations: coreMaxInvocations
92
+ });
59
93
  }
60
94
 
61
95
  /**
62
96
  * @notice Manually limits project's max invocations.
63
- * @param _projectId The id of the project.
64
- * @param _coreContract The address of the core contract.
65
- * @param _maxInvocations The new max invocations limit.
66
- * @param maxInvocationsProjectConfig Data structure that holds max invocations project configuration.
97
+ * @param projectId The id of the project.
98
+ * @param coreContract The address of the core contract.
99
+ * @param maxInvocations The new max invocations limit.
67
100
  */
68
101
  function manuallyLimitProjectMaxInvocations(
69
- uint256 _projectId,
70
- address _coreContract,
71
- uint24 _maxInvocations,
72
- MaxInvocationsProjectConfig storage maxInvocationsProjectConfig
102
+ uint256 projectId,
103
+ address coreContract,
104
+ uint24 maxInvocations
73
105
  ) internal {
74
106
  // CHECKS
75
107
  (
76
108
  uint256 coreInvocations,
77
109
  uint256 coreMaxInvocations
78
- ) = coreContractInvocationData(_projectId, _coreContract);
110
+ ) = coreContractInvocationData({
111
+ projectId: projectId,
112
+ coreContract: coreContract
113
+ });
79
114
  require(
80
- _maxInvocations <= coreMaxInvocations,
115
+ maxInvocations <= coreMaxInvocations,
81
116
  "Invalid max invocations"
82
117
  );
83
- require(_maxInvocations >= coreInvocations, "Invalid max invocations");
118
+ require(maxInvocations >= coreInvocations, "Invalid max invocations");
84
119
 
85
120
  // EFFECTS
121
+ MaxInvocationsProjectConfig
122
+ storage maxInvocationsProjectConfig = getMaxInvocationsProjectConfig({
123
+ projectId: projectId,
124
+ coreContract: coreContract
125
+ });
86
126
  // update storage with results
87
- maxInvocationsProjectConfig.maxInvocations = uint24(_maxInvocations);
127
+ maxInvocationsProjectConfig.maxInvocations = uint24(maxInvocations);
88
128
  // We need to ensure maxHasBeenInvoked is correctly set after manually setting the
89
129
  // local maxInvocations value.
90
130
  maxInvocationsProjectConfig.maxHasBeenInvoked =
91
- coreInvocations == _maxInvocations;
131
+ coreInvocations == maxInvocations;
132
+
133
+ emit ProjectMaxInvocationsLimitUpdated({
134
+ projectId: projectId,
135
+ coreContract: coreContract,
136
+ maxInvocations: maxInvocations
137
+ });
92
138
  }
93
139
 
94
140
  /**
@@ -98,19 +144,24 @@ library MaxInvocationsLib {
98
144
  * @dev This function checks that the token invocation is less than or
99
145
  * equal to the local max invocations, and also updates the local
100
146
  * maxHasBeenInvoked value.
101
- * @param _tokenId The id of the token.
102
- * @param maxInvocationsProjectConfig Data structure that holds max
103
- * invocations project configuration.
147
+ * @param tokenId The id of the token.
148
+ * @param coreContract The address of the core contract.
104
149
  */
105
150
  function validatePurchaseEffectsInvocations(
106
- uint256 _tokenId,
107
- MaxInvocationsProjectConfig storage maxInvocationsProjectConfig
151
+ uint256 tokenId,
152
+ address coreContract
108
153
  ) internal {
154
+ uint256 projectId = ABHelpers.tokenIdToProjectId(tokenId);
155
+ MaxInvocationsProjectConfig
156
+ storage maxInvocationsProjectConfig = getMaxInvocationsProjectConfig({
157
+ projectId: projectId,
158
+ coreContract: coreContract
159
+ });
109
160
  // invocation is token number plus one, and will never overflow due to
110
161
  // limit of 1e6 invocations per project. block scope for gas efficiency
111
162
  // (i.e. avoid an unnecessary var initialization to 0).
112
163
  unchecked {
113
- uint256 tokenInvocation = (_tokenId % ONE_MILLION) + 1;
164
+ uint256 tokenInvocation = (tokenId % ONE_MILLION) + 1;
114
165
  uint256 localMaxInvocations = maxInvocationsProjectConfig
115
166
  .maxInvocations;
116
167
  // handle the case where the token invocation == minter local max
@@ -132,10 +183,34 @@ library MaxInvocationsLib {
132
183
  }
133
184
 
134
185
  /**
135
- * Helper function to check if max invocations has not been initialized.
186
+ * Checks that the max invocations have not been reached for a given
187
+ * project. This only checks the minter's local max invocations, and does
188
+ * not consider the core contract's max invocations.
189
+ * The function reverts if the max invocations have been reached.
190
+ * @param projectId The id of the project.
191
+ * @param coreContract The address of the core contract.
192
+ */
193
+ function preMintChecks(
194
+ uint256 projectId,
195
+ address coreContract
196
+ ) internal view {
197
+ // check that max invocations have not been reached
198
+ MaxInvocationsProjectConfig
199
+ storage maxInvocationsProjectConfig = getMaxInvocationsProjectConfig({
200
+ projectId: projectId,
201
+ coreContract: coreContract
202
+ });
203
+ require(
204
+ !maxInvocationsProjectConfig.maxHasBeenInvoked,
205
+ "Max invocations reached"
206
+ );
207
+ }
208
+
209
+ /**
210
+ * @notice Helper function to check if max invocations has not been initialized.
136
211
  * Returns true if not initialized, false if initialized.
137
- * @param _maxInvocationsProjectConfig Struct that holds max invocations
138
- * project configuration.
212
+ * @param projectId The id of the project.
213
+ * @param coreContract The address of the core contract.
139
214
  * @return bool
140
215
  * @dev We know a project's max invocations have never been initialized if
141
216
  * both max invocations and maxHasBeenInvoked are still initial values.
@@ -143,62 +218,68 @@ library MaxInvocationsLib {
143
218
  * maxHasBeenInvoked would be set to true.
144
219
  */
145
220
  function maxInvocationsIsUnconfigured(
146
- MaxInvocationsProjectConfig storage _maxInvocationsProjectConfig
221
+ uint256 projectId,
222
+ address coreContract
147
223
  ) internal view returns (bool) {
224
+ MaxInvocationsProjectConfig
225
+ storage maxInvocationsProjectConfig = getMaxInvocationsProjectConfig({
226
+ projectId: projectId,
227
+ coreContract: coreContract
228
+ });
148
229
  return
149
- _maxInvocationsProjectConfig.maxInvocations == 0 &&
150
- !_maxInvocationsProjectConfig.maxHasBeenInvoked;
230
+ maxInvocationsProjectConfig.maxInvocations == 0 &&
231
+ !maxInvocationsProjectConfig.maxHasBeenInvoked;
151
232
  }
152
233
 
153
234
  /**
154
- * Returns if invocations remain available for a given project.
235
+ * @notice Function returns if invocations remain available for a given project.
155
236
  * This function calls the core contract to get the most up-to-date
156
237
  * invocation data (which may be useful to avoid reverts during mint).
157
238
  * This function considers core contract max invocations, and minter local
158
239
  * max invocations, and returns a response based on the most limiting
159
240
  * max invocations value.
160
- * @param _maxInvocationsProjectConfig Struct that holds minter-level max
161
- * invocations
162
- * @param _projectId The id of the project.
163
- * @param _coreContract The address of the core contract.
241
+ * @param projectId The id of the project.
242
+ * @param coreContract The address of the core contract.
164
243
  */
165
244
  function invocationsRemain(
166
- MaxInvocationsProjectConfig storage _maxInvocationsProjectConfig,
167
- uint256 _projectId,
168
- address _coreContract
245
+ uint256 projectId,
246
+ address coreContract
169
247
  ) internal view returns (bool) {
170
248
  // get up-to-data invocation data from core contract
171
249
  (
172
250
  uint256 coreInvocations,
173
251
  uint256 coreMaxInvocations
174
- ) = MaxInvocationsLib.coreContractInvocationData(
175
- _projectId,
176
- _coreContract
177
- );
252
+ ) = coreContractInvocationData({
253
+ projectId: projectId,
254
+ coreContract: coreContract
255
+ });
178
256
  // load minter-local max invocations into memory
179
- uint256 localMaxInvocations = _maxInvocationsProjectConfig
180
- .maxInvocations;
257
+ MaxInvocationsProjectConfig
258
+ storage maxInvocationsProjectConfig = getMaxInvocationsProjectConfig({
259
+ projectId: projectId,
260
+ coreContract: coreContract
261
+ });
181
262
  // invocations remain available if the core contract has not reached
182
263
  // the most limiting max invocations, either on minter or core contract
183
264
  uint256 limitingMaxInvocations = Math.min(
184
265
  coreMaxInvocations,
185
- localMaxInvocations
266
+ maxInvocationsProjectConfig.maxInvocations // local max invocations
186
267
  );
187
268
  return coreInvocations < limitingMaxInvocations;
188
269
  }
189
270
 
190
271
  /**
191
- * Pulls core contract invocation data for a given project.
272
+ * @notice Pulls core contract invocation data for a given project.
192
273
  * @dev This function calls the core contract to get the invocation data
193
- * @param _projectId The id of the project.
194
- * @param _coreContract The address of the core contract.
274
+ * @param projectId The id of the project.
275
+ * @param coreContract The address of the core contract.
195
276
  * @return coreInvocations The number of invocations for the project.
196
277
  * @return coreMaxInvocations The max invocations for the project, as
197
278
  * defined on the core contract.
198
279
  */
199
280
  function coreContractInvocationData(
200
- uint256 _projectId,
201
- address _coreContract
281
+ uint256 projectId,
282
+ address coreContract
202
283
  )
203
284
  internal
204
285
  view
@@ -211,54 +292,75 @@ library MaxInvocationsLib {
211
292
  ,
212
293
  ,
213
294
 
214
- ) = IGenArt721CoreContractV3_Base(_coreContract).projectStateData(
215
- _projectId
295
+ ) = IGenArt721CoreContractV3_Base(coreContract).projectStateData(
296
+ projectId
216
297
  );
217
298
  }
218
299
 
219
300
  /**
220
- * Returns the max invocations for a given MaxInvocationsProjectConfig.
221
- * @param _maxInvocationsProjectConfig MaxInvocationsProjectConfig struct
301
+ * @notice Function returns the max invocations for a given project.
302
+ * @param projectId The id of the project.
303
+ * @param coreContract The address of the core contract.
222
304
  * to be queried.
223
305
  */
224
306
  function getMaxInvocations(
225
- MaxInvocationsProjectConfig storage _maxInvocationsProjectConfig
307
+ uint256 projectId,
308
+ address coreContract
226
309
  ) internal view returns (uint256) {
227
- return _maxInvocationsProjectConfig.maxInvocations;
310
+ MaxInvocationsProjectConfig
311
+ storage maxInvocationsProjectConfig = getMaxInvocationsProjectConfig({
312
+ projectId: projectId,
313
+ coreContract: coreContract
314
+ });
315
+ return maxInvocationsProjectConfig.maxInvocations;
228
316
  }
229
317
 
230
318
  /**
231
- * Returns if max has been invoked for a given MaxInvocationsProjectConfig.
232
- * @param _maxInvocationsProjectConfig MaxInvocationsProjectConfig struct
319
+ * @notice Function returns if max has been invoked for a given project.
320
+ * @param projectId The id of the project.
321
+ * @param coreContract The address of the core contract.
233
322
  * to be queried.
234
323
  */
235
324
  function getMaxHasBeenInvoked(
236
- MaxInvocationsProjectConfig storage _maxInvocationsProjectConfig
325
+ uint256 projectId,
326
+ address coreContract
237
327
  ) internal view returns (bool) {
238
- return _maxInvocationsProjectConfig.maxHasBeenInvoked;
328
+ MaxInvocationsProjectConfig
329
+ storage maxInvocationsProjectConfig = getMaxInvocationsProjectConfig({
330
+ projectId: projectId,
331
+ coreContract: coreContract
332
+ });
333
+ return maxInvocationsProjectConfig.maxHasBeenInvoked;
239
334
  }
240
335
 
241
336
  /**
242
- * Get if a project has reached its max invocations.
243
- * Function is labaled as "safe" because it checks the core contract's
337
+ * @notice Function returns if a project has reached its max invocations.
338
+ * Function is labelled as "safe" because it checks the core contract's
244
339
  * invocations and max invocations. If the local max invocations is greater
245
340
  * than the core contract's max invocations, it will defer to the core
246
341
  * contract's max invocations (since those are the limiting factor).
247
- * @param _projectId The id of the project.
248
- * @param _coreContract The address of the core contract.
249
- * @param _maxInvocationsProjectConfig MaxInvocationsProjectConfig struct
342
+ * @param projectId The id of the project.
343
+ * @param coreContract The address of the core contract.
250
344
  */
251
345
  function projectMaxHasBeenInvokedSafe(
252
- uint256 _projectId,
253
- address _coreContract,
254
- MaxInvocationsProjectConfig storage _maxInvocationsProjectConfig
346
+ uint256 projectId,
347
+ address coreContract
255
348
  ) internal view returns (bool) {
256
349
  // get max invocations from core contract
257
- uint256 coreInvocations;
258
- uint256 coreMaxInvocations;
259
- (coreInvocations, coreMaxInvocations) = MaxInvocationsLib
260
- .coreContractInvocationData(_projectId, _coreContract);
261
- uint256 localMaxInvocations = _maxInvocationsProjectConfig
350
+ (
351
+ uint256 coreInvocations,
352
+ uint256 coreMaxInvocations
353
+ ) = coreContractInvocationData({
354
+ projectId: projectId,
355
+ coreContract: coreContract
356
+ });
357
+
358
+ MaxInvocationsProjectConfig
359
+ storage maxInvocationsProjectConfig = getMaxInvocationsProjectConfig({
360
+ projectId: projectId,
361
+ coreContract: coreContract
362
+ });
363
+ uint256 localMaxInvocations = maxInvocationsProjectConfig
262
364
  .maxInvocations;
263
365
  // value is locally defined, and could be out of date.
264
366
  // only possible illogical state is if local max invocations is
@@ -292,30 +394,36 @@ library MaxInvocationsLib {
292
394
  * be more restrictive than the core contract.
293
395
  * @dev assumes core contract's max invocations may only be reduced, which
294
396
  * is the case for all V3 core contracts
397
+ * @param projectId The id of the project.
398
+ * @param coreContract The address of the core contract.
295
399
  */
296
400
  function refreshMaxInvocations(
297
- uint256 _projectId,
298
- address _coreContract,
299
- MaxInvocationsProjectConfig storage _maxInvocationsProjectConfig
300
- ) internal returns (bool maxInvocationsUpdated) {
301
- if (maxInvocationsIsUnconfigured(_maxInvocationsProjectConfig)) {
401
+ uint256 projectId,
402
+ address coreContract
403
+ ) internal {
404
+ MaxInvocationsProjectConfig
405
+ storage maxInvocationsProjectConfig = getMaxInvocationsProjectConfig({
406
+ projectId: projectId,
407
+ coreContract: coreContract
408
+ });
409
+ if (maxInvocationsIsUnconfigured(projectId, coreContract)) {
302
410
  // populate the minter max invocation state to equal the values on
303
411
  // the core contract (least restrictive state)
304
- MaxInvocationsLib.syncProjectMaxInvocationsToCore(
305
- _projectId,
306
- _coreContract,
307
- _maxInvocationsProjectConfig
308
- );
309
- // return true to indicate max invocation state update
310
- maxInvocationsUpdated = true;
412
+ syncProjectMaxInvocationsToCore({
413
+ projectId: projectId,
414
+ coreContract: coreContract
415
+ });
311
416
  } else {
312
417
  // if local max invocations were already populated, validate the local state
313
- uint256 coreMaxInvocations;
314
- uint256 coreInvocations;
315
- (coreInvocations, coreMaxInvocations) = MaxInvocationsLib
316
- .coreContractInvocationData(_projectId, _coreContract);
418
+ (
419
+ uint256 coreInvocations,
420
+ uint256 coreMaxInvocations
421
+ ) = coreContractInvocationData({
422
+ projectId: projectId,
423
+ coreContract: coreContract
424
+ });
317
425
 
318
- uint256 localMaxInvocations = _maxInvocationsProjectConfig
426
+ uint256 localMaxInvocations = maxInvocationsProjectConfig
319
427
  .maxInvocations;
320
428
  if (localMaxInvocations > coreMaxInvocations) {
321
429
  // if local max invocations are greater than core max invocations, make
@@ -324,25 +432,57 @@ library MaxInvocationsLib {
324
432
  // have been reduced since the minter's max invocations were last
325
433
  // updated
326
434
  // set local max invocations to core contract's max invocations
327
- _maxInvocationsProjectConfig.maxInvocations = uint24(
435
+ maxInvocationsProjectConfig.maxInvocations = uint24(
328
436
  coreMaxInvocations
329
437
  );
330
438
  // update the minter's `maxHasBeenInvoked` state
331
- _maxInvocationsProjectConfig
439
+ maxInvocationsProjectConfig
332
440
  .maxHasBeenInvoked = (coreMaxInvocations ==
333
441
  coreInvocations);
334
- // return true to indicate max invocation state update
335
- maxInvocationsUpdated = true;
442
+ emit ProjectMaxInvocationsLimitUpdated({
443
+ projectId: projectId,
444
+ coreContract: coreContract,
445
+ maxInvocations: coreMaxInvocations
446
+ });
336
447
  } else if (coreInvocations >= localMaxInvocations) {
337
448
  // core invocations are greater than this minter's max
338
449
  // invocations, indicating that minting must have occurred on
339
450
  // another minter. update the minter's `maxHasBeenInvoked` to
340
451
  // true to prevent any false negatives on
341
452
  // `getMaxHasBeenInvoked'
342
- _maxInvocationsProjectConfig.maxHasBeenInvoked = true;
343
- // @dev do not return true, because we did not change the value
453
+ maxInvocationsProjectConfig.maxHasBeenInvoked = true;
454
+ // @dev do not emit event, because we did not change the value
344
455
  // of minter-local max invocations
345
456
  }
346
457
  }
347
458
  }
459
+
460
+ /**
461
+ * @notice Loads the MaxInvocationsProjectConfig for a given project and core
462
+ * contract.
463
+ * @param projectId Project Id to get config for
464
+ * @param coreContract Core contract address to get config for
465
+ */
466
+ function getMaxInvocationsProjectConfig(
467
+ uint256 projectId,
468
+ address coreContract
469
+ ) internal view returns (MaxInvocationsProjectConfig storage) {
470
+ return s().maxInvocationsProjectConfigs[coreContract][projectId];
471
+ }
472
+
473
+ /**
474
+ * @notice Return the storage struct for reading and writing. This library
475
+ * uses a diamond storage pattern when managing storage.
476
+ * @return storageStruct The MaxInvocationsLibStorage struct.
477
+ */
478
+ function s()
479
+ internal
480
+ pure
481
+ returns (MaxInvocationsLibStorage storage storageStruct)
482
+ {
483
+ bytes32 position = MAX_INVOCATIONS_LIB_STORAGE_POSITION;
484
+ assembly ("memory-safe") {
485
+ storageStruct.slot := position
486
+ }
487
+ }
348
488
  }