Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
ICOコンサルティング事業から得たトークンと全体アーキテクチャ設計方針の知見 @ blockchain.tokyo #2
Tomohiro Nakamura
November 14, 2017
Technology
7
23k
ICOコンサルティング事業から得たトークンと全体アーキテクチャ設計方針の知見 @ blockchain.tokyo #2
Tomohiro Nakamura
November 14, 2017
Tweet
Share
More Decks by Tomohiro Nakamura
See All by Tomohiro Nakamura
tomohiron
2
1.7k
tomohiron
2
1k
Other Decks in Technology
See All in Technology
ymas0315
0
180
chaspy
1
160
nkjzm
1
850
clustervr
0
210
sumi
0
530
kraj
0
5.4k
clustervr
0
190
redhatopenshift
0
310
kawaguti
0
120
kanaugust
PRO
0
100
line_developers
PRO
0
2.2k
layerx
1
920
Featured
See All Featured
zakiwarfel
88
3.3k
keithpitt
401
20k
shlominoach
176
7.4k
hatefulcrawdad
257
17k
tmm1
61
8.4k
jnunemaker
PRO
40
4.6k
thoeni
4
550
notwaldorf
13
1.6k
bryan
30
3.3k
roundedbygravity
241
21k
sferik
609
54k
samlambert
237
9.9k
Transcript
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE CTO Tomohiro Nakamura ( @HAIL ) ICOコンサルティング事業から得た トークンと全体アーキテクチャ設計⽅針の知⾒ 2017/11/14(Tue)
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE ⾃紹介 AnyPay株式会社 CTO Tomohiro Nakamura ( @HAIL ) 2010年
早稲⽥⼤学⼤学院情報理⼯学専攻 2010年 Goldman Sachs 2012年 Electronic Arts (ex. Playfish) 2014年 Wekids Inc. 創業 2016年 AnyPay株式会社 CTOとして⼊社 好き: Kotlin, Android, GCP paymo招待コード: PNKYFNP ࣗݾհ
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE εϚʔτϑΥϯܾࡁαʔϏεΛఏڙ ΘΓ͔ΜΞϓϦzQBZNPz ܾࡁαʔϏεzQBZNP CJ[z ఏڙதͷαʔϏεʹ͍ͭͯ ఏڙதͷαʔϏεʹ͍ͭͯ
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE *$0ίϯαϧςΟϯάࣄۀʹ͍ͭͯ ৽نࣄۀ 'JO5FDIࣄۀͷల։ɺۀքͷࢿ࣮ࠃ֎ͷؔ࿈اۀͱͷϦϨʔγϣϯΛ׆͔ͯ͠ɺ Ծ௨՟ʹΑΔࢿۚௐୡɺ*$0ίϯαϧςΟϯάࣄۀΛల։ɻ λʔήοτ ڧΈ ελʔτΞοϓɾະ্தখاۀஶ໊ਓͳͲ ࢿۚௐୡधཁ͕ΑΓߴ͍اۀΛ༏ઌɻ Ұൠফඅऀߴ໊͍ϑΝϯ
*$0ʹೃછΈͷ͋ΔاۀҰൠࢿՈ ػؔࢿՈͷרࠐΈૂ͍༏ઌΛݕ౼ ɾԾ௨՟ۚ༥ۀքͷਂ͍ཧղ ɾࢿՈऔҾॴɺۀఏܞઌͳͲωοτϫʔΫ ɾઓུίϯαϧςΟϯάͷέΠύϏϦςΟ ɾߴ͍ٕज़ྗ $0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE ICOコンサルティング事業について 事前準備 事前設計 実装 ICO実施 ⽬的・意義の 定義 調達額・ 計画検討
既存株主への 説明・説得 スキーム決定 コイン機能・サー ビスとの融合決定 コイン実装 サ イ ト オ プ ン プ レ セ ル ク ラ ウ ド セ ル 社 内 側 の 動 き 社 外 協 議 取引所との協議 弁護⼠確認・協議 プロモーション・ 投資家との コミュニケーション キャンペーン 設計 オペレーション 設計 ホワイト ペーパー 作成 サイト 作成 セ カ ン ダ リ マ ケ ッ ト 開 設 1カ⽉〜 1〜2カ⽉ 2〜3カ⽉ :法務・会計 :技術・開発 :ビジネス・マーケ
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE どうしたら ICOに投資してくれるだろう?
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE 1. 値上がりが期待できる 2. 付加価値がついている
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE 付加価値のかたち ICO実施企業の 提供サービス内にて 通貨として利⽤、もしくは 特別割引などの優待を 受ける事が可能 コインが株式のような 役割を担い、 保有者に対して
企業経営・プロジェクトの 収益の⼀部が還元される サービス型 株式型
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE 実際に設計してみよう
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE その前に前提を・・・ Ethereumブロックチェーンに乗っかる ICOの多くはEthereumベース Solidityを使った開発やParityなどを使ったデプロイや管理などエコシステムが できあがりすぎていて圧倒的に楽なため 送受信されるコントラクトはERC20インタフェースに乗っかる Ethereumベースのコントラクトが基本的に実装するべき関数の定義たち、 と考えておけば良い ウォレットや取引所サービスたちは、基本的に各トークンがERC20準拠である
ことを前提にしている
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE ERC20 contract ERC20 { // 合計流通量を返す function totalSupply() constant
returns (uint totalSupply); // _owner の持っている量を返す function balanceOf(address _owner) constant returns (uint balance); // _to に _value 分送る(ウォレットアプリがよく叩く関数) function transfer(address _to, uint _value) returns (bool success); // _from から _to に _value 分代理で送る function transferFrom(address _from, address _to, uint _value) returns (bool success); // _spender に _value 分代理で送ることを許可する function approve(address _spender, uint _value) returns (bool success); // _owner は _spender にどれだけの量を代理で送ることを許可しているか返す function allowance(address _owner, address _spender) constant returns (uint remaining); }
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE 典型的な(シンプルな)セールの流れ CONFIDENTIAL : copyright © by 2017 AnyPay inc.
all rights reserved 1. セールの実施前に参加予定者に事前登録してもらい連絡⼿段を確保 (Email, Slack, Telegram, etc…) 2. セールの実施前に、参加予定者にETHを取引所アカウントではなく、⾃ 分で秘密鍵を管理しているアカウントに移動しておくよう伝達 3. セール開始直前に、参加予定者にETH振込先を伝達 4. ETHを振り込んでくれたアドレスに、ERC20準拠であるICOトークンを 送り返す 5. 終了⽇時または最⼤調達⾦額に達したら締め切り
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE 〜ケーススタディ〜 想定クライアントはアジアのあるライドシェアサービス 当然ながら、ICOをきっかけにサービスの拡⼤を考えている 以下のフェーズに分けてICOをしたいと考えている
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE ケーススタディ ‒ Phase 1 ① このICOで得た資⾦で、サービスに使う⾞両を購⼊する ② このトークンを持っていることにより、購⼊された⾞両によって得られた利益のうち⼀ 部が分配される(株式型)。利益の分配はEthereumベースで毎⽉決まったタイミングで
⾏われる ③ トークンセールの参加にはKYC(本⼈確認) が要求される。また、許可されていないアド レスにtransferすることは許可しない ④ Phase 1のセールは2回⾏われる。それぞれ期間と上限額を事前に決定する。1回⽬は 2ヶ⽉後ぐらいを予定している。2回⽬は未定 ⑤ KYCは2度のPhase 1セールで共有される ⑥ 後々発⾏されるPhase 2のトークンに割引価格で変換できる ⑦ または、⾞両が償却されるまでトークンを持ち続けた場合、再売却価格の分配を受ける こともできる Phase 1
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE ケーススタディ ‒ Phase 2 ① Phase 2のトークンは、このICO予定の会社以外にも、世界中のシェアリング サービスで利⽤可能なサービス型トークンとなっていく計画を持っている ②
サービスのユーザは、このトークンを⽀払に利⽤することができる ③ シェアする側のユーザは、対価としてこのトークンを受取る ④ Phase 1とは違い、こちらのトークンは取引所への上場を予定している Phase 2
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE さあ設計してみよう! オブジェクト指向でいうところのクラス図を書こう! (Ethereumのコントラクト開発は、 正直オブジェクト指向にちょっと寄った JavaScript開発ぐらいの気持ち)
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE 要点1 ユーザに伝達したアドレス上の コントラクトを上書きすることは無理
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE 要点2 数ヶ⽉以上後先のサービスのことなど 普通確定しない(仕様は誰も知らない) (通貨が仮想になりDBがブロックチェーン になったぐらいでこの宇宙の決まりが 変わるわけない)
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE この2点からの導き • 柔軟に作ろう • ユーザが触れるコントラクトでごちゃごちゃやるのはやめよう • 迷惑かけずに実装を変更できるようにしよう • 先のことはわからないが可能性が⾼いことのPoCはなるべくしよう
• こんな当たり前のことをするのが⾯倒な時点でつらぽよなので、す べてをEthereum上でやるかどうかは疑問視してかかろう (時間次第ですがここで1分ぐらい待ちます)
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE 解答例
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE 登場⼈物 1. Coin Vendor(投資家がETHを振り込むアドレスのコントラクト) 2. Coin(投資家が⼿に⼊れるトークンの実装。ERC20) 3. Coin Implementation(ロジックを書くコントラクト)
4. Storage(データを持つコントラクト) 5. Shared Storage(複数トークン間でシェアするデータを持つコント ラクト)
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE Coin Vendor • Phase 1のコインをまとめ て”Private Coin” と便宜上呼ぶ •
ユーザがこのコントラクトに ETHを送るとpayableな無名関 数()が呼ばれる • セールの期間やこれまでに販売 した(発⾏した)量、最⼤販売量、 販売単位などが定義されている • コインの実装コントラクトへの 参照を持つ • transferFundsはたまったETH を引き出す関数
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE Coin Vendor要所 function () public payable { vend(msg.sender, msg.value,
now); } function vend(address receiver, uint value, uint timestamp) internal returns (bool) { uint amount = value / tokenUnitPrice; // ETH (単位は wei) を購入数に変換する require(amount >= minimumPurchaseUnit); // 最小販売トークン数を超えているか require(timestamp >= salesBegin && timestamp < salesEnd); // 販売期間の確認 require(safeAdd(amount, cumulativeSalesAmount) <= salesAmount); // 在庫の確認 cumulativeSalesAmount = safeAdd(cumulativeSalesAmount, amount); impl.mint(receiver, amount); // 発行する(実装はimplに委譲されている) return true; }
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE Coin Implementation • 実際のロジックを持つ • データは持たない • ⾮管理者から関数が叩かれ ることは想定していないの
で殆どの関数が auth 修飾 ⼦つき
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE Coin Implementation要所 function transfer(address sender, address to, uint amount)
auth public returns (bool) { require(coinStorage.coinBalanceOf(sender) >= amount); // 残高を超えて送金してないか require(amount > 0); // 1円以上送ろうとしているか // オーナーまたは許可された (KYC 通過済み) アドレスかを確認 require(sharedStorage.isOwnerAddress(to) || sharedStorage.isApprovedAddress(to)); // 送金元の残高を減らし、送金先の残高を増やす coinStorage.setCoinBalance(sender, safeSub(coinStorage.coinBalanceOf(sender), amount)); coinStorage.setCoinBalance(to, safeAdd(coinStorage.coinBalanceOf(to), amount)); // 送金先がコントラクトで、isPrivateTokenAcceptable が true を返すコントラクトではreceiveToken() if (isContract(to)) { PrivateCoinAcceptableContract receiver = PrivateCoinAcceptableContract(to); if (receiver.isPrivateTokenAcceptable()) { require(receiver.receiveToken(sender, amount)); } } return true; } ここがPhase 2のPoC部分 (Phase 1トークンはPhase 2トーク ンに割引価格で交換できる)
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE Coin • 取引されるトークンのコン トラクト • ERC20準拠 • Eventを呼ぶ •
実装はimplに委譲
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE Coin要所 function transfer(address to, uint amount) public returns (bool)
{ if (impl.transfer(msg.sender, to, amount)) { Transfer(msg.sender, to, amount); return true; } else { return false; } } Eventを呼ぶ 基本的にimplに委譲
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE Coin Storage Phase 1の2つのトークンそれぞれ別々に持つデータのコントラクト
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE Shared Coin Storage KYC済みアドレスのリストなど、 Phase 1の2つのトークンで共有するデータのコントラクト
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE もう⼀度登場⼈物 1. Coin Vendor(投資家がETHを振り込むアドレスのコントラクト) 2. Coin(投資家が⼿に⼊れるトークンの実装。ERC20) 3. Coin Implementation(ロジックを書くコントラクト)
4. Storage(データを持つコントラクト) 5. Shared Storage(複数トークン間でシェアするデータを持つコント ラクト)
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE リリース⽅法 1. 全てのコントラクトをせっせとデプロイする 2. setImpl(address) auth public: bool などを実⾏して付け替えを⾏う
3. KYC済みユーザの追加は impl.addApprovedAddress(address) データのコントラクト書き換えの場合は マイグレーションも頑張らないといけませんよね…… 正直Ethereumすごい。すごいけど
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE Phase 2をすべて この調⼦で実装していこうと思ったら まだつらい気がしている…… (GAS⼿数料も⾺⿅にならない笑)
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE ⼿段のために⽬的を⾒失わない ⼀番⼤事なことは • ◦ トークンの価値が上がり投資家もユーザもハッピー • ◦ サービスが使いやすくてユーザもハッピー •
◦ メンテが楽で開発者もハッピー • × 全部ブロックチェーンでやるとかっこいい ストレージが増える(RDB, NoSQL, ブロックチェーンetc)ごとに、 当然ながらメンテは⼤変。 Ethereumとプライベートな独⾃ブロックチェーンの併⽤も⼤変。 かっこよさとハッピー、両⽴したい、どうしよう…… えっ、もっと詳しく話を聞きたいって?
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE ここでお知らせです AnyPayではICOコンサルティング を提供しております AnyPayでは優秀なエンジニアと コンサルタントを募集しております
$0/'*%&/5*"-DPQZSJHIUCZ"OZ1BZJODBMMSJHIUTSFTFSWFE 決済でもブロックチェーンでも、 興味ある⼈はWantedly で応募待ってます! https://www.wantedly.com/projects/167898