Created
September 2, 2018 09:55
-
-
Save yuriy77k/771837a9b54d81157a27496d50fff1bb to your computer and use it in GitHub Desktop.
electrominer.io pre ico
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.23; | |
/** | |
* @title SafeMath | |
* @dev Math operations with safety checks that throw on error | |
*/ | |
library SafeMath { | |
/** | |
* @dev Multiplies two numbers, throws on overflow. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { | |
if (a == 0) { | |
return 0; | |
} | |
c = a * b; | |
assert(c / a == b); | |
return c; | |
} | |
/** | |
* @dev Integer division of two numbers, truncating the quotient. | |
*/ | |
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 a / b; | |
} | |
/** | |
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
assert(b <= a); | |
return a - b; | |
} | |
/** | |
* @dev Adds two numbers, throws on overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (uint256 c) { | |
c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
} | |
contract Ownable { | |
address public owner; | |
event OwnershipRenounced(address indexed previousOwner); | |
event OwnershipTransferred( | |
address indexed previousOwner, | |
address indexed newOwner | |
); | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
constructor() public { | |
owner = msg.sender; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(msg.sender == owner); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
*/ | |
function transferOwnership(address newOwner) public onlyOwner { | |
require(newOwner != address(0)); | |
emit OwnershipTransferred(owner, newOwner); | |
owner = newOwner; | |
} | |
/** | |
* @dev Allows the current owner to relinquish control of the contract. | |
*/ | |
function renounceOwnership() public onlyOwner { | |
emit OwnershipRenounced(owner); | |
owner = address(0); | |
} | |
} | |
contract Token { | |
function transfer(address _to, uint256 _value) public returns (bool); | |
function balanceOf(address who) public view returns (uint256); | |
} | |
/** | |
* @title Crowdsale | |
* @dev Crowdsale is a base contract for managing a token crowdsale, | |
* allowing investors to purchase tokens with ether. This contract implements | |
* such functionality in its most fundamental form and can be extended to provide additional | |
* functionality and/or custom behavior. | |
* The external interface represents the basic interface for purchasing tokens, and conform | |
* the base architecture for crowdsales. They are *not* intended to be modified / overridden. | |
* The internal interface conforms the extensible and modifiable surface of crowdsales. Override | |
* the methods to add functionality. Consider using 'super' where appropriate to concatenate | |
* behavior. | |
*/ | |
contract Crowdsale is Ownable { | |
using SafeMath for uint256; | |
// The token being sold | |
Token public token; | |
// Address where funds are collected | |
address public wallet; | |
// How many usd per 10000 tokens. | |
uint256 public rate = 7142; | |
// usd cents per 1 ETH | |
uint256 public ethRate = 27500; | |
// Amount of wei raised | |
uint256 public weiRaised; | |
// Seconds in a week | |
uint256 public week = 604800; | |
// ICO start time | |
uint256 public icoStartTime; | |
// bonuses in % | |
uint256 public privateIcoBonus = 50; | |
uint256 public preIcoBonus = 30; | |
uint256 public ico1Bonus = 15; | |
uint256 public ico2Bonus = 10; | |
uint256 public ico3Bonus = 5; | |
uint256 public ico4Bonus = 0; | |
// min contribution in wei | |
uint256 public privateIcoMin = 1 ether; | |
uint256 public preIcoMin = 1 ether; | |
uint256 public ico1Min = 1 ether; | |
uint256 public ico2Min = 1 ether; | |
uint256 public ico3Min = 1 ether; | |
uint256 public ico4Min = 1 ether; | |
// max contribution in wei | |
uint256 public privateIcoMax = 350 ether; | |
uint256 public preIcoMax = 10000 ether; | |
uint256 public ico1Max = 10000 ether; | |
uint256 public ico2Max = 10000 ether; | |
uint256 public ico3Max = 10000 ether; | |
uint256 public ico4Max = 10000 ether; | |
// hardcaps in tokens | |
uint256 public privateIcoCap = uint256(322532).mul(1e8); | |
uint256 public preIcoCap = uint256(8094791).mul(1e8); | |
uint256 public ico1Cap = uint256(28643106).mul(1e8); | |
uint256 public ico2Cap = uint256(17123596).mul(1e8); | |
uint256 public ico3Cap = uint256(9807150).mul(1e8); | |
uint256 public ico4Cap = uint256(6008825).mul(1e8); | |
// tokens sold | |
uint256 public privateIcoSold; | |
uint256 public preIcoSold; | |
uint256 public ico1Sold; | |
uint256 public ico2Sold; | |
uint256 public ico3Sold; | |
uint256 public ico4Sold; | |
//whitelist | |
mapping(address => bool) public whitelist; | |
//whitelisters addresses | |
mapping(address => bool) public whitelisters; | |
modifier isWhitelister() { | |
require(whitelisters[msg.sender]); | |
_; | |
} | |
modifier isWhitelisted() { | |
require(whitelist[msg.sender]); | |
_; | |
} | |
// Sale stages | |
enum Stages {Pause, PrivateIco, PrivateIcoEnd, PreIco, PreIcoEnd, Ico1, Ico2, Ico3, Ico4, IcoEnd} | |
Stages currentStage; | |
/** | |
* Event for token purchase logging | |
* @param purchaser who paid for the tokens | |
* @param beneficiary who got the tokens | |
* @param value weis paid for purchase | |
* @param amount amount of tokens purchased | |
*/ | |
event TokenPurchase( | |
address indexed purchaser, | |
address indexed beneficiary, | |
uint256 value, | |
uint256 amount | |
); | |
/** Event emitted when _account is Whitelisted / UnWhitelisted */ | |
event WhitelistUpdated(address indexed _account, uint8 _phase); | |
/** | |
* @param _wallet Address where collected funds will be forwarded to | |
* @param _token Address of the token being sold | |
*/ | |
constructor(address _newOwner, address _wallet, Token _token) public { | |
require(_newOwner != address(0)); | |
require(_wallet != address(0)); | |
require(_token != address(0)); | |
owner = _newOwner; | |
wallet = _wallet; | |
token = _token; | |
currentStage = Stages.Pause; | |
} | |
// ----------------------------------------- | |
// Crowdsale external interface | |
// ----------------------------------------- | |
/** | |
* @dev fallback function ***DO NOT OVERRIDE*** | |
*/ | |
function () external payable { | |
buyTokens(msg.sender); | |
} | |
/** | |
* @dev sale stage start | |
*/ | |
function startPrivateIco() public onlyOwner returns (bool) { | |
require(currentStage == Stages.Pause); | |
currentStage = Stages.PrivateIco; | |
return true; | |
} | |
/** | |
* @dev sale stage end | |
*/ | |
function endPrivateIco() public onlyOwner returns (bool) { | |
require(currentStage == Stages.PrivateIco); | |
currentStage = Stages.PrivateIcoEnd; | |
return true; | |
} | |
/** | |
* @dev sale stage start | |
*/ | |
function startPreIco() public onlyOwner returns (bool) { | |
require(currentStage == Stages.PrivateIcoEnd); | |
currentStage = Stages.PreIco; | |
return true; | |
} | |
/** | |
* @dev sale stage end | |
*/ | |
function endPreIco() public onlyOwner returns (bool) { | |
require(currentStage == Stages.PreIco); | |
currentStage = Stages.PreIcoEnd; | |
return true; | |
} | |
/** | |
* @dev sale stage start | |
*/ | |
function startIco() public onlyOwner returns (bool) { | |
require(currentStage == Stages.PreIcoEnd); | |
currentStage = Stages.Ico1; | |
icoStartTime = now; | |
return true; | |
} | |
/** | |
* @dev getting stage index (private ICO = 1, pre ICO = 2, ICO = 3, pause = 0, end = 9) | |
*/ | |
function getStageName () public view returns (string) { | |
if (currentStage == Stages.Pause) return 'Pause'; | |
if (currentStage == Stages.PrivateIco) return 'Private ICO'; | |
if (currentStage == Stages.PrivateIcoEnd) return 'Private ICO end'; | |
if (currentStage == Stages.PreIco) return 'Prte ICO'; | |
if (currentStage == Stages.PreIcoEnd) return 'Pre ICO end'; | |
if (currentStage == Stages.Ico1) return 'ICO 1-st week'; | |
if (currentStage == Stages.Ico2) return 'ICO 2-d week'; | |
if (currentStage == Stages.Ico3) return 'ICO 3-d week'; | |
if (currentStage == Stages.Ico4) return 'ICO 4-th week'; | |
return 'ICO is over'; | |
} | |
/** | |
* @dev low level token purchase ***DO NOT OVERRIDE*** | |
* @param _beneficiary Address performing the token purchase | |
*/ | |
function buyTokens(address _beneficiary) public payable isWhitelisted { | |
uint256 weiAmount = msg.value; | |
uint256 time; | |
uint256 weeksPassed; | |
require(currentStage != Stages.Pause); | |
require(currentStage != Stages.PrivateIcoEnd); | |
require(currentStage != Stages.PreIcoEnd); | |
require(currentStage != Stages.IcoEnd); | |
if (currentStage == Stages.Ico1 || currentStage == Stages.Ico2 || currentStage == Stages.Ico3 || currentStage == Stages.Ico4) { | |
time = now.sub(icoStartTime); | |
weeksPassed = time.div(week); | |
if (currentStage == Stages.Ico1) { | |
if (weeksPassed == 1) currentStage = Stages.Ico2; | |
else if (weeksPassed == 2) currentStage = Stages.Ico3; | |
else if (weeksPassed == 3) currentStage = Stages.Ico4; | |
else if (weeksPassed > 3) currentStage = Stages.IcoEnd; | |
} else if (currentStage == Stages.Ico2) { | |
if (weeksPassed == 2) currentStage = Stages.Ico3; | |
else if (weeksPassed == 3) currentStage = Stages.Ico4; | |
else if (weeksPassed > 3) currentStage = Stages.IcoEnd; | |
} else if (currentStage == Stages.Ico3) { | |
if (weeksPassed == 3) currentStage = Stages.Ico4; | |
else if (weeksPassed > 3) currentStage = Stages.IcoEnd; | |
} else if (currentStage == Stages.Ico4) { | |
if (weeksPassed > 3) currentStage = Stages.IcoEnd; | |
} | |
} | |
if (currentStage != Stages.IcoEnd) { | |
_preValidatePurchase(_beneficiary, weiAmount); | |
// calculate token amount to be created | |
uint256 tokens = _getTokenAmount(weiAmount); | |
// update state | |
weiRaised = weiRaised.add(weiAmount); | |
if (currentStage == Stages.PrivateIco) privateIcoSold = privateIcoSold.add(tokens); | |
if (currentStage == Stages.PreIco) preIcoSold = preIcoSold.add(tokens); | |
if (currentStage == Stages.Ico1) ico1Sold = ico1Sold.add(tokens); | |
if (currentStage == Stages.Ico2) ico2Sold = ico2Sold.add(tokens); | |
if (currentStage == Stages.Ico3) ico3Sold = ico3Sold.add(tokens); | |
if (currentStage == Stages.Ico4) ico4Sold = ico4Sold.add(tokens); | |
_processPurchase(_beneficiary, tokens); | |
emit TokenPurchase( | |
msg.sender, | |
_beneficiary, | |
weiAmount, | |
tokens | |
); | |
_forwardFunds(); | |
} else { | |
msg.sender.transfer(msg.value); | |
} | |
} | |
// ----------------------------------------- | |
// Internal interface (extensible) | |
// ----------------------------------------- | |
/** | |
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use `super` in contracts that inherit from Crowdsale to extend their validations. | |
* Example from CappedCrowdsale.sol's _preValidatePurchase method: | |
* super._preValidatePurchase(_beneficiary, _weiAmount); | |
* require(weiRaised.add(_weiAmount) <= cap); | |
* @param _beneficiary Address performing the token purchase | |
* @param _weiAmount Value in wei involved in the purchase | |
*/ | |
function _preValidatePurchase( | |
address _beneficiary, | |
uint256 _weiAmount | |
) | |
internal view | |
{ | |
require(_beneficiary != address(0)); | |
require(_weiAmount != 0); | |
if (currentStage == Stages.PrivateIco) { | |
require(_weiAmount >= privateIcoMin); | |
require(_weiAmount <= privateIcoMax); | |
} else if (currentStage == Stages.PreIco) { | |
require(_weiAmount >= preIcoMin); | |
require(_weiAmount <= preIcoMax); | |
} else if (currentStage == Stages.Ico1) { | |
require(_weiAmount >= ico1Min); | |
require(_weiAmount <= ico1Max); | |
} else if (currentStage == Stages.Ico2) { | |
require(_weiAmount >= ico2Min); | |
require(_weiAmount <= ico2Max); | |
} else if (currentStage == Stages.Ico3) { | |
require(_weiAmount >= ico3Min); | |
require(_weiAmount <= ico3Max); | |
} else if (currentStage == Stages.Ico4) { | |
require(_weiAmount >= ico4Min); | |
require(_weiAmount <= ico4Max); | |
} | |
} | |
/** | |
* @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens. | |
* @param _beneficiary Address performing the token purchase | |
* @param _tokenAmount Number of tokens to be emitted | |
*/ | |
function _deliverTokens( | |
address _beneficiary, | |
uint256 _tokenAmount | |
) | |
internal | |
{ | |
require(token.transfer(_beneficiary, _tokenAmount)); | |
} | |
/** | |
* @dev Executed when a purchase has been validated and is ready to be executed. Not necessarily emits/sends tokens. | |
* @param _beneficiary Address receiving the tokens | |
* @param _tokenAmount Number of tokens to be purchased | |
*/ | |
function _processPurchase( | |
address _beneficiary, | |
uint256 _tokenAmount | |
) | |
internal | |
{ | |
_deliverTokens(_beneficiary, _tokenAmount); | |
} | |
/** | |
* @dev Override to extend the way in which ether is converted to tokens. | |
* @param _weiAmount Value in wei to be converted into tokens | |
* @return Number of tokens that can be purchased with the specified _weiAmount | |
*/ | |
function _getTokenAmount(uint256 _weiAmount) | |
internal view returns (uint256) | |
{ | |
uint256 bonus; | |
uint256 cap; | |
if (currentStage == Stages.PrivateIco) { | |
bonus = privateIcoBonus; | |
cap = privateIcoCap.sub(privateIcoSold); | |
} else if (currentStage == Stages.PreIco) { | |
bonus = preIcoBonus; | |
cap = preIcoCap.sub(preIcoSold); | |
} else if (currentStage == Stages.Ico1) { | |
bonus = ico1Bonus; | |
cap = ico1Cap.sub(ico1Sold); | |
} else if (currentStage == Stages.Ico2) { | |
bonus = ico2Bonus; | |
cap = ico2Cap.sub(ico2Sold); | |
} else if (currentStage == Stages.Ico3) { | |
bonus = ico3Bonus; | |
cap = ico3Cap.sub(ico3Sold); | |
} else if (currentStage == Stages.Ico4) { | |
bonus = ico4Bonus; | |
cap = ico4Cap.sub(ico4Sold); | |
} | |
uint256 tokenAmount = _weiAmount.mul(ethRate).div(rate).div(1e8); | |
uint256 bonusTokens = tokenAmount.mul(bonus).div(100); | |
tokenAmount = tokenAmount.add(bonusTokens); | |
require(tokenAmount <= cap); | |
return tokenAmount; | |
} | |
/** | |
* @dev Determines how ETH is stored/forwarded on purchases. | |
*/ | |
function _forwardFunds() internal { | |
wallet.transfer(msg.value); | |
} | |
function withdrawTokens() public onlyOwner returns (bool) { | |
uint256 time; | |
uint256 weeksPassed; | |
if (currentStage == Stages.Ico1 || currentStage == Stages.Ico2 || currentStage == Stages.Ico3 || currentStage == Stages.Ico4) { | |
time = now.sub(icoStartTime); | |
weeksPassed = time.div(week); | |
if (weeksPassed > 3) currentStage = Stages.IcoEnd; | |
} | |
require(currentStage == Stages.IcoEnd); | |
uint256 balance = token.balanceOf(address(this)); | |
if (balance > 0) { | |
require(token.transfer(owner, balance)); | |
} | |
} | |
/** | |
* @dev Direct tokens sending | |
* @param _to address | |
* @param _amount tokens amount | |
*/ | |
function SendTokens(address _to, uint256 _amount) public onlyOwner returns (bool) { | |
uint256 time; | |
uint256 weeksPassed; | |
require(_to != address(0)); | |
require(currentStage != Stages.Pause); | |
require(currentStage != Stages.PrivateIcoEnd); | |
require(currentStage != Stages.PreIcoEnd); | |
require(currentStage != Stages.IcoEnd); | |
if (currentStage == Stages.Ico1 || currentStage == Stages.Ico2 || currentStage == Stages.Ico3 || currentStage == Stages.Ico4) { | |
time = now.sub(icoStartTime); | |
weeksPassed = time.div(week); | |
if (currentStage == Stages.Ico1) { | |
if (weeksPassed == 1) currentStage = Stages.Ico2; | |
else if (weeksPassed == 2) currentStage = Stages.Ico3; | |
else if (weeksPassed == 3) currentStage = Stages.Ico4; | |
else if (weeksPassed > 3) currentStage = Stages.IcoEnd; | |
} else if (currentStage == Stages.Ico2) { | |
if (weeksPassed == 2) currentStage = Stages.Ico3; | |
else if (weeksPassed == 3) currentStage = Stages.Ico4; | |
else if (weeksPassed > 3) currentStage = Stages.IcoEnd; | |
} else if (currentStage == Stages.Ico3) { | |
if (weeksPassed == 3) currentStage = Stages.Ico4; | |
else if (weeksPassed > 3) currentStage = Stages.IcoEnd; | |
} else if (currentStage == Stages.Ico4) { | |
if (weeksPassed > 3) currentStage = Stages.IcoEnd; | |
} | |
} | |
if (currentStage != Stages.IcoEnd) { | |
uint256 cap; | |
if (currentStage == Stages.PrivateIco) { | |
cap = privateIcoCap.sub(privateIcoSold); | |
} else if (currentStage == Stages.PreIco) { | |
cap = preIcoCap.sub(preIcoSold); | |
} else if (currentStage == Stages.Ico1) { | |
cap = ico1Cap.sub(ico1Sold); | |
} else if (currentStage == Stages.Ico2) { | |
cap = ico2Cap.sub(ico2Sold); | |
} else if (currentStage == Stages.Ico3) { | |
cap = ico3Cap.sub(ico3Sold); | |
} else if (currentStage == Stages.Ico4) { | |
cap = ico4Cap.sub(ico4Sold); | |
} | |
require(_amount <= cap); | |
if (currentStage == Stages.PrivateIco) privateIcoSold = privateIcoSold.add(_amount); | |
if (currentStage == Stages.PreIco) preIcoSold = preIcoSold.add(_amount); | |
if (currentStage == Stages.Ico1) ico1Sold = ico1Sold.add(_amount); | |
if (currentStage == Stages.Ico2) ico2Sold = ico2Sold.add(_amount); | |
if (currentStage == Stages.Ico3) ico3Sold = ico3Sold.add(_amount); | |
if (currentStage == Stages.Ico4) ico4Sold = ico4Sold.add(_amount); | |
} else { | |
return false; | |
} | |
require(token.transfer(_to, _amount)); | |
} | |
/// @dev Adds account addresses to whitelist. | |
/// @param _account address. | |
/// @param _phase 1 to add, 0 to remove. | |
function updateWhitelist (address _account, uint8 _phase) external isWhitelister returns (bool) { | |
require(_account != address(0)); | |
require(_phase <= 1); | |
if (_phase == 1) whitelist[_account] = true; | |
else whitelist[_account] = false; | |
emit WhitelistUpdated(_account, _phase); | |
return true; | |
} | |
/// @dev Adds new whitelister | |
/// @param _address new whitelister address. | |
function addWhitelister (address _address) public onlyOwner returns (bool) { | |
whitelisters[_address] = true; | |
return true; | |
} | |
/// @dev Removes whitelister | |
/// @param _address address to remove. | |
function removeWhitelister (address _address) public onlyOwner returns (bool) { | |
whitelisters[_address] = false; | |
return true; | |
} | |
function setUsdRate (uint256 _usdCents) public onlyOwner returns (bool) { | |
ethRate = _usdCents; | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment