pragma solidity ^0.4.12;
/**
* Overflow aware uint math functions.
*/
contract SafeMath {
function mul(uint256 a, uint256 b) internal returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal returns (uint256) {
uint256 c = a / b;
return c;
}
function pct(uint numerator, uint denominator, uint precision) internal returns(uint quotient) {
uint _numerator = numerator * 10 ** (precision+1);
uint _quotient = ((_numerator / denominator) + 5) / 10;
return (_quotient);
}
function sub(uint256 a, uint256 b) internal returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
function max64(uint64 a, uint64 b) internal constant returns (uint64) {
return a >= b ? a : b;
}
function min64(uint64 a, uint64 b) internal constant returns (uint64) {
return a < b ? a : b;
}
function max256(uint256 a, uint256 b) internal constant returns (uint256) {
return a >= b ? a : b;
}
function min256(uint256 a, uint256 b) internal constant returns (uint256) {
return a < b ? a : b;
}
}
/**
* ERC 20 token
*/
contract Token is SafeMath {
function transfer(address _to, uint256 _value) returns (bool success) {
if (balances[msg.sender] >= _value && _value > 0) {
balances[msg.sender] = sub(balances[msg.sender], _value);
balances[_to] = add(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] = add(balances[_to], _value);
balances[_from] = sub(balances[_from], _value);
allowed[_from][msg.sender] = sub(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];
}
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
uint256 public totalSupply;
// A vulernability of the approve method in the ERC20 standard was identified by
// Mikhail Vladimirov and Dmitry Khovratovich here:
// https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM
// It's better to use this method which is not susceptible to over-withdrawing by the approvee.
/// @param _spender The address to approve
/// @param _currentValue The previous value approved, which can be retrieved with allowance(msg.sender, _spender)
/// @param _newValue The new value to approve, this will replace the _currentValue
/// @return bool Whether the approval was a success (see ERC20's `approve`)
function compareAndApprove(address _spender, uint256 _currentValue, uint256 _newValue) public returns(bool) {
if (allowed[msg.sender][_spender] != _currentValue) {
return false;
}
return approve(_spender, _newValue);
}
}
contract CHEXToken is Token {
string public constant name = "CHEX Token";
string public constant symbol = "CHX";
uint public constant decimals = 18;
uint public startBlock; //crowdsale start block
uint public endBlock; //crowdsale end block
address public founder;
address public owner;
uint public totalSupply = 2000000000 * 10**decimals; // 2b tokens, each divided to up to 10^decimals units.
uint public totalTokens = 0;
uint public presaleSupply = 0;
uint public presaleEtherRaised = 0;
event Buy(address indexed recipient, uint eth, uint chx);
uint public presaleAllocation = totalSupply / 2; //50% of token supply allocated for crowdsale
uint public strategicAllocation = totalSupply / 4; //25% of token supply allocated post-crowdsale for strategic supply
uint public reserveAllocation = totalSupply / 4; //25% of token supply allocated post-crowdsale for internal
bool public strategicAllocated = false;
bool public reserveAllocated = false;
uint public transferLockup = 172800; //no transfers until 30 days after crowdsale begins (assumes 100 day crowdsale)
uint public reserveLockup = 241920; //first wave of reserve locked until 42 days after sale is over
uint public reserveWave = 0; //increments each time 10% of reserve is allocated, to a max of 10
uint public reserveWaveTokens = reserveAllocation / 10; //10% of reserve will be released on each wave
uint public reserveWaveLockup = 172800; //30 day intervals before subsequent wave of reserve tokens can be released
uint public constant MIN_ETHER = 1 finney;
enum TokenSaleState {
Initial, //contract initialized, bonus token
Presale, //limited time crowdsale
Live, //default price
Frozen //prevent sale of tokens
}
TokenSaleState public _saleState = TokenSaleState.Initial;
function CHEXToken(address founderInput, address ownerInput, uint startBlockInput, uint endBlockInput) {
founder = founderInput;
owner = ownerInput;
startBlock = startBlockInput;
endBlock = endBlockInput;
updateTokenSaleState();
}
function price() constant returns(uint) {
if (_saleState == TokenSaleState.Initial) return 12002;
if (_saleState == TokenSaleState.Presale) {
uint percentRemaining = pct((endBlock - block.number), (endBlock - startBlock), 3);
return 6000 + 6 * percentRemaining;
}
return 6000;
}
function() payable {
buy(msg.sender);
}
function buy(address recipient) payable {
if (recipient == 0x0) throw;
if (msg.value < MIN_ETHER) throw;
if (_saleState == TokenSaleState.Frozen) throw;
updateTokenSaleState();
uint tokens = mul(msg.value, price());
uint nextTotal = add(totalTokens, tokens);
uint nextPresaleTotal = add(presaleSupply, tokens);
if (nextTotal >= totalSupply) throw;
if (nextPresaleTotal >= presaleAllocation) throw;
balances[recipient] = add(balances[recipient], tokens);
presaleSupply = nextPresaleTotal;
totalTokens = nextTotal;
if (_saleState == TokenSaleState.Initial || _saleState == TokenSaleState.Presale) {
presaleEtherRaised = add(presaleEtherRaised, msg.value);
}
founder.transfer(msg.value);
Transfer(0, recipient, tokens);
Buy(recipient, msg.value, tokens);
}
function updateTokenSaleState () {
if (_saleState == TokenSaleState.Frozen) return;
if (_saleState == TokenSaleState.Live && block.number > endBlock) return;
if (_saleState == TokenSaleState.Initial && block.number >= startBlock) {
_saleState = TokenSaleState.Presale;
}
if (_saleState == TokenSaleState.Presale && block.number > endBlock) {
_saleState = TokenSaleState.Live;
}
}
function transfer(address _to, uint256 _value) returns (bool success) {
if (block.number <= startBlock + transferLockup && msg.sender != founder && msg.sender != owner) throw;
return super.transfer(_to, _value);
}
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
if (block.number <= startBlock + transferLockup && msg.sender != founder && msg.sender != owner) throw;
return super.transferFrom(_from, _to, _value);
}
modifier onlyInternal {
require(msg.sender == owner || msg.sender == founder);
_;
}
function allocateStrategicTokens() onlyInternal {
if (strategicAllocated) throw;
balances[owner] = add(balances[owner], strategicAllocation);
totalTokens = add(totalTokens, strategicAllocation);
strategicAllocated = true;
Transfer(0, owner, strategicAllocation);
}
function allocateReserveTokens() onlyInternal {
if (block.number <= endBlock + reserveLockup + (reserveWaveLockup * reserveWave)) throw;
if (reserveAllocated) throw;
balances[founder] = add(balances[founder], reserveWaveTokens);
totalTokens = add(totalTokens, reserveWaveTokens);
reserveWave++;
if (reserveWave >= 10) {
reserveAllocated = true;
}
Transfer(0, founder, reserveWaveTokens);
}
function freeze() onlyInternal {
_saleState = TokenSaleState.Frozen;
}
function unfreeze() onlyInternal {
_saleState = TokenSaleState.Presale;
updateTokenSaleState();
}
}
{
"compilationTarget": {
"CHEXToken.sol": "CHEXToken"
},
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"endBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"allocateStrategicTokens","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"reserveAllocated","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"allocateReserveTokens","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"updateTokenSaleState","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"presaleEtherRaised","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"startBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"founder","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"strategicAllocated","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"MIN_ETHER","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"freeze","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unfreeze","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_currentValue","type":"uint256"},{"name":"_newValue","type":"uint256"}],"name":"compareAndApprove","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalTokens","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"presaleAllocation","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"strategicAllocation","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"_saleState","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"price","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"reserveWave","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"presaleSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"transferLockup","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"reserveWaveLockup","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"reserveLockup","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"recipient","type":"address"}],"name":"buy","outputs":[],"payable":true,"type":"function"},{"constant":true,"inputs":[],"name":"reserveWaveTokens","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"reserveAllocation","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"founderInput","type":"address"},{"name":"ownerInput","type":"address"},{"name":"startBlockInput","type":"uint256"},{"name":"endBlockInput","type":"uint256"}],"payable":false,"type":"constructor"},{"payable":true,"type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"recipient","type":"address"},{"indexed":false,"name":"eth","type":"uint256"},{"indexed":false,"name":"chx","type":"uint256"}],"name":"Buy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]