@gooddollar/goodcollective-contracts 1.0.3 → 1.0.5-beta.7a2c704

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 (38) hide show
  1. package/contracts/DirectPayments/DirectPaymentsFactory.sol +70 -13
  2. package/contracts/DirectPayments/DirectPaymentsPool.sol +102 -40
  3. package/contracts/DirectPayments/ProvableNFT.sol +17 -11
  4. package/contracts/GoodCollective/GoodCollectiveSuperApp.sol +155 -77
  5. package/contracts/GoodCollective/IGoodCollectiveSuperApp.sol +12 -0
  6. package/contracts/utils/HelperLibrary.sol +83 -0
  7. package/package.json +13 -7
  8. package/releases/deployment.json +12022 -1689
  9. package/typechain-types/@gooddollar/goodprotocol/contracts/token/IFeesFormula.ts +115 -0
  10. package/typechain-types/@gooddollar/goodprotocol/contracts/token/index.ts +1 -0
  11. package/typechain-types/@openzeppelin/contracts/access/Ownable.ts +176 -0
  12. package/typechain-types/@openzeppelin/contracts/access/index.ts +4 -0
  13. package/typechain-types/@openzeppelin/contracts/index.ts +2 -0
  14. package/typechain-types/@openzeppelin/contracts/proxy/beacon/BeaconProxy.ts +115 -0
  15. package/typechain-types/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.ts +247 -0
  16. package/typechain-types/@openzeppelin/contracts/proxy/beacon/index.ts +2 -0
  17. package/typechain-types/contracts/DirectPayments/DirectPaymentsFactory.ts +168 -14
  18. package/typechain-types/contracts/DirectPayments/DirectPaymentsPool.sol/DirectPaymentsPool.ts +419 -186
  19. package/typechain-types/contracts/DirectPayments/ProvableNFT.ts +32 -3
  20. package/typechain-types/contracts/GoodCollective/GoodCollectiveSuperApp.ts +170 -13
  21. package/typechain-types/contracts/utils/HelperLibrary.ts +154 -0
  22. package/typechain-types/contracts/utils/index.ts +1 -0
  23. package/typechain-types/factories/@gooddollar/goodprotocol/contracts/token/IFeesFormula__factory.ts +60 -0
  24. package/typechain-types/factories/@gooddollar/goodprotocol/contracts/token/index.ts +1 -0
  25. package/typechain-types/factories/@openzeppelin/contracts/access/Ownable__factory.ts +78 -0
  26. package/typechain-types/factories/@openzeppelin/contracts/access/index.ts +4 -0
  27. package/typechain-types/factories/@openzeppelin/contracts/index.ts +1 -0
  28. package/typechain-types/factories/@openzeppelin/contracts/proxy/beacon/BeaconProxy__factory.ts +143 -0
  29. package/typechain-types/factories/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon__factory.ts +170 -0
  30. package/typechain-types/factories/@openzeppelin/contracts/proxy/beacon/index.ts +2 -0
  31. package/typechain-types/factories/contracts/DirectPayments/DirectPaymentsFactory__factory.ts +226 -3
  32. package/typechain-types/factories/contracts/DirectPayments/DirectPaymentsPool.sol/DirectPaymentsPool__factory.ts +473 -95
  33. package/typechain-types/factories/contracts/DirectPayments/ProvableNFT__factory.ts +56 -1
  34. package/typechain-types/factories/contracts/GoodCollective/GoodCollectiveSuperApp__factory.ts +148 -4
  35. package/typechain-types/factories/contracts/utils/HelperLibrary__factory.ts +129 -0
  36. package/typechain-types/factories/contracts/utils/index.ts +1 -0
  37. package/typechain-types/hardhat.d.ts +45 -0
  38. package/typechain-types/index.ts +8 -0
@@ -5,6 +5,9 @@ pragma solidity >=0.8.0;
5
5
  import "./DirectPaymentsPool.sol";
6
6
  import "./ProvableNFT.sol";
7
7
  import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
8
+ import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
9
+ import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
10
+
8
11
  import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
9
12
  import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
10
13
 
