-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest2.sol
434 lines (368 loc) · 16 KB
/
test2.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
/**
*Submitted for verification at Etherscan.io on 2018-04-21
*/
/*
This file is part of the Cryptaur Contract.
The CryptaurToken Contract is free software: you can redistribute it and/or
modify it under the terms of the GNU lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. See the GNU lesser General Public License
for more details.
You should have received a copy of the GNU lesser General Public License
along with the CryptaurToken Contract. If not, see <http://www.gnu.org/licenses/>.
@author Ilya Svirin <[email protected]>
Donation address 0x3Ad38D1060d1c350aF29685B2b8Ec3eDE527452B
*/
pragma solidity ^0.4.19;
contract owned {
address public owner;
address public candidate;
function owned() payable public {
owner = msg.sender;
}
modifier onlyOwner {
require(owner == msg.sender);
_;
}
function changeOwner(address _owner) onlyOwner public {
candidate = _owner;
}
function confirmOwner() public {
require(candidate == msg.sender);
owner = candidate;
delete candidate;
}
}
/**
* @title Part of ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
contract ERC20Base {
uint public totalSupply;
function balanceOf(address who) public constant returns (uint);
function transfer(address to, uint value) public;
}
contract CryptaurRewards {
function payment(address _buyer, address _seller, uint _amount, address _opinionLeader) public returns(uint fee);
}
contract CryputarReserveFund {
function depositNotification(uint _amount) public;
function withdrawNotification(uint _amount) public;
}
/**
* @title Allows to store liked adsress(slave address) connected to the main address (master address)
*/
contract AddressBook {
struct AddressRelations {
SlaveDictionary slaves;
bool hasValue;
}
struct SlaveDictionary
{
address[] values;
mapping(address => uint) keys;
}
event WalletLinked(address indexed _master, address indexed _slave);
event WalletUnlinked(address indexed _master, address indexed _slave);
event AddressChanged(address indexed _old, address indexed _new);
mapping(address => AddressRelations) private masterToSlaves;
mapping(address => address) private slaveToMasterAddress;
uint8 public maxLinkedWalletCount = 5;
function AddressBook() public {}
function getLinkedWallets(address _wallet) public view returns (address[]) {
return masterToSlaves[_wallet].slaves.values;
}
/**
* Only owner of master wallet can add additional wallet.
*/
function linkToMasterWalletInternal(address _masterWallet, address _linkedWallet) internal {
require(_masterWallet != _linkedWallet && _linkedWallet != address(0));
require(isMasterWallet(_masterWallet));
require(!isLinkedWallet(_linkedWallet) && !isMasterWallet(_linkedWallet));
AddressRelations storage rel = masterToSlaves[_masterWallet];
require(rel.slaves.values.length < maxLinkedWalletCount);
rel.slaves.values.push(_linkedWallet);
rel.slaves.keys[_linkedWallet] = rel.slaves.values.length - 1;
slaveToMasterAddress[_linkedWallet] = _masterWallet;
WalletLinked(_masterWallet, _linkedWallet);
}
function unLinkFromMasterWalletInternal(address _masterWallet, address _linkedWallet) internal {
require(_masterWallet != _linkedWallet && _linkedWallet != address(0));
require(_masterWallet == getMasterWallet(_linkedWallet));
SlaveDictionary storage slaves = masterToSlaves[_masterWallet].slaves;
uint indexToDelete = slaves.keys[_linkedWallet];
address keyToMove = slaves.values[slaves.values.length - 1];
slaves.values[indexToDelete] = keyToMove;
slaves.keys[keyToMove] = indexToDelete;
slaves.values.length--;
delete slaves.keys[_linkedWallet];
delete slaveToMasterAddress[_linkedWallet];
WalletUnlinked(_masterWallet, _linkedWallet);
}
function isMasterWallet(address _addr) internal constant returns (bool) {
return masterToSlaves[_addr].hasValue;
}
function isLinkedWallet(address _addr) internal constant returns (bool) {
return slaveToMasterAddress[_addr] != address(0);
}
/**
* Guess that address book already had changing address.
*/
function applyChangeWalletAddress(address _old, address _new) internal {
require(isMasterWallet(_old) || isLinkedWallet(_old));
require(_new != address(0));
if (isMasterWallet(_old)) {
// Cannt change master address with existed linked
require(!isLinkedWallet(_new));
require(masterToSlaves[_new].slaves.values.length == 0);
changeMasterAddress(_old, _new);
}
else {
// Cannt change linked address with existed master and linked to another master
require(!isMasterWallet(_new) && !isLinkedWallet(_new));
changeLinkedAddress(_old, _new);
}
}
function addMasterWallet(address _master) internal {
require(_master != address(0));
masterToSlaves[_master].hasValue = true;
}
function getMasterWallet(address _wallet) internal constant returns(address) {
if(isMasterWallet(_wallet))
return _wallet;
return slaveToMasterAddress[_wallet];
}
/**
* Try to find master address by any other; otherwise add to address book as master.
*/
function getOrAddMasterWallet(address _wallet) internal returns (address) {
address masterWallet = getMasterWallet(_wallet);
if (masterWallet == address(0))
addMasterWallet(_wallet);
return _wallet;
}
function changeLinkedAddress(address _old, address _new) internal {
slaveToMasterAddress[_new] = slaveToMasterAddress[_old];
SlaveDictionary storage slaves = masterToSlaves[slaveToMasterAddress[_new]].slaves;
uint index = slaves.keys[_old];
slaves.values[index] = _new;
delete slaveToMasterAddress[_old];
}
function changeMasterAddress(address _old, address _new) internal {
masterToSlaves[_new] = masterToSlaves[_old];
SlaveDictionary storage slaves = masterToSlaves[_new].slaves;
for (uint8 i = 0; i < slaves.values.length; ++i)
slaveToMasterAddress[slaves.values[i]] = _new;
delete masterToSlaves[_old];
}
}
contract CryptaurDepository is owned, AddressBook {
enum UnlimitedMode {UNLIMITED, LIMITED}
event Deposit(address indexed _who, uint _amount, bytes32 _txHash);
event Withdraw(address indexed _who, uint _amount);
event Payment(address indexed _buyer, address indexed _seller, uint _amount, address indexed _opinionLeader, bool _dapp);
event Freeze(address indexed _who, bool _freeze);
event Share(address indexed _who, address indexed _dapp, uint _amount);
event SetUnlimited(bool _unlimited, address indexed _dapp);
ERC20Base cryptaurToken = ERC20Base(0x88d50B466BE55222019D71F9E8fAe17f5f45FCA1);
address public cryptaurRecovery;
address public cryptaurRewards;
address public cryptaurReserveFund;
address public backend;
modifier onlyBackend {
require(backend == msg.sender);
_;
}
modifier onlyOwnerOrBackend {
require(owner == msg.sender || backend == msg.sender);
_;
}
modifier notFreezed {
require(!freezedAll && !freezed[msg.sender]);
_;
}
mapping(address => uint) internal balances;
mapping(address => mapping (address => uint256)) public available;
mapping(address => bool) public freezed;
mapping(address => mapping(address => UnlimitedMode)) public unlimitedMode;
bool freezedAll;
function CryptaurDepository() owned() public {}
function sub(uint _a, uint _b) internal pure returns (uint) {
assert(_b <= _a);
return _a - _b;
}
function add(uint _a, uint _b) internal pure returns (uint) {
uint c = _a + _b;
assert(c >= _a);
return c;
}
function balanceOf(address _who) constant public returns (uint) {
return balances[getMasterWallet(_who)];
}
function setUnlimitedMode(bool _unlimited, address _dapp) public {
address masterWallet = getOrAddMasterWallet(msg.sender);
unlimitedMode[masterWallet][_dapp] = _unlimited ? UnlimitedMode.UNLIMITED : UnlimitedMode.LIMITED;
SetUnlimited(_unlimited, _dapp);
}
function transferToToken(address[] _addresses) public onlyOwnerOrBackend {
for (uint index = 0; index < _addresses.length; index++) {
address addr = _addresses[index];
uint amount = balances[addr];
if (amount > 0) {
balances[addr] = 0;
cryptaurToken.transfer(addr, amount);
Withdraw(addr, amount);
}
}
}
function setBackend(address _backend) onlyOwner public {
backend = _backend;
}
function setCryptaurRecovery(address _cryptaurRecovery) onlyOwner public {
cryptaurRecovery = _cryptaurRecovery;
}
function setCryptaurToken(address _cryptaurToken) onlyOwner public {
cryptaurToken = ERC20Base(_cryptaurToken);
}
function setCryptaurRewards(address _cryptaurRewards) onlyOwner public {
cryptaurRewards = _cryptaurRewards;
}
function setCryptaurReserveFund(address _cryptaurReserveFund) onlyOwner public {
cryptaurReserveFund = _cryptaurReserveFund;
}
function changeAddress(address _old, address _new) public {
require(msg.sender == cryptaurRecovery);
applyChangeWalletAddress(_old, _new);
balances[_new] = add(balances[_new], balances[_old]);
balances[_old] = 0;
AddressChanged(_old, _new);
}
function linkToMasterWallet(address _linkedWallet) public {
linkToMasterWalletInternal(msg.sender, _linkedWallet);
}
function unLinkFromMasterWallet(address _linkedWallet) public {
unLinkFromMasterWalletInternal(msg.sender, _linkedWallet);
}
function linkToMasterWallet(address _masterWallet, address _linkedWallet) onlyOwnerOrBackend public {
linkToMasterWalletInternal(_masterWallet, _linkedWallet);
}
function unLinkFromMasterWallet(address _masterWallet, address _linkedWallet) onlyOwnerOrBackend public {
unLinkFromMasterWalletInternal(_masterWallet, _linkedWallet);
}
function setMaxLinkedWalletCount(uint8 _newMaxCount) public onlyOwnerOrBackend {
maxLinkedWalletCount = _newMaxCount;
}
function freeze(address _who, bool _freeze) onlyOwner public {
address masterWallet = getMasterWallet(_who);
if (masterWallet == address(0))
masterWallet = _who;
freezed[masterWallet] = _freeze;
Freeze(masterWallet, _freeze);
}
function freeze(bool _freeze) public onlyOwnerOrBackend {
freezedAll = _freeze;
}
function deposit(address _who, uint _amount, bytes32 _txHash) notFreezed onlyBackend public {
address masterWallet = getOrAddMasterWallet(_who);
require(!freezed[masterWallet]);
balances[masterWallet] = add(balances[masterWallet], _amount);
Deposit(masterWallet, _amount, _txHash);
}
function withdraw(uint _amount) public notFreezed {
address masterWallet = getMasterWallet(msg.sender);
require(balances[masterWallet] >= _amount);
require(!freezed[masterWallet]);
balances[masterWallet] = sub(balances[masterWallet], _amount);
cryptaurToken.transfer(masterWallet, _amount);
Withdraw(masterWallet, _amount);
}
function balanceOf2(address _who, address _dapp) constant public returns (uint) {
return balanceOf2Internal(getMasterWallet(_who), _dapp);
}
function balanceOf2Internal(address _who, address _dapp) constant internal returns (uint) {
uint avail;
if (!freezed[_who]) {
if (unlimitedMode[_who][_dapp] == UnlimitedMode.UNLIMITED) {
avail = balances[_who];
}
else {
avail = available[_who][_dapp];
if (avail > balances[_who])
avail = balances[_who];
}
}
return avail;
}
/**
* @dev Function pay wrapper auto share balance.
* When dapp pay to the client, increase its balance at first. Then share "_amount"
* of client balance to dapp for the further purchases.
*
* Only dapp wallet should use this function.
*/
function pay2(address _seller, uint _amount, address _opinionLeader) public notFreezed {
address dapp = getOrAddMasterWallet(msg.sender);
address seller = getOrAddMasterWallet(_seller);
require(!freezed[dapp] && !freezed[seller]);
payInternal(dapp, seller, _amount, _opinionLeader);
available[seller][dapp] = add(available[seller][dapp], _amount);
}
function pay(address _seller, uint _amount, address _opinionLeader) public notFreezed {
address buyer = getOrAddMasterWallet(msg.sender);
address seller = getOrAddMasterWallet(_seller);
require(!freezed[buyer] && !freezed[seller]);
payInternal(buyer, seller, _amount, _opinionLeader);
}
/**
* @dev Common internal pay function.
* OpinionLeader is optional, can be zero.
*/
function payInternal(address _buyer, address _seller, uint _amount, address _opinionLeader) internal {
require(balances[_buyer] >= _amount);
uint fee;
// if (cryptaurRewards != 0 && cryptaurReserveFund != 0) {
fee = CryptaurRewards(cryptaurRewards).payment(_buyer, _seller, _amount, _opinionLeader);
// }
balances[_buyer] = sub(balances[_buyer], _amount);
balances[_seller] = add(balances[_seller], _amount - fee);
if (fee != 0) {
balances[cryptaurReserveFund] = add(balances[cryptaurReserveFund], fee);
CryputarReserveFund(cryptaurReserveFund).depositNotification(_amount);
}
Payment(_buyer, _seller, _amount, _opinionLeader, false);
}
function payDAPP(address _buyer, uint _amount, address _opinionLeader) public notFreezed {
address buyerMasterWallet = getOrAddMasterWallet(_buyer);
require(balanceOf2Internal(buyerMasterWallet, msg.sender) >= _amount);
require(!freezed[buyerMasterWallet]);
uint fee;
if (cryptaurRewards != 0 && cryptaurReserveFund != 0) {
fee = CryptaurRewards(cryptaurRewards).payment(buyerMasterWallet, msg.sender, _amount, _opinionLeader);
}
balances[buyerMasterWallet] = sub(balances[buyerMasterWallet], _amount);
balances[msg.sender] = add(balances[msg.sender], _amount - fee);
if (unlimitedMode[buyerMasterWallet][msg.sender] == UnlimitedMode.LIMITED)
available[buyerMasterWallet][msg.sender] -= _amount;
if (fee != 0) {
balances[cryptaurReserveFund] += fee;
CryputarReserveFund(cryptaurReserveFund).depositNotification(_amount);
}
Payment(buyerMasterWallet, msg.sender, _amount, _opinionLeader, true);
}
function shareBalance(address _dapp, uint _amount) public notFreezed {
address masterWallet = getMasterWallet(msg.sender);
require(masterWallet != address(0));
require(!freezed[masterWallet]);
available[masterWallet][_dapp] = _amount;
Share(masterWallet, _dapp, _amount);
}
function transferFromFund(address _to, uint _amount) public {
require(msg.sender == owner || msg.sender == cryptaurRewards || msg.sender == backend);
require(cryptaurReserveFund != address(0));
require(balances[cryptaurReserveFund] >= _amount);
address masterWallet = getOrAddMasterWallet(_to);
balances[masterWallet] = add(balances[masterWallet], _amount);
balances[cryptaurReserveFund] = sub(balances[cryptaurReserveFund], _amount);
CryputarReserveFund(cryptaurReserveFund).withdrawNotification(_amount);
}
}