Ethereum, Truffle, Zeppelinを使って瞬速でICOを始める

Truffleフレームワークと、Zeppelinライブラリを利用してEthereum上でのICOシステムを瞬速開発し、実現します。
ブロックチェーンは暗号化技術や、ゲーム理論、経済学など様々な知識が必要になりますが、スケーラビリティやセキュリティは置いておいて、プログラムや実装に限ればさほど難しくはないと思います。
※異論、反論あればたくさん教えてください。

## よくある疑問たち
* ICOするためにはブロックチェーンを開発する必要があるの？
 * 必要ではないです。イーサリアムなど既存のプラットフォーム上で実装することが一般的です。
* ICOするためには何を準備する必要があるの？
 * 一般的には多言語のホワイトペーパーを作成して投資家を募り、ICO用のコントラクトを公開して仮想通貨を送ってもらいます。送ってもらったアドレスにちゃんと新通貨を返しますよーというのを契約するのにコントラクトを使います。
 * HPやGithub,Twitterなどの公開もしますが、マーケティングの手段なのでケース・バイ・ケースです。
 * 極端な話ですが、自分のウォレットアドレスを公開してそこに直接仮想通貨を送ってもらうだけでもICO自体は可能です。企画や意図が伝われば良いので、ホワイトペーパーも必須ではないと言えます。

# ICOって？
* ICOってなに？
 * Initial Coin Offering の頭文字です。VCやエンジェル投資家に頼らない新たな資金調達方法として注目されています。
 * 簡単に言うと、投資を受けたいベンチャー起業などが新しい仮想通貨を発行して、その通貨を買ってもらうことで投資を集めることです。今後値上がりすることを期待する投資家やユーザーが初期の安い段階で購入し、ICOを行ったチームはその通貨の価値を上げるためにICOで集まった資産を用いてサービスの開発などを行います。
* ICOは普通の投資とどう違うの？
 * わかりやすい点としては、世界中から投資を得ることができます
 * 次に異なる点はICOの参加者がその通貨の価値を高めるために行動できるということです
 * 例:コロンブスがアメリカ大陸を発見して、その後ヨーロッパから移民が流れ込み、新たにできた米ドルがいまや世界有数の価値と安定感をもっていることでわかるように、通貨を利用する人数やそこで行われる経済活動によって通貨の価値は決まります
 * アメリカ国民は米ドルの価値を高めるために経済活動をするのと同じように、ICOに参加したひとはICOオーナーと一緒に新通貨の価値を高める運動をすることができます。

* ICOはいいことだらけ？
 * スキャム(詐欺)が横行していてICO参加の際は気をつけて下さい。
 * シードで30億とか集まってしまうのでそのまま持ち逃げが早いですよね。
 * 日本の税制上、ICOで集めた通貨は現金化しなくても売上に換算されてしまうのでベンチャー初年度で数億や数十億の売上になるとその年の法人税どうすんねんっていう問題がありそうです。
 * 通貨の価値を上下させるためにデマやフェイクニュースが出るデメリットもあります。

* ホワイトペーパーって？
 * 新たな仮想通貨の概要を説明する数十ページ程度の論文のようなもの
 * 仮想通貨の大元ビットコインの開発者「サトシ・ナカモト」が書いたbitcoinの仕組みが説明された論文をホワイトペーパーと呼んでいて、これを踏襲して新たな仮想通貨でもホワイトペーパーと呼んでいます
 * 新仮想通貨を発行する背景や、開発チーム、ICOの説明や、マイルストーンなどが書かれていることが多いですが、ページ数や内容などかなりバラバラです

## 言葉の意味まとめ
**Ethereum** - イーサリアム
ここではスマートコントラクトを実行するためのプラットフォームを指す。Ethereum Virtual Machine (EVM) 上で動作する。
イーサリアムプラットフォーム上で動作する仮想通貨ETHとしても有名。イーサリアムプラットフォームを利用する際に手数料としてETHを利用して支払う、ガスと呼ばれる。

**Truffle** - トリュフ
Consensysが開発している。Ethereumの開発用フレームワーク。
トークンの作成やアドレス管理、テスト、コンパイル、デプロイなどを簡易にしてくれる。
公式 : http://truffleframework.com/

