Все, что нужно знать об ICO, пробуем смарт-контракт в действии
Слышали про ICO? А как насчёт выпуска собственных токенов? Разобрались, как это осуществить.
Что такое ICO
Initial Coin Offering — это новое слово в мире краудфандинга. Благодаря созданию криптовалют, по всему миру запускают стартапы и для привлечения капитала выпускают в продажу свои токены — те же акции, только для их обращения не нужны банки, сложная отчётность, время. Так вот, первоначальная продажа токенов — и есть ICO (аналог IPO).
Как это работает и откуда появилось
Сами токены основаны на системе криптовалют. А они, между прочим, разрабатываются уже более 20 лет. Да, до Bitcoin были другие попытки создать виртуальные деньги, но потребовалось время, чтобы совместить их сильные стороны.
Технология Bitcoin была описана и реализована в 2008 году, и она есть не что иное, как набор правил, по которым компьютеры обмениваются информацией обо всех сделках — блокчейн. Нет единых дата-центров, потому что одновременно с майнингом новых блоков (добычей биткоинов), пользователи обмениваются информацией, образуя распределённую базу данных.
Вот ещё большая картинка о том, как работают переводы в Bitcoin.
Сеть имеет устойчивость к атакам вроде double-spending, потому что для их проведения необходимо иметь значительный процент от суммарной мощности всей сети.
На Bitcoin дело не остановилось — появились десятки других валют, в том числе Ethereum. Он разрабатывался как усовершенствование Bitcoin: в нём добавлена поддержка «умных контрактов» и создания распределённых приложений (DApps) на Тьюринг-полных языках программирования. Именно этим и заинтересовались такие компании, как Microsoft, IBM, Сбербанк. Каждый умный контракт запускает код на компьютерах майнеров в специальной Ethereum Virtual Machine, что позволяет заключать договора, создавать ценные бумаги, не отдавая контроль какому-либо органу наподобие банка или государства — условия просто исполняются на распределённой сети.
По ссылке можно прочитать подробнее о том, как писать Dapps, на простом примере. А также ещё 3 примера на языке Solidity для вдохновения.
С точки зрения инвестирования
Вкладывая деньги на ICO, можно заработать, как и на торговле криптовалютой. Если вы инвестируете в компанию, она может и не иметь высокого дохода, но её рыночная капитализация будет оцениваться стоимостью токенов.
Как правило, условия проведения ICO — количество и цена токенов, этапы продажи — указываются заранее на сайте. Некоторые компании (в лучших традициях краудфандинга) предлагают возможность впоследствии пользоваться токенами для оплаты их товаров или услуг.
ICO в отличие от IPO:
- пока никак не регулируется государствами
- не рассчитано для выплаты дивидендов
- больше подходит для краткосрочных вложений
- покупка доступна любому
Поэтому, пока его активно применяют некоммерческие, волонтёрские организации, open-source, команды учёных.
Для тех, кого заинтересовало — ещё ссылка про инвестирование в ICO.
Как организовать ICO со своими токенами
Создать свои токены на основе существующих «умных контрактов» несложно (см. ниже). Но вообще говоря, написание документации, контракта, а после — тщательный анализ кода и тестирование — процесс очень трудоёмкий. Потому как будучи однажды выпущенным, контракт не может быть изменён.
Далее возникнут вопросы с тем, как грамотно продавать свои токены: потребуется анализ бизнеса, правовой части, пиар. Если вы действительно намерены собрать деньги посредством ICO, причём с минимумом трудозатрат, то можете обратиться к организации, оказывающей такие услуги — на сегодняшний день их уже существует множество. Вот пример: Coral, Ambisafe, Espeo
Как создавать токены и умные контракты
Если вы разобрались в том, как работает блокчейн, значит вы готовы для этого этапа и можете ознакомиться с этой системой на простых примерах своими руками. Сначала разберёмся с инструментами.
Truffle — фреймворк для создания умных контрактов и распределённых приложений;
OpenZeppelin — библиотека, содержащая отличные проверенные контракты — они все хорошо протестированы и придерживаются лучших практик по безопасности (тут не стоит изобретать велосипед, потому что небольшая ошибка может стоить очень дорого);
testrpc — быстрый и несложный Ethereum клиент (blockchain node) для тестирования и разработки;
Geth, Parity или подобный инструмент — если вы хотите создать контракт в тестовой или основной сети Ethereum.
Всё необходимое установим через npm (скачать его самого можно здесь). В терминале:
$ npm install -g ethereumjs-testrpc $ npm install -g truffle $ mkdir my-ico && cd my-ico $ truffle init $ npm install zeppelin-solidity
Теперь у вас есть всё, чтобы создавать, запускать и выпускать свои умные контракты. После этого у вас есть папка zeppelin-solidity внутри node_modules, где вы можете найти все шаблоны контрактов из библиотеки OpenZeppelin.
Мы создадим простой токен с возможностью остановки на всякий случай. А именно, мы будем иметь возможность приостановить торговлю с нашими токенами во время краудфандинга, если что-то пойдёт не так.
Первый шаг — создание контракта токена
touch contracts/ProglibCoin.sol
А в коде:
pragma solidity ^0.4.11;
import 'zeppelin-solidity/contracts/token/MintableToken.sol';
contract ProglibCoin is MintableToken {
string public name = "PROGLIB COIN";
string public symbol = "PRL";
uint256 public decimals = 18;
}
Это — базовое решение для контрактов. Таким образом, OpenZeppelin лишает нас необходимости хардкодить. Мы обращаемся к MintableToken, чтобы обозначить, что токены управляются, эмитируются их владельцем. Подробнее можно изучить в исходном коде: node_modules/zeppelin-solidity/contracts/token/MintableToken.sol
Следующий шаг — создание Crowdsale контракта
touch contracts/ProglibCoinCrowdsale.sol
Мы собираемся унаследовать его от:
node_modules/zeppelin-solidity/contracts/crowdsale/Crowdsale.sol:
pragma solidity ^0.4.11;
import './ProglibCoin.sol';
import 'zeppelin-solidity/contracts/crowdsale/Crowdsale.sol';
contract ProglibCoinCrowdsale is Crowdsale {
function ProglibCoinCrowdsale(uint256 _startBlock, uint256 _endBlock, uint256 _rate, address _wallet) Crowdsale(_startBlock, _endBlock, _rate, _wallet) {
}
// Создание токена для продажи
// Перегружаем эту функцию, чтобы создавать свои MintableToken
function createTokenContract() internal returns (MintableToken) {
return new ProglibCoin();
}
Согласитесь, красиво? В родительский конструктор Crowdsale мы должны передать параметры startBlock, endBlock (для любопытных, один час — это примерно 212 блоков), rate (tokens per ether), а также wallet — адрес владельца контракта.
Теперь опробуем контракт в действии
В терминале:
$ testrpc -u 0
Эта команда запустит testrpc с одним разблокированным аккаунтом.
Далее откройте файл migrations/2_deploy_contracts.js и измените его следующим образом:
var ProglibCoinCrowdsale = artifacts.require("./ProglibCoinCrowdsale.sol")
module.exports = function(deployer, network, accounts) {
const startBlock = web3.eth.blockNumber + 2 // номер блока, с которого начнётся продажа. Пусть будет через 2 после текущего
const endBlock = startBlock + 300 // номер блока, на котором оно завершится. 300 — это немного больше часа
const rate = new web3.BigNumber(1000) // стоимость по отношению к ether в wei
const wallet = web3.eth.accounts[0] // адрес — держатель счёта. Для безопасности рекомендуется использовать multisig
deployer.deploy(ProglibCoinCrowdsale, startBlock, endBlock, rate, wallet)
}
Обратите внимание, что мы не развёртываем ProglibCoin, потому что ProglibCoinCrowdsale и так его создаёт. Возвращаемся в терминал:
$ truffle compile $ truffle migrate
Если вы наблюдаете вкладку testrpc, то увидите, что контракт был успешно выпущен.
Итак, давайте попробуем приобрести немного PRL токенов
$ truffle console
Должна открыться консоль Truffle, где мы будем использовать API web3.js для взаимодействия с выпущенным контрактом.
// Аккаунт, приобретающий токены PRL
> account1 = web3.eth.accounts[1]
'0xddac5d057c79facd674bc95dfd9104076fd34d6b'
// Присваивание переменной crowdsale результата функции ProglibCoinCrowdsale.deployed() - адрес экземпляра токена PRL
> ProglibCoinCrowdsale.deployed().then(inst => { crowdsale = inst })
> undefined
> crowdsale.token().then(addr => { tokenAddress = addr } )
> tokenAddress
'0x87a784686ef69304ac0cb1fcb845e03c82f4ce16'
> proglibCoinInstance = ProglibCoin.at(tokenAddress)
// Далее убедимся, что account1 имеет нулевое количество PRL.
proglibCoinInstance.balanceOf(account1).then(balance => balance.toString(10))
'0'
// Покупка токенов PRL
> ProglibCoinCrowdsale.deployed().then(inst => inst.sendTransaction({ from: account1, value: web3.toWei(5, "ether")}))
{ tx: '0x68aa48e1f0d0248835378caa1e5b2051be35a5ff1ded82878683e6072c0a0cfc',
receipt:
{ transactionHash: '0x68aa48e1f0d0248835378caa1e5b2051be35a5ff1ded82878683e6072c0a0cfc',
transactionIndex: 0,
blockHash: '0xb48ceed99cf6ddd4f081a99474113c4c16ecf61f76625a6559f1686698ee7d57',
blockNumber: 5,
gasUsed: 68738,
cumulativeGasUsed: 68738,
contractAddress: null,
logs: [] },
logs: [] }
undefined
// Снова проверим баланс account1.
> proglibCoinInstance.balanceOf(account1).then(balance => account1PrlTokenBalance = balance.toString(10))
'5000000000000000000000'
// При создании токена, мы сделали их число 18-разрядным — столько же, сколько и у ether. Выведем только значимую часть:
> web3.fromWei(account1PrlTokenBalance, "ether")
'5000'
Сработало! Что делать дальше, - спросите вы.
Можете протестировать этот код в Ethereum testnet или создать веб-приложение, позволяющее пользователям взаимодействовать с созданным контрактом (обратите внимание, что код работает в Truffle в папке app). Можете реализовать дедлайн, рыночную капитализацию и т. д. Дайте волю воображению, будьте одним из первых!
Сообщество Ethereum растёт изо дня в день, и хотя инструментов для работы пока не много, Truffle и OpenZeppelin отлично справляются с задачами и облегчают работу разработчикам.