Guest User

Untitled

a guest
Jan 23rd, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.12 KB | None | 0 0
  1. pragma solidity ^0.4.18;
  2.  
  3. import "zeppelin-solidity/contracts/token/MintableToken.sol";
  4. import "zeppelin-solidity/contracts/token/DetailedERC20.sol";
  5.  
  6. import '../libraries/SafeMath8.sol';
  7. import '../libraries/SafeMath32.sol';
  8.  
  9. contract MyToken is MintableToken, DetailedERC20 {
  10.  
  11. using SafeMath8 for uint8;
  12. using SafeMath32 for uint32;
  13.  
  14. // This allows us to save some info about the Funder actions
  15. struct Funder {
  16. bool created;
  17. uint256 totalFunded;
  18. uint256 timesFunded;
  19. mapping (uint256 => uint256) funds;
  20. }
  21.  
  22. // A presale must now when it starts and when it ends,
  23. // the buy and sell rates,
  24. // a token cap, how much tokens have been bought,
  25. // and an amount of funders
  26. struct PreSale {
  27. uint256 startDate;
  28. uint256 endDate;
  29. uint32 buyRate; // 1000 wei = X atto tokens
  30. uint32 sellRate; // 1000 wei = X atto tokens
  31. uint256 limit;
  32. uint256 accumulated;
  33. uint256 numFunders;
  34. mapping (address => Funder) funders;
  35. }
  36.  
  37. // pre-sales configuration
  38. uint8 maxNumPreSale;
  39. uint8 numPreSale = 0;
  40. mapping (uint8 => PreSale) preSales;
  41.  
  42. // ICO dates and rates
  43. uint256 icoStartDate;
  44. uint256 icoEndDate;
  45. // 1000 wei = X atto tokens
  46. uint32 buyRate = 100000000;
  47. uint32 sellRate = 100000000;
  48.  
  49. function MyToken(uint256 _totalSupply, uint8 _maxNumPreSale)
  50. Ownable () DetailedERC20("My Token", "MTX", 18) public
  51. {
  52. require(_totalSupply > 0 && _maxNumPreSale > 0);
  53.  
  54. totalSupply = _totalSupply.mul(10 ** 18);
  55. balances[address(this)] = totalSupply.mul(8).div(10);
  56. balances[msg.sender] = totalSupply.mul(2).div(10);
  57. maxNumPreSale = _maxNumPreSale;
  58. }
  59.  
  60. function availableTokens() public view returns (uint256) {
  61. return balanceOf(address(this));
  62. }
  63.  
  64. // Returns true if everything is configured
  65. function isConfigured() public view returns (bool) {
  66. return numPreSale == maxNumPreSale && ((icoStartDate > 0 && icoEndDate > 0) && (icoStartDate < icoEndDate));
  67. }
  68.  
  69. function setICOStartDate(uint256 date) onlyOwner public {
  70. require(numPreSale == maxNumPreSale);
  71. require(preSales[numPreSale].endDate < date);
  72. icoStartDate = date;
  73. }
  74.  
  75. function setICOEndDate(uint256 date) onlyOwner public {
  76. require(numPreSale == maxNumPreSale);
  77. require(icoStartDate < date);
  78. require(date >= block.timestamp);
  79. icoEndDate = date;
  80. }
  81.  
  82. function addPreSale(uint256 _startDate, uint256 endDate, uint32 _buyRate, uint32 _sellRate, uint256 _limit) onlyOwner public {
  83. require(maxNumPreSale > 0);
  84. require(numPreSale + 1 <= maxNumPreSale);
  85. require(_startDate < endDate);
  86. require(_buyRate > 0 && _sellRate > 0 && _buyRate <= _sellRate);
  87. require(_limit > 0);
  88.  
  89. if (numPreSale > 1) {
  90. require(preSales[numPreSale].endDate <= _startDate);
  91. }
  92. numPreSale++;
  93. preSales[numPreSale] = PreSale(_startDate, endDate, _buyRate, _sellRate, _limit.mul(10 ** 18), 0, 0);
  94. }
  95.  
  96. // Gets the current PreSale index, searching from the last PreSale with their end date
  97. // If a PreSale has completed it's limit it should return the next PreSale
  98. function getPreSaleIndex(uint256 time) internal view returns (uint8) {
  99. uint8 index = numPreSale;
  100.  
  101. if (preSales[index].endDate < time) {
  102. return 0;
  103. }
  104.  
  105. while (preSales[index].startDate > time && index > 0) {
  106. index--;
  107. }
  108.  
  109. if (index > 0) {
  110. while(preSales[index].accumulated == preSales[index].limit && index <= numPreSale) {
  111. index++;
  112. }
  113. if (index > numPreSale) {
  114. index = 0;
  115. }
  116. }
  117.  
  118. return index;
  119. }
  120.  
  121. // Gets the current PreSale index and whether the ICO has started or not,
  122. // searching from the last PreSale with their end date
  123. // If a PreSale has completed it's limit it should return the next PreSale
  124. function getPreSaleState(uint256 time) internal view returns (uint8, bool) {
  125. uint8 index = numPreSale;
  126.  
  127. if (preSales[index].endDate < time) {
  128. return (0, true);
  129. }
  130.  
  131. while (preSales[index].startDate > time && index > 0) {
  132. index--;
  133. }
  134. bool doStartICO = false;
  135. if (index > 0) {
  136. while(preSales[index].accumulated == preSales[index].limit && index <= numPreSale) {
  137. index++;
  138. }
  139. if (index > numPreSale) {
  140. index = 0;
  141. doStartICO = true;
  142. }
  143. }
  144.  
  145. return (index, doStartICO);
  146. }
  147.  
  148. function convertPreSale(PreSale preSale) internal pure returns (
  149. uint256, uint256, uint32, uint32,
  150. uint256, uint256, uint256
  151. ) {
  152. return (
  153. preSale.startDate, preSale.endDate,
  154. preSale.buyRate, preSale.sellRate,
  155. preSale.limit, preSale.accumulated,
  156. preSale.numFunders
  157. );
  158. }
  159. function getPreSale(uint8 index) onlyOwner public view returns (
  160. uint256, uint256, uint32, uint32,
  161. uint256, uint256, uint256
  162. ) {
  163. return convertPreSale(preSales[index]);
  164. }
  165.  
  166. function getCurrentPreSale() public view returns (
  167. uint256, uint256, uint32, uint32,
  168. uint256, uint256, uint256
  169. ) {
  170. uint8 index = getPreSaleIndex(block.timestamp);
  171. return convertPreSale(preSales[index]);
  172. }
  173.  
  174. function updatePreSaleRates(uint8 index, uint32 _buyRate, uint32 _sellRate) onlyOwner public {
  175. require(index > 0 && index <= maxNumPreSale);
  176. require(_buyRate > 0 && _sellRate > 0 && _buyRate <= _sellRate);
  177. preSales[index].buyRate = _buyRate;
  178. preSales[index].sellRate = _sellRate;
  179. }
  180.  
  181. function updateSaleRates(uint32 _buyRate, uint32 _sellRate) onlyOwner public {
  182. require(_buyRate > 0 && _sellRate > 0 && _buyRate <= _sellRate);
  183. buyRate = _buyRate;
  184. sellRate = _sellRate;
  185. }
  186.  
  187. function getMaxNumPreSale() onlyOwner public view returns(uint8) {
  188. return maxNumPreSale;
  189. }
  190.  
  191. function getNumPreSale() onlyOwner public view returns(uint8) {
  192. return numPreSale;
  193. }
  194.  
  195. function getICODates() public view returns(uint256, uint256) {
  196. return (icoStartDate, icoEndDate);
  197. }
  198.  
  199. function getRates() public view returns(uint32, uint32) {
  200. return (buyRate, sellRate);
  201. }
  202.  
  203. function getFunderDataFromPreSale(address funder, uint8 index) public view returns (bool, uint256, uint256) {
  204. Funder storage f = preSales[index].funders[funder];
  205. return (f.created, f.totalFunded, f.timesFunded);
  206. }
  207.  
  208. function transferFrom(address from, address to, uint256 value) public returns (bool) {
  209. require(icoEndDate <= block.timestamp);
  210. return super.transferFrom(from, to, value);
  211. }
  212.  
  213. function transfer(address to, uint256 value) public returns (bool) {
  214. require(icoEndDate <= block.timestamp);
  215. return super.transfer(to, value);
  216. }
  217.  
  218. function updatePreSaleFunds(uint8 index, PreSale storage preSale, address funderAddress, uint256 amount) internal {
  219. preSales[index].accumulated = preSale.accumulated.add(amount);
  220. Funder storage funder = preSale.funders[funderAddress];
  221. if (funder.created) {
  222. preSales[index].funders[funderAddress].totalFunded = funder.totalFunded.add(amount);
  223. preSales[index].funders[funderAddress].funds[funder.timesFunded] = amount;
  224. preSales[index].funders[funderAddress].timesFunded = funder.timesFunded.add(1);
  225. } else {
  226. preSales[index].funders[funderAddress] = Funder(true, amount, 1);
  227. preSales[index].funders[funderAddress].funds[0] = amount;
  228. preSales[index].numFunders = preSale.numFunders.add(1);
  229. }
  230. }
  231.  
  232. function () payable public {
  233. buy();
  234. }
  235.  
  236. function buy() payable public {
  237. require(msg.value > 0);
  238. require(maxNumPreSale > 0 && isConfigured());
  239. var (index, doStartICO) = getPreSaleState(block.timestamp);
  240.  
  241. uint256 tokens = msg.value.mul(buyRate).div(1000);
  242. if (index > 0 && index <= maxNumPreSale) {
  243. // There's a preSale ongoing
  244. PreSale storage preSale = preSales[index];
  245. uint256 availableTokensPreSale = preSale.limit.sub(preSale.accumulated);
  246. tokens = msg.value.mul(preSale.buyRate).div(1000);
  247. if (tokens > availableTokensPreSale) {
  248. updatePreSaleFunds(index, preSale, msg.sender, availableTokensPreSale);
  249. uint256 remainingWei = msg.value.sub(availableTokensPreSale.mul(1000).div(preSale.buyRate));
  250. if (index == maxNumPreSale) { // Use ICO rates
  251. tokens = tokens.add(remainingWei.mul(buyRate).div(1000));
  252. } else { // Use next preSale
  253. PreSale storage nextPreSale = preSales[index.add(1)];
  254. uint256 remainingTokens = remainingWei.mul(nextPreSale.buyRate).div(1000);
  255. updatePreSaleFunds(index, nextPreSale, msg.sender, remainingTokens);
  256. tokens = tokens.add(remainingTokens);
  257. }
  258. } else {
  259. updatePreSaleFunds(index, preSale, msg.sender, tokens);
  260. }
  261. } else {
  262. // Pure ICO sale
  263. require((doStartICO || icoStartDate <= block.timestamp) && icoEndDate >= block.timestamp);
  264. require(availableTokens() >= tokens);
  265. }
  266.  
  267. balances[msg.sender] = balanceOf(msg.sender).add(tokens);
  268. balances[address(this)] = availableTokens().sub(tokens);
  269.  
  270. owner.transfer(msg.value);
  271. }
  272.  
  273. // TODO
  274. function sell(uint256 tokens) payable public {
  275. require(tokens >= 0);
  276. require(icoEndDate <= block.timestamp);
  277. require(balanceOf(msg.sender) >= tokens);
  278.  
  279. uint256 value = tokens.mul(1000).div(sellRate);
  280. require(value >= 0);
  281.  
  282. balances[address(this)] = availableTokens().add(tokens);
  283. balances[msg.sender] = balanceOf(msg.sender).sub(tokens);
  284.  
  285. msg.sender.transfer(value);
  286. }
  287.  
  288. }
Add Comment
Please, Sign In to add comment