Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ICOコンサルティング事業から得たトークンと全体アーキテクチャ設計方針の知見 @ blockc...

ICOコンサルティング事業から得たトークンと全体アーキテクチャ設計方針の知見 @ blockchain.tokyo #2

Tomohiro Nakamura

November 14, 2017
Tweet

More Decks by Tomohiro Nakamura

Other Decks in Technology

Transcript

  1. $0/'*%&/5*"-DPQZSJHIU˜CZ"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 ࣗݾ঺հ
  2. $0/'*%&/5*"-DPQZSJHIU˜CZ"OZ1BZJODBMMSJHIUTSFTFSWFE *$0ίϯαϧςΟϯάࣄۀʹ͍ͭͯ ৽نࣄۀ 'JO5FDIࣄۀͷల։ɺۀք΁ͷ౤ࢿ࣮੷΍ࠃ಺֎ͷؔ࿈اۀͱͷϦϨʔγϣϯΛ׆͔ͯ͠ɺ Ծ૝௨՟ʹΑΔࢿۚௐୡɺ*$0ίϯαϧςΟϯάࣄۀΛల։ɻ λʔήοτ ڧΈ ελʔτΞοϓɾະ্৔தখاۀஶ໊ਓͳͲ ࢿۚௐୡधཁ͕ΑΓߴ͍اۀΛ༏ઌɻ Ұൠফඅऀ΁ߴ஌໊౓΍޿͍ϑΝϯ૚

    *$0ʹೃછΈͷ͋Δاۀ΍Ұൠ౤ࢿՈ΍ ػؔ౤ࢿՈͷרࠐΈૂ͍༏ઌ౓Λݕ౼ ɾԾ૝௨՟ۚ༥ۀք΁ͷਂ͍ཧղ ɾ౤ࢿՈऔҾॴɺۀ຿ఏܞઌͳͲωοτϫʔΫ ɾઓུίϯαϧςΟϯάͷέΠύϏϦςΟ ɾߴ͍ٕज़ྗ $0/'*%&/5*"-DPQZSJHIU˜CZ"OZ1BZJODBMMSJHIUTSFTFSWFE
  3. $0/'*%&/5*"-DPQZSJHIU˜CZ"OZ1BZJODBMMSJHIUTSFTFSWFE ICOコンサルティング事業について 事前準備 事前設計 実装 ICO実施 ⽬的・意義の 定義 調達額・ 計画検討

    既存株主への 説明・説得 スキーム決定 コイン機能・サー ビスとの融合決定 コイン実装 サ イ ト オ プ ン プ レ セ ル ク ラ ウ ド セ ル 社 内 側 の 動 き 社 外 協 議 取引所との協議 弁護⼠確認・協議 プロモーション・ 投資家との コミュニケーション キャンペーン 設計 オペレーション 設計 ホワイト ペーパー 作成 サイト 作成 セ カ ン ダ リ マ ケ ッ ト 開 設 1カ⽉〜 1〜2カ⽉ 2〜3カ⽉ :法務・会計 :技術・開発 :ビジネス・マーケ
  4. $0/'*%&/5*"-DPQZSJHIU˜CZ"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); }
  5. $0/'*%&/5*"-DPQZSJHIU˜CZ"OZ1BZJODBMMSJHIUTSFTFSWFE 典型的な(シンプルな)セールの流れ CONFIDENTIAL : copyright © by 2017 AnyPay inc.

    all rights reserved 1. セールの実施前に参加予定者に事前登録してもらい連絡⼿段を確保 (Email, Slack, Telegram, etc…) 2. セールの実施前に、参加予定者にETHを取引所アカウントではなく、⾃ 分で秘密鍵を管理しているアカウントに移動しておくよう伝達 3. セール開始直前に、参加予定者にETH振込先を伝達 4. ETHを振り込んでくれたアドレスに、ERC20準拠であるICOトークンを 送り返す 5. 終了⽇時または最⼤調達⾦額に達したら締め切り
  6. $0/'*%&/5*"-DPQZSJHIU˜CZ"OZ1BZJODBMMSJHIUTSFTFSWFE ケーススタディ ‒ Phase 1 ① このICOで得た資⾦で、サービスに使う⾞両を購⼊する ② このトークンを持っていることにより、購⼊された⾞両によって得られた利益のうち⼀ 部が分配される(株式型)。利益の分配はEthereumベースで毎⽉決まったタイミングで

    ⾏われる ③ トークンセールの参加にはKYC(本⼈確認) が要求される。また、許可されていないアド レスにtransferすることは許可しない ④ Phase 1のセールは2回⾏われる。それぞれ期間と上限額を事前に決定する。1回⽬は 2ヶ⽉後ぐらいを予定している。2回⽬は未定 ⑤ KYCは2度のPhase 1セールで共有される ⑥ 後々発⾏されるPhase 2のトークンに割引価格で変換できる ⑦ または、⾞両が償却されるまでトークンを持ち続けた場合、再売却価格の分配を受ける こともできる Phase 1
  7. $0/'*%&/5*"-DPQZSJHIU˜CZ"OZ1BZJODBMMSJHIUTSFTFSWFE ケーススタディ ‒ Phase 2 ① Phase 2のトークンは、このICO予定の会社以外にも、世界中のシェアリング サービスで利⽤可能なサービス型トークンとなっていく計画を持っている ②

    サービスのユーザは、このトークンを⽀払に利⽤することができる ③ シェアする側のユーザは、対価としてこのトークンを受取る ④ Phase 1とは違い、こちらのトークンは取引所への上場を予定している Phase 2
  8. $0/'*%&/5*"-DPQZSJHIU˜CZ"OZ1BZJODBMMSJHIUTSFTFSWFE Coin Vendor • Phase 1のコインをまとめ て”Private Coin” と便宜上呼ぶ •

    ユーザがこのコントラクトに ETHを送るとpayableな無名関 数()が呼ばれる • セールの期間やこれまでに販売 した(発⾏した)量、最⼤販売量、 販売単位などが定義されている • コインの実装コントラクトへの 参照を持つ • transferFundsはたまったETH を引き出す関数
  9. $0/'*%&/5*"-DPQZSJHIU˜CZ"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; }
  10. $0/'*%&/5*"-DPQZSJHIU˜CZ"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トーク ンに割引価格で交換できる)
  11. $0/'*%&/5*"-DPQZSJHIU˜CZ"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に委譲
  12. $0/'*%&/5*"-DPQZSJHIU˜CZ"OZ1BZJODBMMSJHIUTSFTFSWFE リリース⽅法 1. 全てのコントラクトをせっせとデプロイする 2. setImpl(address) auth public: bool などを実⾏して付け替えを⾏う

    3. KYC済みユーザの追加は impl.addApprovedAddress(address) データのコントラクト書き換えの場合は マイグレーションも頑張らないといけませんよね…… 正直Ethereumすごい。すごいけど
  13. $0/'*%&/5*"-DPQZSJHIU˜CZ"OZ1BZJODBMMSJHIUTSFTFSWFE ⼿段のために⽬的を⾒失わない ⼀番⼤事なことは • ◦ トークンの価値が上がり投資家もユーザもハッピー • ◦ サービスが使いやすくてユーザもハッピー •

    ◦ メンテが楽で開発者もハッピー • × 全部ブロックチェーンでやるとかっこいい ストレージが増える(RDB, NoSQL, ブロックチェーンetc)ごとに、 当然ながらメンテは⼤変。 Ethereumとプライベートな独⾃ブロックチェーンの併⽤も⼤変。 かっこよさとハッピー、両⽴したい、どうしよう…… えっ、もっと詳しく話を聞きたいって?