Smart-contract для PreICO проекта PayAll


11/20/2017 @ 21:00 (UTC) (время оказалось ошибочным читать здесь /preico/@preico/start-preico-proekta-payall-2-pervye-oshibki)
Стартует preICO проекта PayAll

Мы разработали для них смарт-контракты.
Для сбора средств
https://etherscan.io/address/0x6a802a8bc6b0fa3ce5f5f46eebcfb4d4935c83f7
Для создания токенов
https://etherscan.io/address/0xc92f0e1ab6ce026c6b3b76c6589285f67f9b9e85
А так же написали две видеоинструкции к ним.
Для самостоятельного добавления в блокчейн


Или другого варианта, когда в блокчейн смарт-контракты добавили мы и передали управление с файлами ABI.

Код смарт-контракта можно найти на EtherScan
https://etherscan.io/address/0x6a802a8bc6b0fa3ce5f5f46eebcfb4d4935c83f7#code

Исходный код смарт-контракта

/* Token - simple token for PreICO and ICO
   Copyright (C) 2017  Sergey Sherkunov <leinlawun@leinlawun.org>

   This file is part of Token.

   Token is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */

pragma solidity ^0.4.18;

library SafeMath {
  function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
    c = a + b;

    assert (c >= a);
  }

  function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {
    assert(b <);

    c  - b;
  }

  function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
    c  * b;

    assert (c / a  b);
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256 c) {
    c  / b;
  }
}

