-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackup.sol
466 lines (397 loc) · 19.3 KB
/
backup.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
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
/**
* @title The dreaming despoit smart contract
* @author lopahn2 / [email protected]
* @notice Agent for deposit distributor
*/
contract testContract {
///@notice When Contract be ended, ReadOnly
bool isContractRun;
///@notice non kicked user size
uint distributableDeositUserSize;
///@notice Response Msg for ABI server
string response_success_msg = "200_OK";
string response_post_success_msg = "201_OK";
string response_fail_msg = "400_FAIL";
///@notice Dreaming deposit object for control
DreamingDeposit dreamingDeposit;
///@notice Dreaming company wallet address identifier
address _owner;
constructor() {
_owner = msg.sender;
isContractRun = true;
}
/**
* @notice Set status of group
* @enum:pending -> recruit study group member status & not all payed group deposit
* @enum:start -> study group start after checking all guests pay the deposit
* @enum:end -> study group end when presetted time peroid over, in this status
* study group guest and host can pay back their deposit
*/
enum GroupStatus {
pending,
start,
end
}
/**
* @notice Set all contract behavior log recorded in this struct object
*
* @string:who -> dreaming / userId
* @uint:timestamp -> when transaction occurred
* @string:where -> group_id
* @uint:amount -> how mouch amount of money is transacted
* @string:from -> from
* @string:to -> to
* @string:why -> transaction reason
*/
struct DreamingLog {
string who;
uint timestamp;
string where;
uint amount;
string from;
string to;
string why;
}
DreamingLog[] dreamingLogs;
/**
* @notice The Dreaming Finance Info
* @key:deposit_balance -> unit (원)
* @key:dreamingFinance -> finance flow log when profit occured
*/
struct DreamingDeposit {
uint deposit_balance;
DreamingFinance[] dreamingFinance;
}
struct DreamingFinance {
string group_id;
string payer_id;
string payed_reason;
uint payed_amount;
uint timestamp;
}
/**
* @notice Study group members' deposit payment struct
* @key:deposit_amount -> unit (원)
* @key:payment_timestamp -> unit(unix time)
*/
struct Deposit {
string deposit_payer_id;
string warranty_pledge;
uint deposit_amount;
uint payment_timestamp;
bool kicked_flag;
}
/**
* @notice Study group contract details
* @key:group_capacity -> unit (명)
* @key:group_deposit_per_person -> unit (원)
* @key:group_period -> unit (unix time)
* @key:recruitment_period -> uint (unix time)
* @key:minimum_attendance -> uint
* @key: minimum_mission_completion -> uint
* @enum:GroupStatus
*/
struct GroupContract {
string leader_id;
string group_id;
uint group_capacity;
uint group_deposit_per_person;
uint group_deadline;
uint recruitment_period;
uint minimum_attendance;
uint minimum_mission_completion;
GroupStatus groupStatus;
}
///@notice Study Group Contract object for control
GroupContract groupContract;
/**
* @notice Study groups Deposits Finance Info are handled by studyGroupDeposits Array
*/
Deposit[] studyGroupDeposits;
/**
* @notice After stop the Study group, Final Study groups Deposits Balance and This Deposit[] only wrote one time.
*/
Deposit[] finalStudyGroupDeposits;
///@notice Check function caller is admin of the dreaming
modifier onlyOwner() {
require(msg.sender == _owner, "The caller is not owner.");
_;
}
///@notice Check function Contract is readOnly Status or Not
modifier isRun() {
require(isContractRun == true, "The Contract is end. Read Only");
_;
}
/**
* @notice Study group's initial contract create request handler
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function setStudyGroupContract(
string memory leader_id,
string memory group_id,
uint group_capacity,
uint group_deposit_per_person,
uint group_period,
uint recruitment_period,
uint minimum_attendance,
uint minimum_mission_completion
) isRun onlyOwner public returns(string memory) {
groupContract = GroupContract(
leader_id, group_id, group_capacity, group_deposit_per_person, (block.timestamp + (group_period * 1 days)),(block.timestamp + (recruitment_period * 1 days)),minimum_attendance ,minimum_mission_completion, GroupStatus(0)
);
distributableDeositUserSize = group_capacity + 1;
return(response_post_success_msg);
}
/**
* @notice Check if the points the client wants to pay are equal to the preset deposit
* @param client_payment : Points paid by the client
* @dev This Function is only callable in the contract
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function callCheckGroupDeposit(
uint client_payment
) private view returns(bool) {
if (groupContract.group_deposit_per_person == client_payment) {
return(true);
} else {
return(false);
}
}
/**
* @notice Check the client already paid the deposit
* @param user_id : Points paid by the client
* @dev This Function is only callable in the contract
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function callCheckAlreadyPayment(
string memory user_id
) private view returns(bool) {
for (uint i = 0; i < studyGroupDeposits.length; i++) {
if(keccak256(bytes(studyGroupDeposits[i].deposit_payer_id)) == keccak256(bytes(user_id))) {
return(false);
}
}
return (true);
}
/**
* @notice Check All clients are paid the deposit
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function callCheckAllClientsPayment() private view returns(bool) {
if (studyGroupDeposits.length == groupContract.group_capacity) {
return true;
}
return false;
}
/**
* @notice Check whether the user has paid
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function callCheckClientPaymentComplition(
string memory deposit_payer_id
) isRun public view returns(string memory) {
require(studyGroupDeposits.length != 0, "No one pay the deposit");
for (uint i; i < studyGroupDeposits.length; i++) {
if(keccak256(bytes(studyGroupDeposits[i].deposit_payer_id)) == keccak256(bytes(deposit_payer_id))) {
if (studyGroupDeposits[i].deposit_amount == groupContract.group_deposit_per_person) {
return(response_success_msg);
}
}
}
return(response_fail_msg);
}
/**
* @notice Calling the study group's deposit accounting details
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function callContractDepositDetail() public view returns(Deposit[] memory) {
return(studyGroupDeposits);
}
/**
* @notice Calling the study group's Contract details
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function callContractDetail() public view returns(GroupContract memory) {
return(groupContract);
}
/**
* @notice Calling the Dreaming's deposit accounting details
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function callDreamingDepositDetail() onlyOwner public view returns(DreamingDeposit memory) {
require(!isContractRun, "Contract is not ended. Want to check dreaming deposit, check dreaming log first.");
return dreamingDeposit;
}
/**
* @notice Calling the dreaming log array
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function callDreamingLog() onlyOwner public view returns(DreamingLog[] memory) {
return dreamingLogs;
}
/**
* @notice Calling the final study group deposits array
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function callFinalStudyGroupDeposits() onlyOwner public view returns(Deposit[] memory) {
require(!isContractRun, "Contract is not ended. Want to check deposit, check dreaming log first.");
return finalStudyGroupDeposits;
}
/**
* @notice Request to add the deposit amount to the deposit according to the contract
* @return bool : flag of all group member pay the deposit
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function patchClientPaymentDeposit(
string memory deposit_payer_id,
string memory warrenty_pledge,
string memory group_id,
uint deposit_amount
) isRun onlyOwner public returns(string memory) {
require(callCheckGroupDeposit(deposit_amount), "deposit amount is not same in the contarct");
require(callCheckAlreadyPayment(deposit_payer_id), "Already paid the deposit");
require(!callCheckAllClientsPayment(), "All Uer Already Paid the deposit");
studyGroupDeposits.push(Deposit(
deposit_payer_id,
warrenty_pledge,
deposit_amount,
block.timestamp,
false
));
dreamingLogs.push(DreamingLog(deposit_payer_id, block.timestamp, "dreaming_app", deposit_amount, "dreaming_app", group_id, "deposit payment for enrollment"));
if (studyGroupDeposits.length == groupContract.group_capacity) {
return(response_post_success_msg);
}
return(response_post_success_msg);
}
/**
* @notice Split the deposit of the kicked user equally among the rest and Dreaming
*
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function patchDistributeKickedClientDeposit(
string memory deposit_payer_id,
string memory group_id
) isRun onlyOwner public returns(string memory) {
require(distributableDeositUserSize > 1, "All People were kicked");
uint returnableDepositAmount = 0;
for (uint i = 0; i < studyGroupDeposits.length; i++) {
if(keccak256(bytes(studyGroupDeposits[i].deposit_payer_id)) == keccak256(bytes(deposit_payer_id))) {
require(studyGroupDeposits[i].deposit_amount != 0, "deposit payer balance is already 0");
dreamingLogs.push(DreamingLog(deposit_payer_id, block.timestamp, group_id, studyGroupDeposits[i].deposit_amount, group_id, "contract memory", "The deposit was taken because the user was kicked out."));
returnableDepositAmount += studyGroupDeposits[i].deposit_amount;
studyGroupDeposits[i].deposit_amount = 0;
studyGroupDeposits[i].kicked_flag = true;
distributableDeositUserSize -= 1;
break;
}
}
/// @dev split equally among the rest and Dreaming. Because Solidity can not handle float type
returnableDepositAmount /= distributableDeositUserSize;
dreamingDeposit.deposit_balance += returnableDepositAmount;
dreamingLogs.push(DreamingLog("dreaming", block.timestamp, "contract memory", returnableDepositAmount, "contract memory", "dreaming finance", "The deposit is distributed because user was kicked."));
dreamingDeposit.dreamingFinance.push(DreamingFinance(groupContract.group_id, deposit_payer_id, "Kick of player", returnableDepositAmount, block.timestamp));
for (uint i = 0; i < studyGroupDeposits.length; i++) {
if(keccak256(bytes(studyGroupDeposits[i].deposit_payer_id)) != keccak256(bytes(deposit_payer_id))) {
dreamingLogs.push(DreamingLog(studyGroupDeposits[i].deposit_payer_id, block.timestamp, "contract memory", returnableDepositAmount, "contract memory", group_id, "The deposit is distributed because user was kicked."));
studyGroupDeposits[i].deposit_amount += returnableDepositAmount;
}
}
return(response_post_success_msg);
}
/**
* @notice Forfeiture of deposit due to breach of contract
*
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function patchAttributeAllDepositsToDreaming(
string memory group_id
) isRun onlyOwner public returns(string memory) {
uint returnableDepositAmount = 0;
for (uint i = 0; i < studyGroupDeposits.length; i++) {
dreamingLogs.push(DreamingLog(studyGroupDeposits[i].deposit_payer_id, block.timestamp, group_id, studyGroupDeposits[i].deposit_amount, group_id, "contract memory", "Forfeiture of deposit due to breach of contract"));
returnableDepositAmount += studyGroupDeposits[i].deposit_amount;
studyGroupDeposits[i].deposit_amount = 0;
}
dreamingDeposit.deposit_balance += returnableDepositAmount;
dreamingDeposit.dreamingFinance.push(DreamingFinance(groupContract.group_id, "All Payed", "Boom Study Group ( breach of contract )", returnableDepositAmount, block.timestamp));
dreamingLogs.push(DreamingLog("dreaming", block.timestamp, "contract memory", returnableDepositAmount, "contract memory", "dreaming finance", "dreaming earn money because Forfeiture of deposit due to breach of contract"));
return(response_post_success_msg);
}
/**
* @notice Status change request after checking group termination conditions
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function putGroupStatusStartToEnd() isRun public returns(GroupStatus, string memory, GroupContract memory) {
uint nowUnixTime = block.timestamp;
require(nowUnixTime >= groupContract.group_deadline, "Study is not finished");
require(groupContract.groupStatus != GroupStatus(2), "Study is already ended");
groupContract.groupStatus = GroupStatus(2);
return(
groupContract.groupStatus,
response_post_success_msg,
groupContract
);
}
/**
* @notice Status change request after start condition
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function putGroupStatusPendingToStart() isRun public returns(GroupStatus, string memory, GroupContract memory) {
require(callCheckAllClientsPayment(), "All user need to pay the deposit before start the group study");
require(groupContract.groupStatus == GroupStatus(0), "Study is not pending status");
groupContract.groupStatus = GroupStatus(1);
return(
groupContract.groupStatus,
response_post_success_msg,
groupContract
);
}
/**
* @notice Return Dreaming Revenue when Study is end and is not stop.
* Also Balance is not zero.
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function putReturnDreamingAllDeposit() onlyOwner public returns(uint) {
require(dreamingDeposit.deposit_balance != 0, "Dreaming Deposit Balance is 0");
uint revenueOfDreamingInThisContract = dreamingDeposit.deposit_balance;
dreamingDeposit.deposit_balance = 0;
dreamingLogs.push(DreamingLog("dreaming", block.timestamp, "dreaming finance", revenueOfDreamingInThisContract, "dreaming finance", "dreaming app", "settles the profit that the service can earn."));
return revenueOfDreamingInThisContract;
}
/**
* @notice Return Dreaming Revenue when Study is end and is not stop.
* Also Balance is not zero.
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function putSettleDeposit() isRun onlyOwner public returns(string memory) {
GroupStatus groupStatus = groupContract.groupStatus;
require(groupStatus != GroupStatus(2), "Study is not ended");
uint _length = studyGroupDeposits.length;
for (uint i = 0; i < _length; i++) {
finalStudyGroupDeposits.push(studyGroupDeposits[i]);
studyGroupDeposits[i].deposit_amount = 0;
dreamingLogs.push(DreamingLog("dreaming", block.timestamp, studyGroupDeposits[i].deposit_payer_id, studyGroupDeposits[i].deposit_amount, studyGroupDeposits[i].deposit_payer_id, finalStudyGroupDeposits[i].deposit_payer_id, "Fixed final study group users balance"));
}
return response_success_msg;
}
/**
* @notice Study group stop request (when group_status is pending or end)
* @custom:error-handling : Node ABI server is Oracle for onchain data. Error handling is done in ABI Server.
*/
function stopStudyGroupContract() isRun public returns(string memory) {
GroupStatus groupStatus = groupContract.groupStatus;
require(groupStatus != GroupStatus(1), "Study is running now");
require(dreamingDeposit.deposit_balance == 0, "Dreaming Deposit is not payed to Dreaming");
uint _length = studyGroupDeposits.length;
for (uint i = 0; i < _length; i++) {
finalStudyGroupDeposits.push(studyGroupDeposits[i]);
studyGroupDeposits[i].deposit_amount = 0;
dreamingLogs.push(DreamingLog("dreaming", block.timestamp, studyGroupDeposits[i].deposit_payer_id, studyGroupDeposits[i].deposit_amount, studyGroupDeposits[i].deposit_payer_id, finalStudyGroupDeposits[i].deposit_payer_id, "Fixed final study group users balance"));
}
isContractRun = false;
return(response_post_success_msg);
}
}