-
Notifications
You must be signed in to change notification settings - Fork 4
/
DIVXTokenParse.sol
308 lines (245 loc) · 10.7 KB
/
DIVXTokenParse.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
pragma solidity ^0.4.11;
contract Token {
uint256 public totalSupply;
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);
}
/* ERC 20 token */
contract StandardToken is Token {
function transfer(address _to, uint256 _value) returns (bool success) {
if (balances[msg.sender] >= _value && _value > 0 && balances[_to] + _value > balances[_to]) {
balances[msg.sender] -= _value;
balances[_to] += _value;
Transfer(msg.sender, _to, _value);
return true;
} else {
return false;
}
}
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
balances[_to] += _value;
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
Transfer(_from, _to, _value);
return true;
} else {
return false;
}
}
function balanceOf(address _owner) constant returns (uint256 balance) {
return balances[_owner];
}
function approve(address _spender, uint256 _value) returns (bool success) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
}
/* taking ideas from FirstBlood token */
contract SafeMath {
function safeAdd(uint256 x, uint256 y) internal returns(uint256) {
uint256 z = x + y;
assert((z >= x));
return z;
}
function safeSubtract(uint256 x, uint256 y) internal constant returns(uint256) {
assert(x >= y);
return x - y;
}
function safeMult(uint256 x, uint256 y) internal constant returns(uint256) {
uint256 z = x * y;
assert((x == 0)||(z/x == y));
return z;
}
function safeDiv(uint256 x, uint256 y) internal constant returns (uint256) {
uint256 z = x / y;
return z;
}
}
contract DIVXToken is StandardToken, SafeMath {
// metadata
string public constant name = "Divi Exchange Token";
string public constant symbol = "DIVX";
uint256 public constant decimals = 18;
string public version = "1.0";
// owner address
address public fundDeposit; // deposit address for ETH and DIVX for the project
// crowdsale parameters
bool public isPaused;
bool public isRedeeming;
uint256 public fundingStartBlock;
uint256 public firstXRChangeBlock;
uint256 public secondXRChangeBlock;
uint256 public thirdXRChangeBlock;
uint256 public fundingEndBlock;
// Since we have different exchange rates at different stages, we need to keep track
// of how much ether (in units of Wei) each address contributed in case that we need
// to issue a refund
mapping (address => uint256) private weiBalances;
// We need to keep track of how much ether (in units of Wei) has been contributed
uint256 public totalReceivedWei;
uint256 public constant privateExchangeRate = 1000; // 1000 DIVX tokens per 1 ETH
uint256 public constant firstExchangeRate = 650; // 650 DIVX tokens per 1 ETH
uint256 public constant secondExchangeRate = 575; // 575 DIVX tokens per 1 ETH
uint256 public constant thirdExchangeRate = 500; // 500 DIVX tokens per 1 ETH
uint256 public constant receivedWeiCap = 100 * (10**3) * 10**decimals;
uint256 public constant receivedWeiMin = 5 * (10**3) * 10**decimals;
// events
event LogCreate(address indexed _to, uint256 _value, uint256 _tokenValue);
event LogRefund(address indexed _to, uint256 _value, uint256 _tokenValue);
event LogRedeem(address indexed _to, uint256 _value, bytes32 _diviAddress);
// modifiers
modifier onlyOwner() {
require(msg.sender == fundDeposit);
_;
}
modifier isNotPaused() {
require(isPaused == false);
_;
}
// constructor
function DIVXToken(
address _fundDeposit,
uint256 _fundingStartBlock,
uint256 _firstXRChangeBlock,
uint256 _secondXRChangeBlock,
uint256 _thirdXRChangeBlock,
uint256 _fundingEndBlock) {
isPaused = false;
isRedeeming = false;
totalSupply = 0;
totalReceivedWei = 0;
fundDeposit = _fundDeposit;
fundingStartBlock = _fundingStartBlock;
firstXRChangeBlock = _firstXRChangeBlock;
secondXRChangeBlock = _secondXRChangeBlock;
thirdXRChangeBlock = _thirdXRChangeBlock;
fundingEndBlock = _fundingEndBlock;
}
// overriden methods
// Overridden method to check that the minimum was reached (no refund is possible
// after that, so transfer of tokens shouldn't be a problem)
function transfer(address _to, uint256 _value) returns (bool success) {
require(totalReceivedWei >= receivedWeiMin);
return super.transfer(_to, _value);
}
// Overridden method to check that the minimum was reached (no refund is possible
// after that, so transfer of tokens shouldn't be a problem)
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
require(totalReceivedWei >= receivedWeiMin);
return super.transferFrom(_from, _to, _value);
}
/// @dev Accepts ether and creates new DIVX tokens.
function createTokens() payable external isNotPaused {
require(block.number >= fundingStartBlock);
require(block.number <= fundingEndBlock);
require(msg.value > 0);
// Check that this transaction wouldn't exceed the ETH cap
uint256 checkedReceivedWei = safeAdd(totalReceivedWei, msg.value);
require(checkedReceivedWei <= receivedWeiCap);
// Calculate how many tokens (in units of Wei) should be awarded
// on this transaction
uint256 tokens = safeMult(msg.value, getCurrentTokenPrice());
// Calculate how many tokens (in units of Wei) should be awarded to the project (20%)
uint256 projectTokens = safeDiv(tokens, 5);
// Increment the total received ETH
totalReceivedWei = checkedReceivedWei;
// Only update our accounting of how much ETH this contributor has sent us if
// we're already on the public sale (since private sale contributions are going
// to be used before the end of end of the sale period, they don't get a refund)
if (block.number >= firstXRChangeBlock) weiBalances[msg.sender] += msg.value;
// Increment the total supply of tokens and then deposit the tokens
// to the contributor
totalSupply = safeAdd(totalSupply, tokens);
balances[msg.sender] += tokens;
// Increment the total supply of tokens and then deposit the tokens
// to the project
totalSupply = safeAdd(totalSupply, projectTokens);
balances[fundDeposit] += projectTokens;
LogCreate(msg.sender, msg.value, tokens); // logs token creation
}
/// @dev Allows to transfer ether from the contract to the multisig wallet
function withdrawWei(uint256 _value) external onlyOwner isNotPaused {
require(_value <= this.balance);
// Allow withdrawal during the private sale, but after that, only allow
// withdrawal if we already met the minimum
require((block.number < firstXRChangeBlock) || (totalReceivedWei >= receivedWeiMin));
// send the eth to the project multisig wallet
fundDeposit.transfer(_value);
}
/// @dev Pauses the contract
function pause() external onlyOwner isNotPaused {
// Move the contract to Paused state
isPaused = true;
}
/// @dev Resume the contract
function resume() external onlyOwner {
// Move the contract out of the Paused state
isPaused = false;
}
/// @dev Starts the redeeming phase of the contract
function startRedeeming() external onlyOwner isNotPaused {
// Move the contract to Redeeming state
isRedeeming = true;
}
/// @dev Stops the redeeming phase of the contract
function stopRedeeming() external onlyOwner isNotPaused {
// Move the contract out of the Redeeming state
isRedeeming = false;
}
/// @dev Allows contributors to recover their ether in the case of a failed funding campaign
function refund() external {
// prevents refund until sale period is over
require(block.number > fundingEndBlock);
// Refunds are only available if the minimum was not reached
require(totalReceivedWei < receivedWeiMin);
// Retrieve how much DIVX (in units of Wei) this account has
uint256 divxVal = balances[msg.sender];
require(divxVal > 0);
// Retrieve how much ETH (in units of Wei) this account contributed
uint256 weiVal = weiBalances[msg.sender];
require(weiVal > 0);
// Destroy this contributor's tokens and reduce the total supply
balances[msg.sender] = 0;
totalSupply = safeSubtract(totalSupply, divxVal);
// Log this refund operation
LogRefund(msg.sender, weiVal, divxVal);
// Send the money back
msg.sender.transfer(weiVal);
}
/// @dev Redeems tokens and records the address that the sender created in the new blockchain
function redeem(bytes32 diviAddress) external {
// Only allow this function to be called when on the redeeming state
require(isRedeeming);
// Retrieve how much DIVX (in units of Wei) this account has
uint256 divxVal = balances[msg.sender];
require(divxVal > 0);
// Move the tokens of the caller to the project's address
assert(super.transfer(fundDeposit, divxVal));
// Log the redeeming of this tokens
LogRedeem(msg.sender, divxVal, diviAddress);
}
/// @dev Returns the current token price
function getCurrentTokenPrice() private constant returns (uint256 currentPrice) {
if (block.number < firstXRChangeBlock) {
return privateExchangeRate;
} else if (block.number < secondXRChangeBlock) {
return firstExchangeRate;
} else if (block.number < thirdXRChangeBlock) {
return secondExchangeRate;
} else {
return thirdExchangeRate;
}
}
}