contract ERC20MintableToken {
  using SafeMath for uint256;

  address public owner;

  Minter public minter;

  string constant public name 

  string constant public symbol 

  uint8 constant public decimals 

  uint256 public totalSupply;

  mapping (address => uint256) public balanceOf;

  mapping (address => mapping (address => uint256)) public allowance;

  event Transfer(address indexed _oldTokensHolder,
                 address indexed _newTokensHolder, uint256 _tokensNumber);

  //https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
  event Transfer(address indexed _tokensSpender,
                 address indexed _oldTokensHolder,
                 address indexed _newTokensHolder, uint256 _tokensNumber);

  event Approval(address indexed _tokensHolder, address indexed _tokensSpender,
                 uint256 _newTokensNumber);

  //https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
  event Approval(address indexed _tokensHolder, address indexed _tokensSpender,
                 uint256 _oldTokensNumber, uint256 _newTokensNumber);

  modifier onlyOwner {
    require (owner == msg.sender);

    _;
  }

  modifier onlyMinter {
    require (minter == msg.sender);

    _;
  }

  //https://vessenes.com/the-erc20-short-address-attack-explained
  //https://blog.golemproject.net/how-to-find-10m-by-just-reading-blockchain-6ae9d39fcd95
  //https://ericrafaloff.com/analyzing-the-erc20-short-address-attack
  modifier checkPayloadSize(uint256 size) {
     require (msg.data.length == size + 4);

     _;
  }

  function setOwner(address _owner) public onlyOwner {
    uint256 _allowance = allowance[this][owner];

    _approve(this, owner, 0);

    owner = _owner;

    _approve(this, owner, _allowance);
  }

  function setMinter(Minter _minter) public onlyOwner {
    uint256 _allowance = allowance[this][minter];

    _approve(this, minter, 0);

    minter = _minter;

    _approve(this, minter, _allowance);
  }

  function ERC20MintableToken(Minter _minter) public {
    owner = tx.origin;
    minter = _minter;
  }

  function _transfer(address _oldTokensHolder, address _newTokensHolder,
                     uint256 _tokensNumber) private {
    balanceOf[_oldTokensHolder] =
      balanceOf[_oldTokensHolder].sub(_tokensNumber);

    balanceOf[_newTokensHolder] =
      balanceOf[_newTokensHolder].add(_tokensNumber);

    Transfer(_oldTokensHolder, _newTokensHolder, _tokensNumber);
  }

  //https://vessenes.com/the-erc20-short-address-attack-explained
  //https://blog.golemproject.net/how-to-find-10m-by-just-reading-blockchain-6ae9d39fcd95
  //https://ericrafaloff.com/analyzing-the-erc20-short-address-attack
  function transfer(address _newTokensHolder, uint256 _tokensNumber) public
                   checkPayloadSize(2 * 32) returns (bool) {
    _transfer(msg.sender, _newTokensHolder, _tokensNumber);

    return true;
  }

  //https://vessenes.com/the-erc20-short-address-attack-explained
  //https://blog.golemproject.net/how-to-find-10m-by-just-reading-blockchain-6ae9d39fcd95
  //https://ericrafaloff.com/analyzing-the-erc20-short-address-attack
  //https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
  function transferFrom(address _oldTokensHolder, address _newTokensHolder,
                        uint256 _tokensNumber) public checkPayloadSize(3 * 32)
                       returns (bool) {
    allowance[_oldTokensHolder][msg.sender] =
      allowance[_oldTokensHolder][msg.sender].sub(_tokensNumber);

    _transfer(_oldTokensHolder, _newTokensHolder, _tokensNumber);

    Transfer(msg.sender, _oldTokensHolder, _newTokensHolder, _tokensNumber);

    return true;
  }

  function _approve(address _tokensHolder, address _tokensSpender,
                    uint256 _newTokensNumber) private {
    allowance[_tokensHolder][_tokensSpender] = _newTokensNumber;

    Approval(msg.sender, _tokensSpender, _newTokensNumber);
  }

  //https://vessenes.com/the-erc20-short-address-attack-explained
  //https://blog.golemproject.net/how-to-find-10m-by-just-reading-blockchain-6ae9d39fcd95
  //https://ericrafaloff.com/analyzing-the-erc20-short-address-attack
  //https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
  function approve(address _tokensSpender, uint256 _newTokensNumber) public
                  checkPayloadSize(2 * 32) returns (bool) {
    require (allowance[msg.sender][_tokensSpender] == 0 ||
             _newTokensNumber == 0);

    _approve(msg.sender, _tokensSpender, _newTokensNumber);

    return true;
  }

  //https://vessenes.com/the-erc20-short-address-attack-explained
  //https://blog.golemproject.net/how-to-find-10m-by-just-reading-blockchain-6ae9d39fcd95
  //https://ericrafaloff.com/analyzing-the-erc20-short-address-attack
  //https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
  function approve(address _tokensSpender, uint256 _oldTokensNumber,
                   uint256 _newTokensNumber) public checkPayloadSize(3 * 32)
                  returns (bool) {
    require (allowance[msg.sender][_tokensSpender] == _oldTokensNumber);

    _approve(msg.sender, _tokensSpender, _newTokensNumber);

    Approval(msg.sender, _tokensSpender, _oldTokensNumber, _newTokensNumber);

    return true;
  }

  function () public {
    revert();
  }

  function mint(uint256 _tokensNumber) public onlyMinter {
    totalSupply = totalSupply.add(_tokensNumber);

    balanceOf[this] = balanceOf[this].add(_tokensNumber);

    uint256 _allowance = allowance[this][msg.sender].add(_tokensNumber);

    _approve(this, minter, _allowance);

    _approve(this, owner, _allowance);
  }

  function burnUndistributed() public onlyMinter {
    _approve(this, minter, 0);

    _approve(this, owner, 0);

    totalSupply = totalSupply.sub(balanceOf[this]);

    balanceOf[this] = 0;
  }
}

