-
Notifications
You must be signed in to change notification settings - Fork 0
/
ContributionContract.sol
385 lines (352 loc) · 15 KB
/
ContributionContract.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "./voting/ContributionVotingContract.sol";
import "./interface/IRecords.sol";
import "./interface/ITracks.sol";
contract ContributionContract is Initializable {
using Counters for Counters.Counter;
/// @dev this is Contribution Create event this event will be emitted when a new contribution is created.
/// @param contributionId it is the unique identifier for the contribution
/// @param tracks are id of the tracks that are part of this contribution, you will have to manually fetch the
/// tracks data from trackId once you do the indexing.
/// @param title title of the contribution
/// @param createdAt createdAt is indicates the time of creation of the contribution
/// @param previewFile this is the file that contains the mix of the contribution also known as preview file
/// @param previewFileHash this is the hash of the preview file to make sure the previewFile is not tampered with
/// @param recordId this is the id of the record to which the contribution belong to
/// @param seedContribution this flag determines if the contribution is a seed contribution or not
/// @param roughMix this flag determines if the contribution is a new contribution, with new tracks or is it just mix
/// of all the previous tracks
/// @param status this is status of the contribution that is (PENDING = 1 | ACCEPTED = 2| REJECTED = 3)
/// @param description the description of record that is in text format
/// @param owner the owner of the contribution
event ContributionCreated(
uint256 contributionId,
uint256[] tracks,
string title,
uint256 createdAt,
string previewFile,
string previewFileHash,
uint256 recordId,
bool seedContribution,
bool roughMix,
uint256 status,
string description,
address owner
);
/// @dev This structure will store information of the contribution
/// @param tracks Array of id of tracks
/// @param title title of the contribution
/// @param createdAt blocknumber of when the contribution was created
/// @param previewFile This is the preview file link
/// @param previewFileHash This is the preview file hash
// / @param recordId This is the id of the record to which contribution belongs to
/// @param seedContribution This flag determines if it is a seed contribution or not
/// @param roughMix This flag determines if it is a rough mix or not, true if rough mix or else false
/// @param status This specifies the status of contribution PENDING = 1 | ACCEPTED = 2| REJECTED = 3
/// @param description This is the description that is entered by user
/// @param owner This is the owner of the contribution
/// @param isPresent This is to check if a contribution exists or not
struct Contribution {
uint256[] tracks;
string title;
uint256 createdAt;
string previewFile;
string previewFileHash;
bool seedContribution;
bool roughMix;
uint256 status;
string description;
address owner;
bool isPresent;
}
/// @param tracks Id of tracks that are part of this contribution
/// @param title title of the contribution
/// @param previewFile this is preview file of the contribution
/// @param previewFileHash this is hash of the preview file
/// @param recordId this is the id of the record to which contribution belongs to.
/// @param roughMix this represents if a contribution is a roughMix or is a new contribution
/// @param description this is the description of the new contribution that is created.
/// @param communityReward this is the amount of community token that the contributor is requesting
/// for his work contribution.
/// @param governanceReward this is the amount of governance token that the contributor is requesting for his
/// work contribution.
struct NewContributionPayload {
uint256[] tracks;
string title;
string previewFile;
string previewFileHash;
uint256 recordId;
bool roughMix;
string description;
uint256 communityReward;
uint256 governanceReward;
}
/// @param tracks Id of tracks that are part of this contribution
/// @param title it is the title of the contribution
/// @param previewFile this is preview file of the contribution
/// @param previewFileHash this is hash of the preview file
/// @param description this is the description of the new contribution that is created.
struct SeedContributionPayload {
uint256[] tracks;
string title;
string previewFile;
string previewFileHash;
string description;
}
Counters.Counter private _contributionIds;
address public OWNER;
address public CONTRIBUTION_VOTING_CONTRACT_ADDRESS;
ContributionVotingContract contributionVotingContract;
address public RECORD_CONTRACT_ADDRESS;
IRecords public recordsContract;
address public TRACKS_CONTRACT_ADDRESS;
ITracks public trackInterface;
address public CONTROLLER_CONTRACT_ADDRESS;
mapping(uint256 => Contribution) public contributionData;
uint256 public PENDING = 1;
uint256 public ACCEPTED = 2;
uint256 public REJECTED = 3;
constructor(address owner) {
OWNER = owner;
}
/// @dev Modifier to check that the person who accesses a specific function is the owner of contract himself.
modifier ownerOnly() {
require(msg.sender == OWNER, "UNAUTHORIZED: CANNOT_PERFORM_ACTION");
_;
}
/// @dev Modifier to restrict the function call from controller contract
modifier controllerContractOnly() {
require(
msg.sender == CONTROLLER_CONTRACT_ADDRESS,
"UNAUTHORIZED: CANNOT_PERFORM_ACTION"
);
_;
}
/// @dev This is to set the address of the contracts
/// @param newVotingContractAddress this is the address of new voting contract
/// @param newRecordsContractAddress this is the address of new Records contract
/// @param newTracksContractAddress this is the address of new tracks contract
/// @param controllerContractAddress this is the address of controller contract
function initialize(
address newVotingContractAddress,
address newRecordsContractAddress,
address newTracksContractAddress,
address controllerContractAddress
) public initializer ownerOnly {
CONTRIBUTION_VOTING_CONTRACT_ADDRESS = newVotingContractAddress;
contributionVotingContract = ContributionVotingContract(
CONTRIBUTION_VOTING_CONTRACT_ADDRESS
);
RECORD_CONTRACT_ADDRESS = newRecordsContractAddress;
recordsContract = IRecords(RECORD_CONTRACT_ADDRESS);
TRACKS_CONTRACT_ADDRESS = newTracksContractAddress;
trackInterface = ITracks(TRACKS_CONTRACT_ADDRESS);
CONTROLLER_CONTRACT_ADDRESS = controllerContractAddress;
}
/// @dev This function sets the owner address
/// @param ownerAddress This is the address of the owner
function setOwnerAddress(address ownerAddress) public ownerOnly {
OWNER = ownerAddress;
}
/// @dev This function returns contribution data
/// @param contributionId Id of the contribution whose data you want
function getContributionData(
uint256 contributionId
) public view returns (Contribution memory contribution) {
return contributionData[contributionId];
}
/// @dev This function will be called by the user to create a new contribution
/// @param payload this is the data required for creation of new contribution
/// @param platformWallet this is the UI providers wallet
/// @param platformFee this is the incentive amount for the UI maintainer
function createNewContribution(
NewContributionPayload memory payload,
address payable platformWallet,
uint256 platformFee
) public payable returns (uint256) {
{
require(msg.value >= platformFee, "INV: INSUFFICIENT_PLATFORM_FEE");
if (msg.value > 0) {
platformWallet.call{value: platformFee}("");
}
bool ownerStatus = trackInterface.checkOwner(
payload.tracks,
msg.sender
);
require(ownerStatus, "INVALID: NOT_A_TRACK_OWNER");
}
return
createContributionAndVoting(
payload,
msg.sender,
msg.value - platformFee
);
}
/// @dev This function will be called by the controller contract to create a new contribution and voting
/// @param payload this is the data required for creation of new contribution
/// @param owner this is the owner of the new contribution which is to be created
function controllerCreateNewContribution(
NewContributionPayload memory payload,
address owner
) public payable controllerContractOnly returns (uint256) {
return createContributionAndVoting(payload, owner, msg.value);
}
/// @dev This function is responsible to create a non seed contribution and to create voting for contribution
/// @param payload this is the data required for creation of new contribution
/// @param owner this is the owner of the contribution
/// @param depositAmount this is the deposit amount for voting creation
function createContributionAndVoting(
NewContributionPayload memory payload,
address owner,
uint256 depositAmount
) internal returns (uint256) {
uint256 contributionId = _createContribution(
payload.tracks,
payload.title,
payload.previewFile,
payload.previewFileHash,
payload.description,
payload.roughMix,
PENDING,
false,
owner,
payload.recordId
);
{
contributionVotingContract.createContributionVotingBallot{
value: depositAmount
}(
contributionId,
payload.recordId,
payload.governanceReward,
payload.communityReward
);
recordsContract.pushContributionIdToContributionList(
payload.recordId,
contributionId
);
}
return contributionId;
}
/// @dev This function will be called by the user to create a new seed contribution as there will be not voting
/// or anything like that
/// @param payload data for the seed contribution creation
/// @param platformWallet this is the UI providers wallet
/// @param platformFee this is the incentive amount for the UI maintainer
function createSeedContribution(
SeedContributionPayload memory payload,
address payable platformWallet,
uint256 platformFee
) public payable returns (uint256) {
{
require(msg.value >= platformFee, "INV: INSUFFICIENT_PLATFORM_FEE");
if (msg.value > 0) {
platformWallet.call{value: platformFee}("");
}
bool ownerStatus = trackInterface.checkOwner(
payload.tracks,
msg.sender
);
require(ownerStatus, "INVALID: NOT_A_TRACK_OWNER");
}
return
_createContribution(
payload.tracks,
payload.title,
payload.previewFile,
payload.previewFileHash,
payload.description,
false,
ACCEPTED,
true,
msg.sender,
0
);
}
/// @dev This function is to be called only by the controller contract that is created to bundle multiple contract calls into single function
/// @param payload data for the seed contribution creation
/// @param owner address of the owner of the seed contribution
function controllerCreateSeedContribution(
SeedContributionPayload memory payload,
address owner
) public controllerContractOnly returns (uint256) {
return
_createContribution(
payload.tracks,
payload.title,
payload.previewFile,
payload.previewFileHash,
payload.description,
false,
ACCEPTED,
true,
owner,
0
);
}
/// @dev This function is an internal function that creates the contribution
/// @param tracks Id of tracks that are part of this contribution
/// @param previewFile this is preview file of the contribution
/// @param previewFileHash this is hash of the preview file
/// @param description this is the description of the new contribution that is created.
/// @param roughMix this flag denotes if the contribution is a rough mix or a new contributions
/// @param status this is the status of the contribution
/// @param isSeed this denotes if it is seed contribution or not
/// @param owner this is the owner address
/// @param recordId this is the record id to which the contribution belongs
function _createContribution(
uint256[] memory tracks,
string memory title,
string memory previewFile,
string memory previewFileHash,
string memory description,
bool roughMix,
uint status,
bool isSeed,
address owner,
uint recordId
) internal returns (uint256) {
_contributionIds.increment();
uint256 contributionId = _contributionIds.current();
Contribution memory contribution = Contribution({
tracks: tracks,
title: title,
createdAt: block.timestamp,
previewFile: previewFile,
previewFileHash: previewFileHash,
roughMix: roughMix,
status: status,
description: description,
seedContribution: isSeed,
owner: owner,
isPresent: true
});
contributionData[contributionId] = contribution;
emitContributionCreated(contributionId, contribution, recordId);
return contributionId;
}
function emitContributionCreated(
uint256 contributionId,
Contribution memory contribution,
uint256 recordId
) internal {
emit ContributionCreated(
contributionId,
contribution.tracks,
contribution.title,
contribution.createdAt,
contribution.previewFile,
contribution.previewFileHash,
recordId,
contribution.seedContribution,
contribution.roughMix,
contribution.status,
contribution.description,
contribution.owner
);
}
}