EthereumのERC223トークンとERC20トークンの欠点について

#はじめに
2015年11月19日に、利便性を高める目的で基準を統一化し、スマートコントラクトの共通規格として「ERC20」が誕生しました。しかしERC20には色々な欠点がありその改善版として、2017年3月5日にERC223が誕生しました。
詳しいERC20についての記事は[こちら](https://qiita.com/tubaki_k05/items/dc57c53a56b6e3a8a3d1)。
そのERC20の欠点とは送金先をユーザーアドレスではなく、誤ってコントラクトアドレスを指定した場合に起こる誤送金問題でした。これによってトークンは消失となってしまうのですが、 ERC223では新たに追加された関数によりこの問題を解決しました。

#ERC20トークン標準問題
ERC20トークンは２つの問題を抱えていて、一つは**通知方法に関する定義がされてないこと**と、もう一つは**ERC20の送金方法が2通りあるのが原因で、誤ったアドレスに送信した場合、トークンが失われてしまうこと**です。
一つめの問題である通知方法が未定義とは、送金した際に相手に通知が行かずにトランザクションが発生し、取引が成立してしまうことです。
わかりやすく次のような例のユースケースを考える。


アリスには10個のERC20トークンがあり、アリスはそのうち3つのトークンをボブに送信したいと考えている。
アリスの残高には複数のトークンを持っているように見えるが、実際は単なる数字に過ぎず、送受信のやり取りは単純に互いの残高を減らしたり、増やしたりしている。
 アリスがアリスの残高を3つ減らし、ボブの残高を3つ増やすトランザクションを作ります。このトランザクションがマイニングされると、トークンの送信がされます。
しかし、この時ボブはこのトランザクションが発生したことをボブは知りません。ボブは自分のアカウントを確認し初めて増加したことを知ります。**このようにトークンを送信しても受信コントラクトへの通知がないため届いたかどうかわからないのです**。通知するための代替方法はあるのですが、gasの無駄な消費と必要のないトランザクションが発生するため、非効率な規格です。
次に二つ目の問題である誤送金問題について、ERC20トークには二通りあることは話しましたが、それぞれはどのような使われ方をするのでしょうか。
まず、transfer関数による指定したユーザーアドレスに送信する方法です。これは単純にユーザーとユーザーが直接トークンの送受信するための関数です。もう一方でapprove,transferFrom関数によるスマートコントラクトアドレスに送信する方法がある。この方法ではapprove関数によりトークンの送金を承認し、transferFrom関数でコントラクトアドレスに送金します。また、この送金方法はtransfer関数とは違い、トランザクションのステップ数を多く必要とするので無駄なgasが発生します。
というように２つの送金方法があり、それらは受信アドレスがユーザーかコントラクトアドレスかによって使い分けます。しかし、誤ってtransfer関数でスマートコントラクトにトークンの送金を行った場合、一つ目の問題でも行ったように、**受け取った側への通知がないため、拒否する必要があるトランザクションを拒否することが不可能であり、このトークンはコントラクト内でスタックしてしまう。よってトークンの消失へとなるのです**。これら二つの問題を解決したのがERC20の改良版とされるERC223トークンです。
参考ページ: [https://docs.google.com/document/d/1Feh5sP6oQL1-1NHi-X1dbgT3ch2WdhbXRevDN681Jv4/edit](https://docs.google.com/document/d/1Feh5sP6oQL1-1NHi-X1dbgT3ch2WdhbXRevDN681Jv4/edit)

#ERC223の関数とイベント
 ERC223はERC20の解決策として、送ったトークン内容を確認して、誤っていれば送り手にトークンを返却するというtokenFallback関数が定義されました。また、ERC223で送金方法を一つにし,approve関数やtransfer関数を用いた送金方法による無駄なgasを消費しないで、少ない手数料での送金を可能にしました。
##主なERC223の関数とイベント

| 関数名                                                     |       説明 |
|:----------------------------------------------------------|:------------------|
| totalSupply()                                             |トークンの合計供給量を返す           |
| balanceOf(address _owner)                                 |_ownerアカウントの残高を返す             |
| transfer(address _to, uint _value)                     |  指定されたaddressに指定された量のトークンを転送する      | 
|transfer(address, _to, uint _value, bytes _data)|transfer関数にバイト型のdataが加わり、トークンの転送する。|
|tokenFallback(address, _from, uint _value, bytes _data)|トークンコントラクトから呼び出されるトークン転送を処理する関数            |  

ERC223にはtransfer関数が２つあることがわかります。なぜ２つあるのかというと、ERC20のtransfer関数にはbytesパラメーターがないため、互換性の理由で必要なのです。
もう一方のtransfer関数は新たにバイト型のdataが加わり、このdataはトランザクションに含まれ、ブロックチェーン上に保存されます。また、トークンの転送の際は常に呼び出され、_toがコントラクトアドレスだった場合、tokenFallback関数を呼び出し、トークンの返却を行います。
参考ページ:[https://github.com/ethereum/EIPs/issues/223](https://github.com/ethereum/EIPs/issues/223)

##イベント

| 関数名                                                     |       説明 |
|:----------------------------------------------------------|:------------------|
|Transfer(address indexed _from, address indexed _to, uint256 _value, bytes _data)                      |トークンが転送されたときにトリガーする|

これはERC20のイベントと同じような感じです。
#ERC223の特徴
ERC223の特徴をまとめると

- tokenFallbackを導入するこのにより誤送信によるトークンの消失を防ぐ
- transfer関数の一本化により、無駄なgasの浪費と、トランザクションの増加を防ぎ、より簡単でシンプルなトークン転送が可能
- transferやtokenFallback関数にパラメータdataを追加することによりトランザクションにある情報を添付することができる
- 通知なしに一方的なトークンの転送を無くし、tokenFallbackの導入により受け取り側へ通知がいくような仕様になった

この4つが大きな改善点なのかなと思いました。

#まとめ
今回、前回まとめてたERC20規格の欠点をより具体的に紹介しながら ERC223トークンの特徴をまとめました。この記事を通してトークンの理解と、どうして色々なトークンが存在するの？などの疑問が解消されればなと思います。次回ERC20をさらに別方向に発展したERC721についてまとめたいなと思います。また何か訂正箇所がございましたらコメントよろしくお願いします。