contract Minter {
  using SafeMath for uint256;

  enum MinterState {
    PreICOWait,
    PreICOStarted,
    ICOWait,
    ICOStarted,
    Over
  }

  struct Tokensale {
    uint256 startTime;
    uint256 endTime;
    uint256 tokensMinimumNumberForBuy;
    uint256 tokensCost;
    uint256 tokensNumberForMint;
    bool tokensMinted;
    uint256 tokensStepOneBountyTime;
    uint256 tokensStepTwoBountyTime;
    uint256 tokensStepThreeBountyTime;
    uint256 tokensStepFourBountyTime;
    uint8 tokensStepOneBounty;
    uint8 tokensStepTwoBounty;
    uint8 tokensStepThreeBounty;
    uint8 tokensStepFourBounty;
  }

  address public owner;

  ERC20MintableToken public token;

  Tokensale public PreICO =
    Tokensale(1511211600, 1513803600, 150, 340000000000000 wei, 10000000, false,
              1 weeks, 2 weeks, 3 weeks, 4 weeks + 2 days, 25, 15, 10, 5);

  Tokensale public ICO =
    Tokensale(1526850000, 1529528400, 150, 340000000000000 wei, 290000000,
              false, 1 weeks, 2 weeks, 3 weeks, 4 weeks + 3 days, 20, 10, 5, 0);

  bool public paused = false;

  modifier onlyOwner {
    require (owner == msg.sender);

    _;
  }

  modifier onlyDuringTokensale {
    MinterState _minterState_ = _minterState();

    require (_minterState_ == MinterState.PreICOStarted ||
             _minterState_ == MinterState.ICOStarted);

    _;
  }

  modifier onlyAfterTokensaleOver {
    MinterState _minterState_ = _minterState();

    require (_minterState_ == MinterState.Over);

    _;
  }

  modifier onlyNotPaused {
    require (!paused);

    _;
  }

  modifier checkLimitsToBuyTokens {
    MinterState _minterState_ = _minterState();

    require (_minterState_ == MinterState.PreICOStarted &&
             PreICO.tokensMinimumNumberForBuy  / PreICO.tokensCost ||
             _minterState_  MinterState.ICOStarted &&
             ICO.tokensMinimumNumberForBuy  / ICO.tokensCost);

    _;
  }

  function setOwner(address _owner) public onlyOwner {
    owner 
  }

  function setPaused(bool _paused) public onlyOwner {
    paused 
  }

  function Minter() public {
    owner 
    token  ERC20MintableToken(this);
  }

  function _minterState() private constant returns (MinterState) {
    if (PreICO.startTime > now) {
      return MinterState.PreICOWait;
    } else if (PreICO.endTime > now) {
      return MinterState.PreICOStarted;
    } else if (ICO.startTime > now) {
      return MinterState.ICOWait;
    } else if (ICO.endTime > now) {
      return MinterState.ICOStarted;
    } else {
      return MinterState.Over;
    }
  }

  function _tokensaleCountTokensNumber(Tokensale _tokensale, uint256 _timestamp,
                                       uint256 _wei, uint256 _totalTokensNumber,
                                       uint256 _totalTokensNumberAllowance)
                                      private pure
                                      returns (uint256, uint256) {
    uint256 _tokensNumber = _wei.div(_tokensale.tokensCost);

    require (_tokensNumber >= _tokensale.tokensMinimumNumberForBuy);

    uint256 _aviableTokensNumber =
      _totalTokensNumber <= _totalTokensNumberAllowance ?
        _totalTokensNumber : _totalTokensNumberAllowance;

    uint256 _restWei 

    if (_tokensNumber >= _aviableTokensNumber) {
      uint256 _restTokensNumber = _tokensNumber.sub(_aviableTokensNumber);

      _restWei = _restTokensNumber.mul(_tokensale.tokensCost);

      _tokensNumber = _aviableTokensNumber;
    } else {
      uint256 _timePassed = _timestamp.sub(_tokensale.startTime);

      uint256 _tokensNumberBounty = 0;

      if (_timePassed < _tokensale.tokensStepOneBountyTime) {
        _tokensNumberBounty 
                                           .div(100);
      } else if (_timePassed < _tokensale.tokensStepTwoBountyTime) {
        _tokensNumberBounty 
                                           .div(100);
      } else if (_timePassed < _tokensale.tokensStepThreeBountyTime) {
        _tokensNumberBounty 
          _tokensNumber.mul(_tokensale.tokensStepThreeBounty).div(100);
      } else if (_timePassed < _tokensale.tokensStepFourBountyTime) {
        _tokensNumberBounty  _tokensNumber.mul(_tokensale.tokensStepFourBounty)
                                           .div(100);
      }

      _tokensNumber  _tokensNumber.add(_tokensNumberBounty);

      if (_tokensNumber > _aviableTokensNumber) {
        _tokensNumber = _aviableTokensNumber;
      }
    }

    return (_tokensNumber, _restWei);
  }

  function _tokensaleStart(Tokensale storage _tokensale) private {
    if (!_tokensale.tokensMinted) {
      token.mint(_tokensale.tokensNumberForMint);

      _tokensale.tokensMinted = true;
    }

    uint256 _totalTokensNumber = token.balanceOf(token);

    uint256 _totalTokensNumberAllowance = token.allowance(token, this);

    var (_tokensNumber, _restWei) =
      _tokensaleCountTokensNumber(_tokensale, now, msg.value,
                                  _totalTokensNumber,
                                  _totalTokensNumberAllowance);

    token.transferFrom(token, msg.sender, _tokensNumber);

    if (_restWei > 0) {
      msg.sender.transfer(_restWei);
    }
  }

  function _tokensaleSelect() private constant returns (Tokensale storage) {
    MinterState _minterState_ = _minterState();

    if (_minterState_ == MinterState.PreICOStarted) {
      return PreICO;
    } else if (_minterState_ == MinterState.ICOStarted) {
      return ICO;
    } else {
      revert();
    }
  }

  function () public payable onlyDuringTokensale onlyNotPaused
    checkLimitsToBuyTokens {
    Tokensale storage _tokensale = _tokensaleSelect();

    _tokensaleStart(_tokensale);
  }

  function mint(uint256 _tokensNumber) public onlyOwner onlyDuringTokensale {
    token.mint(_tokensNumber);
  }

  function burnUndistributed() public onlyAfterTokensaleOver {
    token.burnUndistributed();
  }

  function withdraw() public onlyOwner {
    msg.sender.transfer(this.balance);
  }
}

