-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCANA Smart Contract.sol
397 lines (330 loc) · 11.9 KB
/
CANA Smart Contract.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
pragma solidity ^0.4.19;
/*
* Creator: CANA (cannabis seed token)
*/
/*
* Abstract Token Smart Contract
*
*/
/*
* Safe Math Smart Contract.
* https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/math/SafeMath.sol
*/
contract SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
function safeDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function safeSub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function safeAdd(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
/**
* ERC-20 standard token interface, as defined
* <a href="http://github.com/ethereum/EIPs/issues/20">here</a>.
*/
contract Token {
function totalSupply() constant returns (uint256 supply);
function balanceOf(address _owner) constant returns (uint256 balance);
function transfer(address _to, uint256 _value) returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
function approve(address _spender, uint256 _value) returns (bool success);
function allowance(address _owner, address _spender) constant returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
/**
* Abstract Token Smart Contract that could be used as a base contract for
* ERC-20 token contracts.
*/
contract AbstractToken is Token, SafeMath {
/**
* Create new Abstract Token contract.
*/
function AbstractToken () {
// Do nothing
}
/**
* Get number of tokens currently belonging to given owner.
*
* @param _owner address to get number of tokens currently belonging to the
* owner of
* @return number of tokens currently belonging to the owner of given address
*/
function balanceOf(address _owner) constant returns (uint256 balance) {
return accounts [_owner];
}
/**
* Transfer given number of tokens from message sender to given recipient.
*
* @param _to address to transfer tokens to the owner of
* @param _value number of tokens to transfer to the owner of given address
* @return true if tokens were transferred successfully, false otherwise
* accounts [_to] + _value > accounts [_to] for overflow check
* which is already in safeMath
*/
function transfer(address _to, uint256 _value) returns (bool success) {
require(_to != address(0));
if (accounts [msg.sender] < _value) return false;
if (_value > 0 && msg.sender != _to) {
accounts [msg.sender] = safeSub (accounts [msg.sender], _value);
accounts [_to] = safeAdd (accounts [_to], _value);
}
Transfer (msg.sender, _to, _value);
return true;
}
/**
* Transfer given number of tokens from given owner to given recipient.
*
* @param _from address to transfer tokens from the owner of
* @param _to address to transfer tokens to the owner of
* @param _value number of tokens to transfer from given owner to given
* recipient
* @return true if tokens were transferred successfully, false otherwise
* accounts [_to] + _value > accounts [_to] for overflow check
* which is already in safeMath
*/
function transferFrom(address _from, address _to, uint256 _value)
returns (bool success) {
require(_to != address(0));
if (allowances [_from][msg.sender] < _value) return false;
if (accounts [_from] < _value) return false;
if (_value > 0 && _from != _to) {
allowances [_from][msg.sender] = safeSub (allowances [_from][msg.sender], _value);
accounts [_from] = safeSub (accounts [_from], _value);
accounts [_to] = safeAdd (accounts [_to], _value);
}
Transfer(_from, _to, _value);
return true;
}
/**
* Allow given spender to transfer given number of tokens from message sender.
* @param _spender address to allow the owner of to transfer tokens from message sender
* @param _value number of tokens to allow to transfer
* @return true if token transfer was successfully approved, false otherwise
*/
function approve (address _spender, uint256 _value) returns (bool success) {
allowances [msg.sender][_spender] = _value;
Approval (msg.sender, _spender, _value);
return true;
}
/**
* Tell how many tokens given spender is currently allowed to transfer from
* given owner.
*
* @param _owner address to get number of tokens allowed to be transferred
* from the owner of
* @param _spender address to get number of tokens allowed to be transferred
* by the owner of
* @return number of tokens given spender is currently allowed to transfer
* from given owner
*/
function allowance(address _owner, address _spender) constant
returns (uint256 remaining) {
return allowances [_owner][_spender];
}
/**
* Mapping from addresses of token holders to the numbers of tokens belonging
* to these token holders.
*/
mapping (address => uint256) accounts;
/**
* Mapping from addresses of token holders to the mapping of addresses of
* spenders to the allowances set by these token holders to these spenders.
*/
mapping (address => mapping (address => uint256)) private allowances;
}
/**
* cana token smart contract.
*/
contract CANAToken is AbstractToken {
/**
* Maximum allowed number of tokens in circulation.
* tokenSupply = tokensIActuallyWant * (10 ^ decimals)
*/
uint256 constant MAX_TOKEN_COUNT = 12000000 * (10**18);
/**
* Address of the owner of this smart contract.
*/
address private owner;
/**
* Frozen account list holder
*/
mapping (address => bool) private frozenAccount;
/**
* Current number of tokens in circulation.
*/
uint256 tokenCount = 0;
/**
* True if tokens transfers are currently frozen, false otherwise.
*/
bool frozen = false;
/**
* Create new token smart contract and make msg.sender the
* owner of this smart contract.
*/
function CANAToken () {
owner = msg.sender;
}
/**
* Get total number of tokens in circulation.
*
* @return total number of tokens in circulation
*/
function totalSupply() constant returns (uint256 supply) {
return tokenCount;
}
string constant public name = "cannabis seed token";
string constant public symbol = "CANA";
uint8 constant public decimals = 18;
/**
* Transfer given number of tokens from message sender to given recipient.
* @param _to address to transfer tokens to the owner of
* @param _value number of tokens to transfer to the owner of given address
* @return true if tokens were transferred successfully, false otherwise
*/
function transfer(address _to, uint256 _value) returns (bool success) {
require(!frozenAccount[msg.sender]);
if (frozen) return false;
else return AbstractToken.transfer (_to, _value);
}
/**
* Transfer given number of tokens from given owner to given recipient.
*
* @param _from address to transfer tokens from the owner of
* @param _to address to transfer tokens to the owner of
* @param _value number of tokens to transfer from given owner to given
* recipient
* @return true if tokens were transferred successfully, false otherwise
*/
function transferFrom(address _from, address _to, uint256 _value)
returns (bool success) {
require(!frozenAccount[_from]);
if (frozen) return false;
else return AbstractToken.transferFrom (_from, _to, _value);
}
/**
* Change how many tokens given spender is allowed to transfer from message
* spender. In order to prevent double spending of allowance,
* To change the approve amount you first have to reduce the addresses`
* allowance to zero by calling `approve(_spender, 0)` if it is not
* already 0 to mitigate the race condition described here:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* @param _spender address to allow the owner of to transfer tokens from
* message sender
* @param _value number of tokens to allow to transfer
* @return true if token transfer was successfully approved, false otherwise
*/
function approve (address _spender, uint256 _value)
returns (bool success) {
require(allowance (msg.sender, _spender) == 0 || _value == 0);
return AbstractToken.approve (_spender, _value);
}
/**
* Create _value new tokens and give new created tokens to msg.sender.
* May only be called by smart contract owner.
*
* @param _value number of tokens to create
* @return true if tokens were created successfully, false otherwise
*/
function createTokens(uint256 _value)
returns (bool success) {
require (msg.sender == owner);
if (_value > 0) {
if (_value > safeSub (MAX_TOKEN_COUNT, tokenCount)) return false;
accounts [msg.sender] = safeAdd (accounts [msg.sender], _value);
tokenCount = safeAdd (tokenCount, _value);
// adding transfer event and _from address as null address
Transfer(0x0, msg.sender, _value);
return true;
}
return false;
}
/**
* Set new owner for the smart contract.
* May only be called by smart contract owner.
*
* @param _newOwner address of new owner of the smart contract
*/
function setOwner(address _newOwner) {
require (msg.sender == owner);
owner = _newOwner;
}
/**
* Freeze ALL token transfers.
* May only be called by smart contract owner.
*/
function freezeTransfers () {
require (msg.sender == owner);
if (!frozen) {
frozen = true;
Freeze ();
}
}
/**
* Unfreeze ALL token transfers.
* May only be called by smart contract owner.
*/
function unfreezeTransfers () {
require (msg.sender == owner);
if (frozen) {
frozen = false;
Unfreeze ();
}
}
/*A user is able to unintentionally send tokens to a contract
* and if the contract is not prepared to refund them they will get stuck in the contract.
* The same issue used to happen for Ether too but new Solidity versions added the payable modifier to
* prevent unintended Ether transfers. However, there’s no such mechanism for token transfers.
* so the below function is created
*/
function refundTokens(address _token, address _refund, uint256 _value) {
require (msg.sender == owner);
require(_token != address(this));
AbstractToken token = AbstractToken(_token);
token.transfer(_refund, _value);
RefundTokens(_token, _refund, _value);
}
/**
* Freeze specific account
* May only be called by smart contract owner.
*/
function freezeAccount(address _target, bool freeze) {
require (msg.sender == owner);
require (msg.sender != _target);
frozenAccount[_target] = freeze;
FrozenFunds(_target, freeze);
}
/**
* Logged when token transfers were frozen.
*/
event Freeze ();
/**
* Logged when token transfers were unfrozen.
*/
event Unfreeze ();
/**
* Logged when a particular account is frozen.
*/
event FrozenFunds(address target, bool frozen);
/**
* when accidentally send other tokens are refunded
*/
event RefundTokens(address _token, address _refund, uint256 _value);
}