-
Notifications
You must be signed in to change notification settings - Fork 97
/
Copy path0x2ca72c9699b92b47272c9716c664cad6167c80b0-GUNS-GeoUnits.sol
233 lines (189 loc) · 11.3 KB
/
0x2ca72c9699b92b47272c9716c664cad6167c80b0-GUNS-GeoUnits.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
pragma solidity ^0.4.11;
/*
Copyright 2017, Shaun Shull
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/// @title GUNS Crowdsale Contract - GeoFounders.com
/// @author Shaun Shull
/// @dev Simple single crowdsale contract for fixed supply, single-rate,
/// block-range crowdsale. Additional token cleanup functionality.
/// @dev Generic ERC20 Token Interface, totalSupply made to var for compiler
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);
}
/// @dev ERC20 Standard Token Contract
contract StandardToken is Token {
function transfer(address _to, uint256 _value) returns (bool success) {
if (balances[msg.sender] >= _value && _value > 0) {
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;
}
/// @dev Primary Token Contract
contract GUNS is StandardToken {
// metadata
string public constant name = "GeoUnits";
string public constant symbol = "GUNS";
uint256 public constant decimals = 18;
string public version = "1.0";
// contracts
address public hostAccount; // address that kicks off the crowdsale
address public ethFundDeposit; // deposit address for ETH for GeoFounders
address public gunsFundDeposit; // deposit address for GeoFounders Tokens - GeoUnits (GUNS)
// crowdsale parameters
bool public isFinalized; // false until crowdsale finalized
uint256 public fundingStartBlock; // start block
uint256 public fundingEndBlock; // end block
uint256 public constant gunsFund = 35 * (10**6) * 10**decimals; // 35m GUNS reserved for devs
uint256 public constant tokenExchangeRate = 1000; // 1000 GUNS per 1 ETH
uint256 public constant tokenCreationCap = 100 * (10**6) * 10**decimals; // 100m GUNS fixed supply
uint256 public constant tokenCreationMin = 1 * (10**6) * 10**decimals; // 1m minimum must be in supply (legacy code)
// events
event LogRefund(address indexed _to, uint256 _value); // event for refund
event CreateGUNS(address indexed _to, uint256 _value); // event for token creation
// safely add
function safeAdd(uint256 x, uint256 y) internal returns(uint256) {
uint256 z = x + y;
assert((z >= x) && (z >= y));
return z;
}
// safely subtract
function safeSubtract(uint256 x, uint256 y) internal returns(uint256) {
assert(x >= y);
uint256 z = x - y;
return z;
}
// safely multiply
function safeMult(uint256 x, uint256 y) internal returns(uint256) {
uint256 z = x * y;
assert((x == 0)||(z/x == y));
return z;
}
// constructor
function GUNS() {}
// initialize deployed contract
function initialize(
address _ethFundDeposit,
address _gunsFundDeposit,
uint256 _fundingStartBlock,
uint256 _fundingEndBlock
) public {
require(address(hostAccount) == 0x0); // one time initialize
hostAccount = msg.sender; // assign initializer var
isFinalized = false; // crowdsale state
ethFundDeposit = _ethFundDeposit; // set final ETH deposit address
gunsFundDeposit = _gunsFundDeposit; // set final GUNS dev deposit address
fundingStartBlock = _fundingStartBlock; // block number to start crowdsale
fundingEndBlock = _fundingEndBlock; // block number to end crowdsale
totalSupply = gunsFund; // update totalSupply to reserve
balances[gunsFundDeposit] = gunsFund; // deposit reserve tokens to dev address
CreateGUNS(gunsFundDeposit, gunsFund); // logs token creation event
}
// enable people to pay contract directly
function () public payable {
require(address(hostAccount) != 0x0); // initialization check
if (isFinalized) throw; // crowdsale state check
if (block.number < fundingStartBlock) throw; // within start block check
if (block.number > fundingEndBlock) throw; // within end block check
if (msg.value == 0) throw; // person actually sent ETH check
uint256 tokens = safeMult(msg.value, tokenExchangeRate); // calculate num of tokens purchased
uint256 checkedSupply = safeAdd(totalSupply, tokens); // calculate total supply if purchased
if (tokenCreationCap < checkedSupply) throw; // if exceeding token max, cancel order
totalSupply = checkedSupply; // update totalSupply
balances[msg.sender] += tokens; // update token balance for payer
CreateGUNS(msg.sender, tokens); // logs token creation event
}
// generic function to pay this contract
function emergencyPay() external payable {}
// wrap up crowdsale after end block
function finalize() external {
//if (isFinalized) throw; // check crowdsale state is false
if (msg.sender != ethFundDeposit) throw; // check caller is ETH deposit address
//if (totalSupply < tokenCreationMin) throw; // check minimum is met
if (block.number <= fundingEndBlock && totalSupply < tokenCreationCap) throw; // check past end block unless at creation cap
if (!ethFundDeposit.send(this.balance)) throw; // send account balance to ETH deposit address
uint256 remainingSupply = safeSubtract(tokenCreationCap, totalSupply); // calculate remaining tokens to reach fixed supply
if (remainingSupply > 0) { // if remaining supply left
uint256 updatedSupply = safeAdd(totalSupply, remainingSupply); // calculate total supply with remaining supply
totalSupply = updatedSupply; // update totalSupply
balances[gunsFundDeposit] += remainingSupply; // manually update devs token balance
CreateGUNS(gunsFundDeposit, remainingSupply); // logs token creation event
}
isFinalized = true; // update crowdsale state to true
}
// legacy code to enable refunds if min token supply not met (not possible with fixed supply)
function refund() external {
if (isFinalized) throw; // check crowdsale state is false
if (block.number <= fundingEndBlock) throw; // check crowdsale still running
if (totalSupply >= tokenCreationMin) throw; // check creation min was not met
if (msg.sender == gunsFundDeposit) throw; // do not allow dev refund
uint256 gunsVal = balances[msg.sender]; // get callers token balance
if (gunsVal == 0) throw; // check caller has tokens
balances[msg.sender] = 0; // set callers tokens to zero
totalSupply = safeSubtract(totalSupply, gunsVal); // subtract callers balance from total supply
uint256 ethVal = gunsVal / tokenExchangeRate; // calculate ETH from token exchange rate
LogRefund(msg.sender, ethVal); // log refund event
if (!msg.sender.send(ethVal)) throw; // send caller their refund
}
// clean up mistaken tokens sent to this contract
// also check empty address for tokens and clean out
// (GUNS only, does not support 3rd party tokens)
function mistakenTokens() external {
if (msg.sender != ethFundDeposit) throw; // check caller is ETH deposit address
if (balances[this] > 0) { // if contract has tokens
Transfer(this, gunsFundDeposit, balances[this]); // log transfer event
balances[gunsFundDeposit] += balances[this]; // send tokens to dev tokens address
balances[this] = 0; // zero out contract token balance
}
if (balances[0x0] > 0) { // if empty address has tokens
Transfer(0x0, gunsFundDeposit, balances[0x0]); // log transfer event
balances[gunsFundDeposit] += balances[0x0]; // send tokens to dev tokens address
balances[0x0] = 0; // zero out empty address token balance
}
}
}