Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pragma solidity ^0.4.18;
- import "zeppelin-solidity/contracts/token/MintableToken.sol";
- import "zeppelin-solidity/contracts/token/DetailedERC20.sol";
- import '../libraries/SafeMath8.sol';
- import '../libraries/SafeMath32.sol';
- contract MyToken is MintableToken, DetailedERC20 {
- using SafeMath8 for uint8;
- using SafeMath32 for uint32;
- // This allows us to save some info about the Funder actions
- struct Funder {
- bool created;
- uint256 totalFunded;
- uint256 timesFunded;
- mapping (uint256 => uint256) funds;
- }
- // A presale must now when it starts and when it ends,
- // the buy and sell rates,
- // a token cap, how much tokens have been bought,
- // and an amount of funders
- struct PreSale {
- uint256 startDate;
- uint256 endDate;
- uint32 buyRate; // 1000 wei = X atto tokens
- uint32 sellRate; // 1000 wei = X atto tokens
- uint256 limit;
- uint256 accumulated;
- uint256 numFunders;
- mapping (address => Funder) funders;
- }
- // pre-sales configuration
- uint8 maxNumPreSale;
- uint8 numPreSale = 0;
- mapping (uint8 => PreSale) preSales;
- // ICO dates and rates
- uint256 icoStartDate;
- uint256 icoEndDate;
- // 1000 wei = X atto tokens
- uint32 buyRate = 100000000;
- uint32 sellRate = 100000000;
- function MyToken(uint256 _totalSupply, uint8 _maxNumPreSale)
- Ownable () DetailedERC20("My Token", "MTX", 18) public
- {
- require(_totalSupply > 0 && _maxNumPreSale > 0);
- totalSupply = _totalSupply.mul(10 ** 18);
- balances[address(this)] = totalSupply.mul(8).div(10);
- balances[msg.sender] = totalSupply.mul(2).div(10);
- maxNumPreSale = _maxNumPreSale;
- }
- function availableTokens() public view returns (uint256) {
- return balanceOf(address(this));
- }
- // Returns true if everything is configured
- function isConfigured() public view returns (bool) {
- return numPreSale == maxNumPreSale && ((icoStartDate > 0 && icoEndDate > 0) && (icoStartDate < icoEndDate));
- }
- function setICOStartDate(uint256 date) onlyOwner public {
- require(numPreSale == maxNumPreSale);
- require(preSales[numPreSale].endDate < date);
- icoStartDate = date;
- }
- function setICOEndDate(uint256 date) onlyOwner public {
- require(numPreSale == maxNumPreSale);
- require(icoStartDate < date);
- require(date >= block.timestamp);
- icoEndDate = date;
- }
- function addPreSale(uint256 _startDate, uint256 endDate, uint32 _buyRate, uint32 _sellRate, uint256 _limit) onlyOwner public {
- require(maxNumPreSale > 0);
- require(numPreSale + 1 <= maxNumPreSale);
- require(_startDate < endDate);
- require(_buyRate > 0 && _sellRate > 0 && _buyRate <= _sellRate);
- require(_limit > 0);
- if (numPreSale > 1) {
- require(preSales[numPreSale].endDate <= _startDate);
- }
- numPreSale++;
- preSales[numPreSale] = PreSale(_startDate, endDate, _buyRate, _sellRate, _limit.mul(10 ** 18), 0, 0);
- }
- // Gets the current PreSale index, searching from the last PreSale with their end date
- // If a PreSale has completed it's limit it should return the next PreSale
- function getPreSaleIndex(uint256 time) internal view returns (uint8) {
- uint8 index = numPreSale;
- if (preSales[index].endDate < time) {
- return 0;
- }
- while (preSales[index].startDate > time && index > 0) {
- index--;
- }
- if (index > 0) {
- while(preSales[index].accumulated == preSales[index].limit && index <= numPreSale) {
- index++;
- }
- if (index > numPreSale) {
- index = 0;
- }
- }
- return index;
- }
- // Gets the current PreSale index and whether the ICO has started or not,
- // searching from the last PreSale with their end date
- // If a PreSale has completed it's limit it should return the next PreSale
- function getPreSaleState(uint256 time) internal view returns (uint8, bool) {
- uint8 index = numPreSale;
- if (preSales[index].endDate < time) {
- return (0, true);
- }
- while (preSales[index].startDate > time && index > 0) {
- index--;
- }
- bool doStartICO = false;
- if (index > 0) {
- while(preSales[index].accumulated == preSales[index].limit && index <= numPreSale) {
- index++;
- }
- if (index > numPreSale) {
- index = 0;
- doStartICO = true;
- }
- }
- return (index, doStartICO);
- }
- function convertPreSale(PreSale preSale) internal pure returns (
- uint256, uint256, uint32, uint32,
- uint256, uint256, uint256
- ) {
- return (
- preSale.startDate, preSale.endDate,
- preSale.buyRate, preSale.sellRate,
- preSale.limit, preSale.accumulated,
- preSale.numFunders
- );
- }
- function getPreSale(uint8 index) onlyOwner public view returns (
- uint256, uint256, uint32, uint32,
- uint256, uint256, uint256
- ) {
- return convertPreSale(preSales[index]);
- }
- function getCurrentPreSale() public view returns (
- uint256, uint256, uint32, uint32,
- uint256, uint256, uint256
- ) {
- uint8 index = getPreSaleIndex(block.timestamp);
- return convertPreSale(preSales[index]);
- }
- function updatePreSaleRates(uint8 index, uint32 _buyRate, uint32 _sellRate) onlyOwner public {
- require(index > 0 && index <= maxNumPreSale);
- require(_buyRate > 0 && _sellRate > 0 && _buyRate <= _sellRate);
- preSales[index].buyRate = _buyRate;
- preSales[index].sellRate = _sellRate;
- }
- function updateSaleRates(uint32 _buyRate, uint32 _sellRate) onlyOwner public {
- require(_buyRate > 0 && _sellRate > 0 && _buyRate <= _sellRate);
- buyRate = _buyRate;
- sellRate = _sellRate;
- }
- function getMaxNumPreSale() onlyOwner public view returns(uint8) {
- return maxNumPreSale;
- }
- function getNumPreSale() onlyOwner public view returns(uint8) {
- return numPreSale;
- }
- function getICODates() public view returns(uint256, uint256) {
- return (icoStartDate, icoEndDate);
- }
- function getRates() public view returns(uint32, uint32) {
- return (buyRate, sellRate);
- }
- function getFunderDataFromPreSale(address funder, uint8 index) public view returns (bool, uint256, uint256) {
- Funder storage f = preSales[index].funders[funder];
- return (f.created, f.totalFunded, f.timesFunded);
- }
- function transferFrom(address from, address to, uint256 value) public returns (bool) {
- require(icoEndDate <= block.timestamp);
- return super.transferFrom(from, to, value);
- }
- function transfer(address to, uint256 value) public returns (bool) {
- require(icoEndDate <= block.timestamp);
- return super.transfer(to, value);
- }
- function updatePreSaleFunds(uint8 index, PreSale storage preSale, address funderAddress, uint256 amount) internal {
- preSales[index].accumulated = preSale.accumulated.add(amount);
- Funder storage funder = preSale.funders[funderAddress];
- if (funder.created) {
- preSales[index].funders[funderAddress].totalFunded = funder.totalFunded.add(amount);
- preSales[index].funders[funderAddress].funds[funder.timesFunded] = amount;
- preSales[index].funders[funderAddress].timesFunded = funder.timesFunded.add(1);
- } else {
- preSales[index].funders[funderAddress] = Funder(true, amount, 1);
- preSales[index].funders[funderAddress].funds[0] = amount;
- preSales[index].numFunders = preSale.numFunders.add(1);
- }
- }
- function () payable public {
- buy();
- }
- function buy() payable public {
- require(msg.value > 0);
- require(maxNumPreSale > 0 && isConfigured());
- var (index, doStartICO) = getPreSaleState(block.timestamp);
- uint256 tokens = msg.value.mul(buyRate).div(1000);
- if (index > 0 && index <= maxNumPreSale) {
- // There's a preSale ongoing
- PreSale storage preSale = preSales[index];
- uint256 availableTokensPreSale = preSale.limit.sub(preSale.accumulated);
- tokens = msg.value.mul(preSale.buyRate).div(1000);
- if (tokens > availableTokensPreSale) {
- updatePreSaleFunds(index, preSale, msg.sender, availableTokensPreSale);
- uint256 remainingWei = msg.value.sub(availableTokensPreSale.mul(1000).div(preSale.buyRate));
- if (index == maxNumPreSale) { // Use ICO rates
- tokens = tokens.add(remainingWei.mul(buyRate).div(1000));
- } else { // Use next preSale
- PreSale storage nextPreSale = preSales[index.add(1)];
- uint256 remainingTokens = remainingWei.mul(nextPreSale.buyRate).div(1000);
- updatePreSaleFunds(index, nextPreSale, msg.sender, remainingTokens);
- tokens = tokens.add(remainingTokens);
- }
- } else {
- updatePreSaleFunds(index, preSale, msg.sender, tokens);
- }
- } else {
- // Pure ICO sale
- require((doStartICO || icoStartDate <= block.timestamp) && icoEndDate >= block.timestamp);
- require(availableTokens() >= tokens);
- }
- balances[msg.sender] = balanceOf(msg.sender).add(tokens);
- balances[address(this)] = availableTokens().sub(tokens);
- owner.transfer(msg.value);
- }
- // TODO
- function sell(uint256 tokens) payable public {
- require(tokens >= 0);
- require(icoEndDate <= block.timestamp);
- require(balanceOf(msg.sender) >= tokens);
- uint256 value = tokens.mul(1000).div(sellRate);
- require(value >= 0);
- balances[address(this)] = availableTokens().add(tokens);
- balances[msg.sender] = balanceOf(msg.sender).sub(tokens);
- msg.sender.transfer(value);
- }
- }
Add Comment
Please, Sign In to add comment