Comments 10


Привет!

20.11.2017 15:04
0
20.11.2017 15:05
0

Приветствую Вас и желаю успехов на платформе Голос!

В этой статье вы сможете найти ответы на большинство вопросов, возникающих у новичков. Также большую подборку ссылок на полезные материалы вы можете найти по этой ссылке
Оперативно получить помощь, вы можете присоединившись к нашему сообществу в Телеграм

Буду признателен, если расскажете, откуда Вы узнали о платформе Голос (ответьте цифрой):
1) увидел в Facebook
2) увидел в ВКонтакте
3) из поиска Google
4) из поиска Яндекс
5) из Steem
6) рассказал друг
7) другое (укажите в комментарии)

Чтобы быстрей освоится, присоединяйтесь к мотивирующему промоушену для новичков, действующего месяц с момента регистрации!

И обязательно добавьте себе в Telegram Бота-инструктора, который позволит вам пошагово освоится на платформе Голос.

20.11.2017 15:35
0

Спасибо за подробную информацию, буду иметь в виду)

Кстати, поздравляю с первым постом на Голосе) Подписался, надеюсь на взаимность) Удачи и всего самого наилучшего!

20.11.2017 21:22
0

Привет @preico -

А) Весь код нужно обернуть в тэги кода - три обратных кавычки:

like this ``` here is code ```

Иначе - читать нереально :)

B) Фраза "Для управления с файлами ABI, если в блокчейн смарт-контракты добавили мы и передали управление" - непонятна. Видимо там пропущено какое-то слово?

C) Код, вставленный пост, необходимо озаглавить как-то. Например, "Исходный код смарт-контракта" и вставить перед заголовком решетку (#) - так в маркдауне получится заголовок.

Удачи, @preico

21.11.2017 14:24
0

Спасибо, @sxiii
Всё поправил как ты рекомендовал. Поддерживается подстветка синтаксиса голосом? Как на гитхабе, когда пишешь после трёх обратных ковычек имя языка)

21.11.2017 14:51
0

Пожалуйста, @preico
Но ничего не исправилось.
Весь код нужно разместить в один блок - не надо делать раздельные блоки, если только ты не комментируешь скриншотами / большими фрагментами пояснений на русском. Даже если комментарии есть в коде - лучше чтобы это был один блок, когда это разбито на 100500 блоков это невозможно нормально скопировать, невозможно нормально читать. Весь фрагмент кода = один блок

 и в конце блока снова 
.
Также, # нужно поставить всего одну, и после # должен быть пробел.
Markdown очень простой язык, я бы сказал - простейший, но он не разрешает совершать ошибки или опечатки. Что-то надо указывать слитно, например жирный шрифт, а где то наоборот нужен пробел. Перед тем как публиковать результат - всегда советую перепроверить получившийся код в окошке под постом. Иначе люди увидят полу-доделанную версию.
P.S. Подсветка кода пока что не поддерживается, насколько мне известно. Возможно она поддерживается в стимите, но точно не уверен.

Удачи, @preico!

21.11.2017 15:00
0