@@ -13,7 +16,15 @@ import "hardhat/console.sol";
13
16
  contract DirectPaymentsFactory is AccessControlUpgradeable, UUPSUpgradeable {
14
17
  error NOT_PROJECT_OWNER();
15
18
 
16
- event PoolCreated(address indexed pool, string indexed projectId, string ipfs, uint32 indexed nftType);
19
+ event PoolCreated(
20
+ address indexed pool,
21
+ string indexed projectId,
22
+ string ipfs,
23
+ uint32 indexed nftType,
24
+ DirectPaymentsPool.PoolSettings poolSettings,
25
+ DirectPaymentsPool.SafetyLimits poolLimits
26
+ );
27
+
17
28
  event PoolDetailsChanged(address indexed pool, string ipfs);
18
29
  event PoolVerifiedChanged(address indexed pool, bool isVerified);
19
30
  event UpdatedImpl(address indexed impl);
@@ -24,16 +35,18 @@ contract DirectPaymentsFactory is AccessControlUpgradeable, UUPSUpgradeable {
24
35
  string projectId;
25
36
  }
26
37
 
27
- address public impl;
38
+ UpgradeableBeacon public impl;
28
39
  ProvableNFT public nft;
29
40
  uint32 public nextNftType;
30
41
 
31
42
  mapping(address => PoolRegistry) public registry;
32
43
  mapping(bytes32 => DirectPaymentsPool) public projectIdToControlPool;
33
44
 
45
+ address public feeRecipient;
46
+ uint32 public feeBps;
47
+
34
48
  modifier onlyProjectOwnerOrNon(string memory projectId) {
35
49
  DirectPaymentsPool controlPool = projectIdToControlPool[keccak256(bytes(projectId))];
36
- console.log("control:%s sender:%s %s", address(controlPool), msg.sender);
37
50
  // console.log("result %s", controlPool.hasRole(controlPool.DEFAULT_ADMIN_ROLE(), msg.sender));
38
51
  if (address(controlPool) != address(0)) {
39
52
  if (controlPool.hasRole(controlPool.DEFAULT_ADMIN_ROLE(), msg.sender) == false) {
@@ -55,38 +68,77 @@ contract DirectPaymentsFactory is AccessControlUpgradeable, UUPSUpgradeable {
55
68
 
56
69
  function _authorizeUpgrade(address _impl) internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {}
57
70
 
58
- function initialize(address _owner, address _dpimpl, address _nftimpl) external initializer {
71
+ function initialize(
72
+ address _owner,
73
+ address _dpimpl,
74
+ ProvableNFT _nft,
75
+ address _feeRecipient,
76
+ uint32 _feeBps
77
+ ) external initializer {
59
78
  nextNftType = 1;
60
- impl = _dpimpl;
61
- bytes memory initCall = abi.encodeWithSelector(ProvableNFT.initialize.selector, "DirectPayments NFT", "DPNFT");
62
- nft = ProvableNFT(address(new ERC1967Proxy(_nftimpl, initCall)));
79
+ impl = new UpgradeableBeacon(_dpimpl);
80
+ nft = _nft;
81
+ feeRecipient = _feeRecipient;
82
+ feeBps = _feeBps;
63
83
 
64
- nft.grantRole(DEFAULT_ADMIN_ROLE, _owner);
65
84
  _setupRole(DEFAULT_ADMIN_ROLE, _owner);
66
85
  }
67
86
 
87
+ //TODO: implement a pool that's auto upgradeable using beacon method
88
+ function createBeaconPool(
89
+ string memory _projectId,
90
+ string memory _ipfs,
91
+ DirectPaymentsPool.PoolSettings memory _settings,
92
+ DirectPaymentsPool.SafetyLimits memory _limits
93
+ ) external onlyProjectOwnerOrNon(_projectId) returns (DirectPaymentsPool pool) {
94
+ return _createPool(_projectId, _ipfs, _settings, _limits, true);
95
+ }
96
+
68
97
  function createPool(
69
98
  string memory _projectId,
70
99
  string memory _ipfs,
71
100
  DirectPaymentsPool.PoolSettings memory _settings,
72
101
  DirectPaymentsPool.SafetyLimits memory _limits
73
102
  ) external onlyProjectOwnerOrNon(_projectId) returns (DirectPaymentsPool pool) {
103
+ return _createPool(_projectId, _ipfs, _settings, _limits, false);
104
+ }
105
+
106
+ function _createPool(
107
+ string memory _projectId,
108
+ string memory _ipfs,
109
+ DirectPaymentsPool.PoolSettings memory _settings,
110
+ DirectPaymentsPool.SafetyLimits memory _limits,
111
+ bool useBeacon
112
+ ) internal returns (DirectPaymentsPool pool) {
74
113
  //TODO: add check if msg.sender is whitelisted
75
114
 
76
115
  _settings.nftType = nextNftType;
77
- bytes memory initCall = abi.encodeWithSelector(DirectPaymentsPool.initialize.selector, nft, _settings, _limits);
78
- pool = DirectPaymentsPool(address(new ERC1967Proxy(impl, initCall)));
116
+ bytes memory initCall = abi.encodeWithSelector(
117
+ DirectPaymentsPool.initialize.selector,
118
+ nft,
119
+ _settings,
120
+ _limits,
121
+ address(this)
122
+ );
123
+
124
+ if (useBeacon) {
125
+ pool = DirectPaymentsPool(address(new BeaconProxy(address(impl), initCall)));
126
+ } else {
127
+ pool = DirectPaymentsPool(address(new ERC1967Proxy(impl.implementation(), initCall)));
128
+ }
79
129
 
80
130
  nft.grantRole(nft.getManagerRole(nextNftType), _settings.manager);
81
131
  nft.grantRole(nft.getManagerRole(nextNftType), address(pool));
82
132
  pool.grantRole(pool.MINTER_ROLE(), _settings.manager);
83
133
 
84
- projectIdToControlPool[keccak256(bytes(_projectId))] = pool;
134
+ //access control to project is determinted by the first pool access control rules
135
+ if (address(projectIdToControlPool[keccak256(bytes(_projectId))]) == address(0))
136
+ projectIdToControlPool[keccak256(bytes(_projectId))] = pool;
85
137
  registry[address(pool)].ipfs = _ipfs;
86
138
  registry[address(pool)].projectId = _projectId;
87
139
 
88
140
  pool.renounceRole(DEFAULT_ADMIN_ROLE, address(this));
89
- emit PoolCreated(address(pool), _projectId, _ipfs, nextNftType);
141
+ emit PoolCreated(address(pool), _projectId, _ipfs, nextNftType, _settings, _limits);
90
142
 
91
143
  nextNftType++;
92
144
  }
@@ -102,7 +154,12 @@ contract DirectPaymentsFactory is AccessControlUpgradeable, UUPSUpgradeable {
102
154
  }
103
155
 
104
156
  function updateImpl(address _impl) external onlyRole(DEFAULT_ADMIN_ROLE) {
105
- impl = _impl;
157
+ impl.upgradeTo(_impl);
106
158
  emit UpdatedImpl(_impl);
107
159
  }
160
+
161
+ function setFeeInfo(address _feeRecipient, uint32 _feeBps) external onlyRole(DEFAULT_ADMIN_ROLE) {
162
+ feeBps = _feeBps;
163
+ feeRecipient = _feeRecipient;
164
+ }
108
165
  }
@@ -41,21 +41,39 @@ contract DirectPaymentsPool is
41
41
  error NOT_MANAGER();
42
42
  error ALREADY_CLAIMED(uint256);
43
43
  error NFT_MISSING(uint256);
44
- error NOT_MEMBER(address);
45
- error NOT_WHITELISTED(address);
46
44
  error OVER_MEMBER_LIMITS(address);
47
45
  error OVER_GLOBAL_LIMITS();
48
46
  error UNSUPPORTED_NFT();
49
47
  error NO_BALANCE();
48
+ error NFTTYPE_CHANGED();
49
+ error EMPTY_MANAGER();
50
50
 
51
51
  bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
52
+ bytes32 public constant MEMBER_ROLE = keccak256("MEMBER_ROLE");
52
53
  bytes32 public constant MINTER_ROLE = keccak256("MINTER");
53
54
 
55
+ event PoolCreated(
56
+ address indexed pool,
57
+ string indexed projectId,
58
+ string ipfs,
59
+ uint32 indexed nftType,
60
+ DirectPaymentsPool.PoolSettings poolSettings,
61
+ DirectPaymentsPool.SafetyLimits poolLimits
62
+ );
63
+
54
64
  event PoolSettingsChanged(PoolSettings settings);
55
65
  event PoolLimitsChanged(SafetyLimits limits);
56
- event MemberAdded(address member);
57
- event MemberRemoved(address member);
58
- event RewardClaimed(uint256 indexed tokenId, uint256 totalRewards);
66
+ event EventRewardClaimed(
67
+ uint256 indexed tokenId,
68
+ uint16 eventType,
69
+ uint32 eventTimestamp,
70
+ uint256 eventQuantity,
71
+ string eventUri,
72
+ address[] contributers,
73
+ uint256 rewardPerContributer
74
+ );
75
+ event NFTClaimed(uint256 indexed tokenId, uint256 totalRewards);
76
+ event NOT_MEMBER_OR_WHITELISTED(address contributer);
59
77
 
60
78
  // Define functions
61
79
  struct PoolSettings {
@@ -66,6 +84,7 @@ contract DirectPaymentsPool is
66
84
  IMembersValidator membersValidator;
67
85
  IIdentityV2 uniquenessValidator;
68
86
  IERC20Upgradeable rewardToken;
87
+ bool allowRewardOverride;
69
88
  }
70
89
 
71
90
  struct SafetyLimits {
@@ -87,10 +106,10 @@ contract DirectPaymentsPool is
87
106
  ProvableNFT public nft;
88
107
 
89
108
  mapping(uint256 => bool) public claimedNfts;
90
- mapping(address => bool) public members;
109
+ mapping(address => bool) private members_unused; // using access control instead
91
110
  mapping(address => LimitsData) public memberLimits;
92
111
  LimitsData public globalLimits;
93
- address public createdBy;
112
+ DirectPaymentsFactory public registry;
94
113
 
95
114
  /// @custom:oz-upgrades-unsafe-allow constructor
96
115
  constructor(ISuperfluid _host, ISwapRouter _swapRouter) GoodCollectiveSuperApp(_host, _swapRouter) {}
@@ -99,7 +118,11 @@ contract DirectPaymentsPool is
99
118
  * @dev Authorizes an upgrade for the implementation contract.
100
119
  * @param impl The address of the new implementation contract.
101
120
  */
102
- function _authorizeUpgrade(address impl) internal virtual override {}
121
+ function _authorizeUpgrade(address impl) internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {}
122
+
123
+ function getRegistry() public view override returns (DirectPaymentsFactory) {
124
+ return DirectPaymentsFactory(registry);
125
+ }
103
126
 
104
127
  /**
105
128
  * @dev Initializes the contract with the given settings and limits.
@@ -110,20 +133,20 @@ contract DirectPaymentsPool is
110
133
  function initialize(
111
134
  ProvableNFT _nft,
112
135
  PoolSettings memory _settings,
113
- SafetyLimits memory _limits
136
+ SafetyLimits memory _limits,
137
+ DirectPaymentsFactory _registry
114
138
  ) external initializer {
115
- createdBy = msg.sender;
139
+ registry = _registry;
116
140
  settings = _settings;
117
141
  limits = _limits;
118
142
  nft = _nft;
119
143
  _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
120
144
  _setupRole(DEFAULT_ADMIN_ROLE, _settings.manager);
121
-
122
145
  setSuperToken(ISuperToken(address(settings.rewardToken)));
123
146
  }
124
147
 
125
- function upgradeToLatest(bytes memory data) external payable virtual onlyProxy {
126
- address impl = DirectPaymentsFactory(createdBy).impl();
148
+ function upgradeToLatest(bytes memory data) external payable virtual {
149
+ address impl = address(DirectPaymentsFactory(registry).impl());
127
150
  _authorizeUpgrade(impl);
128
151
  _upgradeToAndCallUUPS(impl, data, false);
129
152
  }
@@ -164,17 +187,31 @@ contract DirectPaymentsPool is
164
187
  uint totalRewards;
165
188
  uint rewardsBalance = settings.rewardToken.balanceOf(address(this));
166
189
 
190
+ bool allowRewardOverride = settings.allowRewardOverride;
167
191
  for (uint256 i = 0; i < _data.events.length; i++) {
168
- uint128 reward = _eventReward(_data.events[i].subtype);
192
+ uint reward = (
193
+ allowRewardOverride && _data.events[i].rewardOverride > 0
194
+ ? _data.events[i].rewardOverride
195
+ : _eventReward(_data.events[i].subtype)
196
+ ) * _data.events[i].quantity;
169
197
  if (reward > 0) {
170
- totalRewards += reward * _data.events[i].quantity;
198
+ totalRewards += reward;
171
199
  if (totalRewards > rewardsBalance) revert NO_BALANCE();
172
200
  rewardsBalance -= totalRewards;
173
- _sendReward(_data.events[i].contributers, uint128(reward * _data.events[i].quantity));
201
+ _sendReward(_data.events[i].contributers, uint128(reward));
202
+ emit EventRewardClaimed(
203
+ _nftId,
204
+ _data.events[i].subtype,
205
+ _data.events[i].timestamp,
206
+ _data.events[i].quantity,
207
+ _data.events[i].eventUri,
208
+ _data.events[i].contributers,
209
+ uint128(reward / _data.events[i].contributers.length)
210
+ );
174
211
  }
175
212
  }
176
213
 
177
- emit RewardClaimed(_nftId, totalRewards);
214
+ emit NFTClaimed(_nftId, totalRewards);
178
215
  }
179
216
 
180
217
  /**
@@ -196,11 +233,17 @@ contract DirectPaymentsPool is
196
233
  */
197
234
  function _sendReward(address[] memory recipients, uint128 reward) internal {
198
235
  uint128 perReward = uint128(reward / recipients.length);
236
+ uint128 totalSent;
199
237
  for (uint i = 0; i < recipients.length; i++) {
200
- _enforceAndUpdateMemberLimits(recipients[i], perReward);
201
- settings.rewardToken.safeTransfer(recipients[i], perReward);
238
+ bool valid = _enforceAndUpdateMemberLimits(recipients[i], perReward);
239
+ if (valid) {
240
+ settings.rewardToken.safeTransfer(recipients[i], perReward);
241
+ totalSent += perReward;
242
+ } else {
243
+ emit NOT_MEMBER_OR_WHITELISTED(recipients[i]);
244
+ }
202
245
  }
203
- _enforceAndUpdateGlobalLimits(reward);
246
+ _enforceAndUpdateGlobalLimits(totalSent);
204
247
  }
205
248
 
206
249
  /**
@@ -208,8 +251,11 @@ contract DirectPaymentsPool is
208
251
  * @param member The address of the member to enforce and update limits for.
209
252
  * @param reward The amount of rewards to enforce and update limits for.
210
253
  */
211
- function _enforceAndUpdateMemberLimits(address member, uint128 reward) internal {
212
- if (members[member] == false) revert NOT_MEMBER(member);
254
+ function _enforceAndUpdateMemberLimits(address member, uint128 reward) internal returns (bool) {
255
+ //dont revert on non valid members, just dont reward them (their reward is lost)
256
+ if (_addMember(member, "") == false) {
257
+ return false;
258
+ }
213
259
 
214
260
  uint64 curMonth = _month();
215
261
  if (memberLimits[member].lastReward + 60 * 60 * 24 < block.timestamp) //more than a day passed since last reward
@@ -234,6 +280,8 @@ contract DirectPaymentsPool is
234
280
  memberLimits[member].daily > limits.maxMemberPerDay ||
235
281
  memberLimits[member].monthly > limits.maxMemberPerMonth
236
282
  ) revert OVER_MEMBER_LIMITS(member);
283
+
284
+ return true;
237
285
  }
238
286
 
239
287
  /**
@@ -278,32 +326,23 @@ contract DirectPaymentsPool is
278
326
  * @param extraData Additional data to validate the member.
279
327
  */
280
328
 
281
- function addMember(address member, bytes memory extraData) external {
329
+ function _addMember(address member, bytes memory extraData) internal returns (bool isMember) {
330
+ if (hasRole(MEMBER_ROLE, member)) return true;
331
+
282
332
  if (address(settings.uniquenessValidator) != address(0)) {
283
333
  address rootAddress = settings.uniquenessValidator.getWhitelistedRoot(member);
284
- if (rootAddress == address(0)) revert NOT_WHITELISTED(member);
334
+ if (rootAddress == address(0)) return false;
285
335
  }
286
336
 
337
+ // if no members validator then anyone can join the pool
287
338
  if (address(settings.membersValidator) != address(0)) {
288
339
  if (settings.membersValidator.isMemberValid(address(this), msg.sender, member, extraData) == false) {
289
- revert NOT_MEMBER(member);
340
+ return false;
290
341
  }
291
- } else {
292
- // if no members validator then only admin can add members
293
- if (hasRole(DEFAULT_ADMIN_ROLE, msg.sender) == false) revert NOT_MANAGER();
294
342
  }
295
343
 
296
- members[member] = true;
297
- emit MemberAdded(member);
298
- }
299
-
300
- /**
301
- * @dev Removes a member from the contract.
302
- * @param member The address of the member to remove.
303
- */
304
- function removeMember(address member) external onlyRole(DEFAULT_ADMIN_ROLE) {
305
- members[member] = false;
306
- emit MemberRemoved(member);
344
+ _setupRole(MEMBER_ROLE, member);
345
+ return true;
307
346
  }
308
347
 
309
348
  function mintNFT(address _to, ProvableNFT.NFTData memory _nftData, bool withClaim) external onlyRole(MINTER_ROLE) {
@@ -314,7 +353,7 @@ contract DirectPaymentsPool is
314
353
  }
315
354
 
316
355
  /**
317
- * @dev Receives an ERC721 token and triggers a claim for rewards.
356
+ * @dev Receives an ERC721 token
318
357
  * @param operator The address of the operator that sent the token.
319
358
  * @param from The address of the sender that sent the token.
320
359
  * @param tokenId The ID of the token received.
@@ -340,4 +379,27 @@ contract DirectPaymentsPool is
340
379
  if (nftData.nftType != settings.nftType) revert UNSUPPORTED_NFT();
341
380
  return DirectPaymentsPool.onERC721Received.selector;
342
381
  }
382
+
383
+ /**
384
+ * @dev Sets the safety limits for the pool.
385
+ * @param _limits The new safety limits.
386
+ */
387
+ function setPoolLimits(SafetyLimits memory _limits) public onlyRole(DEFAULT_ADMIN_ROLE) {
388
+ limits = _limits;
389
+ emit PoolLimitsChanged(_limits);
390
+ }
391
+
392
+ /**
393
+ * @dev Sets the settings for the pool.
394
+ * @param _settings The new pool settings.
395
+ */
396
+ function setPoolSettings(PoolSettings memory _settings) public onlyRole(DEFAULT_ADMIN_ROLE) {
397
+ if (_settings.nftType != settings.nftType) revert NFTTYPE_CHANGED();
398
+ if (_settings.manager == address(0)) revert EMPTY_MANAGER();
399
+
400
+ _revokeRole(DEFAULT_ADMIN_ROLE, settings.manager);
401
+ settings = _settings;
402
+ _setupRole(DEFAULT_ADMIN_ROLE, _settings.manager);
403
+ emit PoolSettingsChanged(_settings);
404
+ }
343
405
  }
@@ -19,12 +19,15 @@ contract ProvableNFT is ERC721Upgradeable, AccessControlUpgradeable, UUPSUpgrade
19
19
  bytes32 public constant MINTER_ROLE = keccak256(abi.encodePacked("MINTER"));
20
20
  bytes16 private constant _SYMBOLS = "0123456789abcdef";
21
21
 
22
+ event ProvableNftMinted(uint256 tokenId, address to, bytes32 nftDataHash);
23
+
22
24
  struct EventData {
23
25
  uint16 subtype;
24
26
  uint32 timestamp;
25
27
  uint256 quantity;
26
28
  string eventUri; //extra data related to event
27
29
  address[] contributers;
30
+ uint128 rewardOverride; //override reward defined per 1 quantity of event, pool will use this instead of its own reward if allowRewardOverride is true
28
31
  }
29
32
 
30
33
  struct NFTData {
@@ -41,7 +44,9 @@ contract ProvableNFT is ERC721Upgradeable, AccessControlUpgradeable, UUPSUpgrade
41
44
  _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
42
45
  }
43
46
 
44
- function _authorizeUpgrade(address newimpl) internal virtual override onlyManager(0) {}
47
+ function _authorizeUpgrade(address /*newimpl*/) internal virtual override {
48
+ _onlyManager(0);
49
+ }
45
50
 
46
51
  function supportsInterface(
47
52
  bytes4 interfaceId
@@ -49,14 +54,13 @@ contract ProvableNFT is ERC721Upgradeable, AccessControlUpgradeable, UUPSUpgrade
49
54
  return super.supportsInterface(interfaceId);
50
55
  }
51
56
 
52
- modifier onlyManager(uint32 nftType) {
57
+ function _onlyManager(uint32 nftType) internal view {
53
58
  if (
54
59
  ((nftType > 0 && hasRole(getManagerRole(nftType), msg.sender)) ||
55
60
  hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) == false
56
61
  ) {
57
62
  revert NOT_MANAGER(nftType);
58
63
  }
59
- _;
60
64
  }
61
65
 
62
66
  /**
@@ -72,23 +76,24 @@ contract ProvableNFT is ERC721Upgradeable, AccessControlUpgradeable, UUPSUpgrade
72
76
  * @param _nftDataHash The hash of the NFT's data.
73
77
  * @return tokenId ID of the newly minted NFT.
74
78
  */
75
- function mint(
76
- address _to,
77
- string memory _uri,
78
- bytes32 _nftDataHash
79
- ) public onlyManager(0) returns (uint256 tokenId) {
80
- return _mint(_to, _uri, _nftDataHash, ""); //send false in calldata, assuming default receiver is a directpaymentspool. without nft data on chain it will fail.
79
+ function mint(address _to, string memory _uri, bytes32 _nftDataHash) public returns (uint256 tokenId) {
80
+ _onlyManager(0);
81
+ NFTData memory nftData;
82
+
83
+ return _mint(_to, _uri, _nftDataHash, nftData, ""); //send false in calldata, assuming default receiver is a directpaymentspool. without nft data on chain it will fail.
81
84
  }
82
85
 
83
86
  function _mint(
84
87
  address _to,
85
88
  string memory _uri,
86
89
  bytes32 _nftDataHash,
90
+ NFTData memory /*_nftData*/,
87
91
  bytes memory _callData
88
92
  ) internal returns (uint256 tokenId) {
89
93
  tokenId = uint256(_nftDataHash);
90
94
  nftDatas[tokenId].nftUri = _uri;
91
95
  _safeMint(_to, tokenId, _callData);
96
+ emit ProvableNftMinted(tokenId, _to, _nftDataHash);
92
97
  }
93
98
 
94
99
  /**
@@ -109,7 +114,8 @@ contract ProvableNFT is ERC721Upgradeable, AccessControlUpgradeable, UUPSUpgrade
109
114
  NFTData memory _nftData,
110
115
  bool _withStore,
111
116
  bytes memory _callData
112
- ) external onlyManager(_nftData.nftType) returns (uint256 tokenId) {
117
+ ) external returns (uint256 tokenId) {
118
+ _onlyManager(_nftData.nftType);
113
119
  if (_nftData.nftType == 0) revert BAD_NFTTYPE();
114
120
 
115
121
  bytes32 dataHash = keccak256(abi.encode(_nftData));
@@ -123,7 +129,7 @@ contract ProvableNFT is ERC721Upgradeable, AccessControlUpgradeable, UUPSUpgrade
123
129
  store.events.push(_nftData.events[i]);
124
130
  }
125
131
  }
126
- _mint(_to, _nftData.nftUri, dataHash, _callData);
132
+ _mint(_to, _nftData.nftUri, dataHash, _nftData, _callData);
127
133
  }
128
134
 
129
135
  function proveNFTData(uint256 _tokenId, NFTData memory _nftData) public view returns (NFTData memory data) {