**Zeppelin Solidity**　- ツェッペリン ソリディティ
EthereumのコントラクトをSolidityでの実装を補助するためのライブラリ。
ETH上で動作するトークンは8つの関数と２つのイベントを作成する必要があるが、これを簡単にしてくれる。
※上記はERC20の仕様で、新たにERC223という仕様があり、幾つかの課題が解決している。

**Solidity** - ソリディティ
Ethrerumのコントラクトを記述するためのプログラミング言語。いまのところデファクトスタンダードとなっている。使い勝手などについて賛否両論あります。
Ethereumの生みの親VitalikはSolidityを余り好んでいないという話も聞きました（裏取ってません）

**token** - トークン
プラットフォームとなっているブロックチェーン上で実装されている独自コインのこと。OMGとか。
トークンではない仮想通貨にBitcoinやEthereumがある。

## 実行環境
mac OS High Sierra 10.13.1
node 8.7.0
npm 5.6.0
solidity 0.4.18+commit.9cf6e910.Darwin.appleclang

## Solidity のインストール

Github: https://github.com/ethereum/solidity

```
$ brew install cpp-ethereum
$ brew linkapps cpp-ethereum
$ brew install solidity
```

## テンプレートの作成

Truffleのインストール

``` 
npm install -g truffle
```

テスト用のEthereum環境を提供するethereumjs-testrpcのインストール

```
npm install -g ethereumjs-testrpc
```

テンプレートの作成 と Zeppelin Solidity　のインストール

```
$ mkdir araya_coin
$ cd araya_coin
$ truffle init
$ npm install  zeppelin-solidity
```

これでTruffleとZeppelinを利用したテンプレートができました。

## トークンの実装
上記で述べたERC20のトークンをZeppelinで実装します

```
$ vim contracts/ArayaCoin.sol 
```

```
pragma solidity ^0.4.18;
import "zeppelin-solidity/contracts/token/MintableToken.sol";

contract ArayaCoin is MintableToken {
  string public name = "ARAYA COIN";
  string public symbol = "ARY";
  uint8 public decimals = 18;
}
```

なんとこれだけでやんス！Zeppelineは天国への階段ですね。

## ICOのルールの実装
いつからいつまで？とか、いくらで１トークン売るの？とかICOで決めないといけないですよね。
ZeppelinにはきちんとCrowdsaleというクラスが準備されています。

```
$ vim contracts/ArayaCoinCrowdSale.sol
```

```
pragma solidity ^0.4.18;

import './ArayaCoin.sol';
import 'zeppelin-solidity/contracts/crowdsale/Crowdsale.sol';


contract ArayaCoinCrowdsale is Crowdsale {

  function ArayaCoinCrowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet) public 
    Crowdsale(_startTime, _endTime, _rate, _wallet) {
  }

  function createTokenContract() internal returns (MintableToken) {
    return new ArayaCoin();
  }

}
```

```
$ vim migrations/2_deploy_contracts.js
```

```js
const ArayaCoinCrowdsale = artifacts.require("./ArayaCoinCrowdsale.sol")

module.exports = function(deployer, network, accounts) {
  const startTime = web3.eth.getBlock(web3.eth.blockNumber).timestamp + 1 // one second in the future
  const endTime = startTime + (60 * 10) // 10 minutes
  const rate = new web3.BigNumber(1000)
  const wallet = accounts[0]

  deployer.deploy(ArayaCoinCrowdsale, startTime, endTime, rate, wallet)
};
```

* startTime : 開始時間
* endTime : 終了時間
* rate : ETHとのトレードレート。  上記の場合 1ETH=1000ARY
* wallet : ETH集めるウォレットのアドレス



# デプロイ
ローカル環境にデプロイして動作を確認します。

testrpcを起動

```
$ testrpc -u 0
```

別のコンソールで

```
$ truffle compile
$ truffle migrate
```

これでICOが開始されました(ローカルのテスト環境)！　やったねボーナム！

# ICOのコインを購入
ICOのコインを購入してみます

開発環境にアクセス

```
$ truffle console
truffle(development)>
```

Web3.jsのAPIが使えるインタラクティブなコンソールが立ち上がるので、ARY通貨の購入を試してみます。

ARY通貨購入用のアカウントの準備

