forked from 0xKiwi/dApps-for-funsies
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVTK2XToken.sol
382 lines (329 loc) · 13.9 KB
/
VTK2XToken.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
pragma solidity ^0.4.23;
import "./ERC223ReceivingContract.sol";
/**
* @title SafeMath
* @dev Math operations with safety checks that revert on error
*/
library 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 div(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b > 0); // Solidity only automatically asserts when dividing by 0
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
uint256 c = a - b;
return c;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b != 0);
return a % b;
}
}
/// @title Base Token contract
contract Token {
/*
* Implements ERC 20 standard.
* https://github.com/ethereum/EIPs/blob/f90864a3d2b2b45c4decf95efd26b3f0c276051a/EIPS/eip-20-token-standard.md
* https://github.com/ethereum/EIPs/issues/20
*
* Added support for the ERC 223 "tokenFallback" method in a "transfer" function with a payload.
* https://github.com/ethereum/EIPs/issues/223
*/
uint256 public totalSupply;
/*
* ERC 20
*/
function balanceOf(address _owner) public view returns (uint256 balance);
function transfer(address _to, uint256 _value) public returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public returns (bool success);
function allowance(address _owner, address _spender) public view returns (uint256 remaining);
/*
* ERC 223
*/
function transfer(address _to, uint256 _value, bytes _data) public returns (bool success);
/*
* Events
*/
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
/// @title Standard token contract - Standard token implementation.
contract StandardToken is Token {
/*
* Data structures
*/
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
/// @notice Allows `_spender` to transfer `_value` tokens from `msg.sender` to any address.
/// @dev Sets approved amount of tokens for spender. Returns success.
/// @param _spender Address of allowed account.
/// @param _value Number of approved tokens.
/// @return Returns success of function call.
function approve(address _spender, uint256 _value) public returns (bool) {
require(_spender != 0x0);
// 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
require(_value == 0 || allowed[msg.sender][_spender] == 0);
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
/*
* Read functions
*/
/// @dev Returns number of allowed tokens that a spender can transfer on
/// behalf of a token owner.
/// @param _owner Address of token owner.
/// @param _spender Address of token spender.
/// @return Returns remaining allowance for spender.
function allowance(address _owner, address _spender)
public
view
returns (uint256)
{
return allowed[_owner][_spender];
}
/// @dev Returns number of tokens owned by the given address.
/// @param _owner Address of token owner.
/// @return Returns balance of owner.
function balanceOf(address _owner) public view returns (uint256) {
return balances[_owner];
}
}
/// @title Vitalik2X Token
contract Vitalik2XToken is StandardToken {
using SafeMath for uint256;
/*
* Token metadata
*/
string constant public symbol = "V2X";
string constant public name = "Vitalik2X";
uint256 constant public decimals = 18;
uint256 constant public multiplier = 10 ** decimals;
address public owner;
uint256 public creationBlock;
uint256 public mainPotTokenBalance;
uint256 public mainPotETHBalance;
mapping (address => uint256) blockLock;
event Mint(address indexed to, uint256 amount);
event DonatedTokens(address indexed donator, uint256 amount);
event DonatedETH(address indexed donator, uint256 amount);
event SoldTokensFromPot(address indexed seller, uint256 amount);
event BoughtTokensFromPot(address indexed buyer, uint256 amount);
/*
* Public functions
*/
/// @dev Function create the token and distribute to the deploying address
constructor() public {
owner = msg.sender;
totalSupply = 10 ** decimals;
balances[msg.sender] = totalSupply;
creationBlock = block.number;
emit Transfer(0x0, msg.sender, totalSupply);
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/*
* External Functions
*/
/// @dev Adds the tokens to the main Pot.
function donateTokensToMainPot(uint256 amount) external returns (bool){
require(_transfer(this, amount));
mainPotTokenBalance = mainPotTokenBalance.add(amount);
emit DonatedTokens(msg.sender, amount);
return true;
}
function donateETHToMainPot() external payable returns (bool){
require(msg.value > 0);
mainPotETHBalance = mainPotETHBalance.add(msg.value);
emit DonatedETH(msg.sender, msg.value);
return true;
}
/// @dev Automatically sends a proportional percent of the ETH balance from the pot for proportion of the Tokens deposited.
function sellTokensToPot(uint256 amount) external returns (bool) {
uint256 amountBeingPaid = ethSliceAmount(amount);
require(amountBeingPaid <= ethSliceCap(), "Token amount sent is above the cap.");
require(_transfer(this, amount));
mainPotTokenBalance = mainPotTokenBalance.add(amount);
mainPotETHBalance = mainPotETHBalance.sub(amountBeingPaid);
msg.sender.transfer(amountBeingPaid);
emit SoldTokensFromPot(msg.sender, amount);
return true;
}
/// @dev Automatically sends a proportional percent of the VTK2X token balance from the pot for proportion of the ETH deposited.
function buyTokensFromPot() external payable returns (uint256) {
require(msg.value > 0);
uint256 amountBuying = tokenSliceAmount(msg.value);
require(amountBuying <= tokenSliceCap(), "Msg.value is above the cap.");
require(mainPotTokenBalance >= 1 finney, "Pot does not have enough tokens.");
mainPotETHBalance = mainPotETHBalance.add(msg.value);
mainPotTokenBalance = mainPotTokenBalance.sub(amountBuying);
balances[address(this)] = balances[address(this)].sub(amountBuying);
balances[msg.sender] = balances[msg.sender].add(amountBuying);
emit Transfer(address(this), msg.sender, amountBuying);
emit BoughtTokensFromPot(msg.sender, amountBuying);
return amountBuying;
}
/// @dev Returns the block number the given address is locked until.
/// @param _owner Address of token owner.
/// @return Returns block number the lock is released.
function blockLockOf(address _owner) external view returns (uint256) {
return blockLock[_owner];
}
/// @dev external function to retrieve ETH sent to the contract.
function withdrawETH() external onlyOwner {
owner.transfer(address(this).balance.sub(mainPotETHBalance));
}
/// @dev external function to retrieve tokens accidentally sent to the contract.
function withdrawToken(address token) external onlyOwner {
require(token != address(this));
Token erc20 = Token(token);
erc20.transfer(owner, erc20.balanceOf(this));
}
/*
* Public Functions
*/
/// @dev public function to retrieve the ETH amount.
function ethSliceAmount(uint256 amountOfTokens) public view returns (uint256) {
uint256 amountBuying = mainPotETHBalance.mul(amountOfTokens).div(mainPotTokenBalance);
amountBuying = amountBuying.sub(amountBuying.mul(amountOfTokens).div(mainPotTokenBalance));
return amountBuying;
}
/// @dev public function to retrieve the max ETH slice allotted.
function ethSliceCap() public view returns (uint256) {
return mainPotETHBalance.mul(30).div(100);
}
/// @dev public function to retrieve the percentage of ETH user wants from pot.
function ethSlicePercentage(uint256 amountOfTokens) public view returns (uint256) {
uint256 amountOfTokenRecieved = ethSliceAmount(amountOfTokens);
return amountOfTokenRecieved.mul(100).div(mainPotETHBalance);
}
/// @dev public function to retrieve the current pot reward amount.
function tokenSliceAmount(uint256 amountOfETH) public view returns (uint256) {
uint256 amountBuying = mainPotTokenBalance.mul(amountOfETH).div(mainPotETHBalance);
amountBuying = amountBuying.sub(amountBuying.mul(amountOfETH).div(mainPotETHBalance));
return amountBuying;
}
/// @dev public function to retrieve the max token slice allotted.
function tokenSliceCap() public view returns (uint256) {
return mainPotTokenBalance.mul(30).div(100);
}
/// @dev public function to retrieve the percentage of ETH user wants from pot.
function tokenSlicePercentage(uint256 amountOfEth) public view returns (uint256) {
uint256 amountOfEthRecieved = tokenSliceAmount(amountOfEth);
return amountOfEthRecieved.mul(100).div(mainPotTokenBalance);
}
/// @dev public function to check the status of account's lock.
function accountLocked() public view returns (bool) {
return (block.number < blockLock[msg.sender]);
}
function transfer(address _to, uint256 _value) public returns (bool) {
require(block.number >= blockLock[msg.sender], "Address is still locked.");
if (_to == address(this)) {
return _vitalikize(msg.sender, _value);
} else {
return _transfer(_to, _value);
}
}
/// @notice Send `_value` tokens to `_to` from `msg.sender` and trigger
/// tokenFallback if sender is a contract.
/// @dev Function that is called when a user or another contract wants to transfer funds.
/// @param _to Address of token receiver.
/// @param _value Number of tokens to transfer.
/// @param _data Data to be sent to tokenFallback
/// @return Returns success of function call.
function transfer(
address _to,
uint256 _value,
bytes _data)
public
returns (bool)
{
require(_to != address(this));
// Transfers tokens normally as per ERC20 standards
require(transfer(_to, _value));
uint codeLength;
assembly {
// Retrieve the size of the code on target address, this needs assembly.
codeLength := extcodesize(_to)
}
// If codeLength is > 0, it means it is a contract, handle fallback
if (codeLength > 0) {
ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
receiver.tokenFallback(msg.sender, _value, _data);
}
return true;
}
/// @notice Transfer `_value` tokens from `_from` to `_to` if `msg.sender` is allowed.
/// @dev Allows for an approved third party to transfer tokens from one
/// address to another. Returns success.
/// @param _from Address from where tokens are withdrawn.
/// @param _to Address to where tokens are sent.
/// @param _value Number of tokens to transfer.
/// @return Returns success of function call.
function transferFrom(address _from, address _to, uint256 _value)
public
returns (bool)
{
require(block.number >= blockLock[_from], "Address is still locked.");
require(_from != 0x0);
require(_to != 0x0);
require(_to != address(this));
// Balance of sender is legit
balances[_to] = balances[_to].add(_value);
balances[_from] = balances[_from].sub(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
emit Transfer(_from, _to, _value);
return true;
}
/*
* Internal functions
*/
/// @notice Send `_value` tokens to `_to` from `msg.sender`.
/// @dev Transfers sender's tokens to a given address. Returns success.
/// @param _to Address of token receiver.
/// @param _value Number of tokens to transfer.
/// @return Returns success of function call.
function _transfer(address _to, uint256 _value) internal returns (bool) {
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(msg.sender, _to, _value);
return true;
}
/// @dev Mints the amount of token passed and sends it to the sender
function _vitalikize(address _sender, uint256 _value) internal returns (bool) {
require(balances[_sender] >= _value, "Owner doesnt have enough tokens.");
uint256 calcBlockLock = (block.number - creationBlock)/5;
blockLock[_sender] = block.number + calcBlockLock;
If blockLock[_sender] >= block.number + 42000{
blockLock[_sender] = block.number + 42000;
}
require(mint(_sender, _value), "Minting failed");
emit Transfer(address(0), _sender, _value);
return true;
}
function mint(address _address, uint256 _amount) internal returns (bool) {
totalSupply = totalSupply.add(_amount);
balances[_address] = balances[_address].add(_amount);
return true;
}
}