pragma solidity ^0.4.18;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(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 sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) { //was constant
uint256 c = a + b;
assert(c >= a);
return c;
}
}
/************************************************************************************************
*
*************************************************************************************************/
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function Ownable() public {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function transferOwnership(address newOwner) onlyOwner public {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
contract ERC20 {
function transfer(address receiver, uint amount) public ;
function transferFrom(address sender, address receiver, uint amount) public returns(bool success); // do token.approve on the ICO contract
function balanceOf(address _owner) constant public returns (uint256 balance);
}
/************************************************************************************************
*
*************************************************************************************************/
contract ASTRICOSale is Ownable {
ERC20 public token; // using the ASTRCoin token - will set an address
// start and end of the sale - 4 weeks
uint256 public startTime;
uint256 public endTime;
// where funds are collected
address public wallet; // beneficiary
address public ownerAddress; // deploy owner
// amount of raised money in wei
uint256 public weiRaised;
uint8 internal decimals = 4; // 4 decimal places should be enough in general
uint256 internal decimalsConversion = 10 ** uint256(decimals);
uint256 internal ALLOC_CROWDSALE = 90000000 * decimalsConversion; // (10 ** uint256(decimals)); // 90 mill in ICO
// 90MIL 90000000
// 10MIL 10000000
// 90MIL 4DCP 900000000000
uint internal BASIC_RATE = 133 * decimalsConversion; // based on the price of ether at 330 USD
uint internal PRICE_STAGE_PS = 625 * decimalsConversion;
uint internal PRICE_STAGE_ONE = 445 * decimalsConversion;
uint internal PRICE_STAGE_TWO = 390 * decimalsConversion;
uint internal PRICE_STAGE_THREE = 347 * decimalsConversion;
uint internal PRICE_STAGE_FOUR = 312 * decimalsConversion;
uint public PRICE_VARIABLE = 0 * decimalsConversion;
//TIME LIMITS
// uint public constant STAGE_ONE_TIME_END = 1 weeks;
// uint public constant STAGE_TWO_TIME_END = 2 weeks;
// uint public constant STAGE_THREE_TIME_END = 3 weeks;
// uint public constant STAGE_FOUR_TIME_END = 4 weeks;
uint internal STAGE_ONE_TIME_END = 1 weeks;
uint internal STAGE_TWO_TIME_END = 2 weeks;
uint internal STAGE_THREE_TIME_END = 3 weeks;
uint internal STAGE_FOUR_TIME_END = 4 weeks;
uint256 public astrSold = 0;
bool public halted;
bool public crowdsaleClosed;
// simple event to track purchases
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
modifier isNotHalted() { require(!halted); _; }
modifier afterDeadline() { if (now >= endTime) _; }
/**
* Constructor for ASTRICOSale
* param _token ASTRCoin 0x80E7a4d750aDe616Da896C49049B7EdE9e04C191
*
* 1511798400
* Tuesday, November 28, 2017 12:00:00 AM GMT+08:00
*
* 90000000000
*/
// function ASTRCoinCrowdSale(address _token, uint256 _startTime, address _ethWallet) public {
function ASTRICOSale() public {
// require(_startTime >= now);
// require(_ethWallet != 0x0);
crowdsaleClosed = false;
halted = false;
startTime = 1511798400; // Tuesday, November 28, 2017 12:00:00 AM GMT+08:00
endTime = startTime + STAGE_FOUR_TIME_END; //_startTime + STAGE_FOUR_TIME_END; set start and end the same :/
wallet = ERC20(0x3baDA155408AB1C9898FDF28e545b51f2f9a65CC); // This wallet needs to give permission for the ICO to transfer Tokens
ownerAddress = ERC20(0x3EFAe2e152F62F5cc12cc0794b816d22d416a721); // This is bad in theory but does fix the 2300 gas problem
token = ERC20(0x80E7a4d750aDe616Da896C49049B7EdE9e04C191); // Ropsten we have pregenerated thiss
}
// fallback function can be used to buy tokens
function () public payable {
require(msg.sender != 0x0);
require(validPurchase());
require(!halted); // useful to test if we have paused it
uint256 weiAmount = msg.value; // money sent in wei
uint256 tokens = SafeMath.div(SafeMath.mul(weiAmount, getCurrentRate()), 1 ether);
require(ALLOC_CROWDSALE - astrSold >= tokens);
weiRaised += weiAmount;
astrSold += tokens;
token.transferFrom(ownerAddress, msg.sender, tokens);
wallet.transfer(msg.value); // transfer straight away PRESALE wallet
}
function validPurchase() internal constant returns (bool) {
bool withinPeriod = now >= startTime && now <= endTime;
bool nonZeroPurchase = (msg.value != 0);
bool astrAvailable = (ALLOC_CROWDSALE - astrSold) > 0;
return withinPeriod && nonZeroPurchase && astrAvailable && ! crowdsaleClosed;
}
function getCurrentRate() internal constant returns (uint256) {
uint delta = SafeMath.sub(now, startTime);
if( PRICE_VARIABLE > 0 ) {
return PRICE_VARIABLE; // we can manually set prices if we want
}
if (delta > STAGE_THREE_TIME_END) {
return PRICE_STAGE_FOUR;
}
if (delta > STAGE_TWO_TIME_END) {
return PRICE_STAGE_THREE;
}
if (delta > STAGE_ONE_TIME_END) {
return PRICE_STAGE_TWO;
}
return PRICE_STAGE_ONE;
}
// this closes it when we want to close - rather than waiting
function setNewRate(uint256 _coinsPerEther) onlyOwner public {
if( _coinsPerEther > 0 ) {
PRICE_VARIABLE = _coinsPerEther * decimalsConversion;
}
}
// this closes it when we want to close - rather than waiting
function setFixedRate() onlyOwner public {
PRICE_VARIABLE = 0 * decimalsConversion;
}
// this closes it when we want to close - rather than waiting - this is bad
function closeSaleAnyway() onlyOwner public {
// wallet.transfer(weiRaised);
crowdsaleClosed = true;
}
// this closes it when we want to close - rather than waiting
function safeCloseSale() onlyOwner afterDeadline public {
// wallet.transfer(weiRaised);
crowdsaleClosed = true;
}
function pause() onlyOwner public {
halted = true;
}
function unpause() onlyOwner public {
halted = false;
}
}
{
"compilationTarget": {
"ASTRICOSale.sol": "ASTRICOSale"
},
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 0
},
"remappings": []
}
[{"constant":false,"inputs":[{"name":"_coinsPerEther","type":"uint256"}],"name":"setNewRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"endTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"safeCloseSale","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"weiRaised","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"wallet","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"startTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ownerAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PRICE_VARIABLE","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"halted","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"astrSold","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"crowdsaleClosed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"closeSaleAnyway","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"setFixedRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"purchaser","type":"address"},{"indexed":true,"name":"beneficiary","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"TokenPurchase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]