```
truffle(development)> account1 = web3.eth.accounts[1]
'0x5d1c1371dcf76157934badb4c8ea9b8cc3a7b901'
```

Arayaクラウドセールクラスのインスタンスを crowdsale変数に代入

```
truffle(development)> ArayaCoinCrowdsale.deployed().then(inst => { crowdsale = inst })
undefined
```

クラウドセールのOwnerアドレスを取得

```
truffle(development)> crowdsale.token().then(addr => { tokenAddress = addr } )
undefined
truffle(development)> tokenAddress
'0x57376d152d82a38250c65bedb8ea08ebca9765d7'
```

Arayaコインのインスタンスを作成

```
truffle(development)> arayaCoinInstance = ArayaCoin.at(tokenAddress)
TruffleContract {
  constructor: 
   { [Function: TruffleContract]
・・・・・・・・
・・・・・・・・
・・・・・・・・
```


現在のArayaコインのトークン数を確認すると、０です。

```
truffle(development)> arayaCoinInstance.balanceOf(account1).then(balance => balance.toString(10))
'0'
```

ARYトークンの購入
5ETHでARYトークンを購入します。

```js
truffle(development)> ArayaCoinCrowdsale.deployed().then(inst => inst.sendTransaction({ from: account1, value: web3.toWei(5, "ether")}))
{ tx: '0x3b09fff2b78079f95217ab264d0bf048ee07059bbb8a4b19d9743b0fbb406f6e',
  receipt: 
   { transactionHash: '0x3b09fff2b78079f95217ab264d0bf048ee07059bbb8a4b19d9743b0fbb406f6e',
     transactionIndex: 0,
     blockHash: '0x956c340c5947359b71e2928c9107b4aa9ec77621e08d79a618812f25dcd8472c',
     blockNumber: 5,
     gasUsed: 99236,
     cumulativeGasUsed: 99236,
     contractAddress: null,
     logs: [ [Object], [Object], [Object] ],
     status: 1 },
  logs: 
   [ { logIndex: 2,
       transactionIndex: 0,
       transactionHash: '0x3b09fff2b78079f95217ab264d0bf048ee07059bbb8a4b19d9743b0fbb406f6e',
       blockHash: '0x956c340c5947359b71e2928c9107b4aa9ec77621e08d79a618812f25dcd8472c',
       blockNumber: 5,
       address: '0xb8c9780f0011df13dc7a2dde65c11a2215a3b6e0',
       type: 'mined',
       event: 'TokenPurchase',
       args: [Object] } ] }
```

Arayaトークン数の確認

```
truffle(development)> arayaCoinInstance.balanceOf(account1).then(balance => account1GusTokenBalance = balance.toString(10))
'5000000000000000000000'
```

18decimalsを設定していたので、0が18個後ろについています。decimalsを外してみてみましょう。
設定していた 1ETH = 1000ARY となっていますね。
※普通の草コインはもっと少ないETHで買うため 18decilmals でもちょうどよいのだと思います。

```
truffle(development)> web3.fromWei(account1GusTokenBalance, "ether")
'5000'
```

コントラクトが守られてオーナーのウォレットへのETHの送金によって、ARYが購入できていますね！！

これで最低限のICOのコントラクトの準備ができました。
あとはホワイトペーパーなどで投資家をつのり、ETHのプラットフォーム上にICOシステムをデプロイすればICOが開始できます。

ソースです
https://github.com/arkth-araya/araya-coin-ico/


## 参考
* How To Create Token and Initial Coin Offering Contracts Using Truffle + OpenZeppelin
https://blog.zeppelin.solutions/how-to-create-token-and-initial-coin-offering-contracts-using-truffle-openzeppelin-1b7a5dae99b6
* https://github.com/trufflesuite/truffle
* https://github.com/OpenZeppelin/zeppelin-solidity
* サーバーレスフレームワークTruffleでÐappを爆速開発する ①Tutorial
https://qiita.com/syrohei/items/5eb573b781caedde16a1#9-main-net%E3%81%AB%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4
* Ethereumテストネット上でクラウドセール(Crowdsale)を開催する
https://wakuwaku-currency.com/virtual-currency/ethereum/testnet-crowdsale-ethereum.html