アルゴリズムとかオーダーとか

仕事で勉強したことなどをまとめてます

ERC223Tokenを試してみた

とあるEthereumグループでちょっと話題になったERC223Tokenを実際に試してみました。
ERC223Tokenについてはこちらの方がわかりやすく説明されているので参照ください。
qiita.com

ERC223のリポジトリはこちら。
GitHub - Dexaran/ERC223-token-standard


ERC223Token実行時に起きるエラーの解消法

こんなエラーが出ます。

     Uncaught Error: Number can only safely store up to 53 bits

ERC223_interface.solのevent Transferの定義の部分の最後のパラメータについているindexedがついているのが問題なので削除したら治ります。

event Transfer(address indexed from, address indexed to, uint value, bytes indexed data);
                                                                                                                                 ^^^^^^^ ここを削除


今回お試しのために作ったテストコード

contract('ERC223TokenTest', function (accounts) {
  let token;
  beforeEach(async () => {
    token = await SampleToken.new();
  })
  it("allow transfer to implemented contract ", async () => {
    const impl = await ReceiverImpl.new();
    const receipt = await token.transfer(impl.address, 20)
    const balance = await token.balanceOf(impl.address)
    assert.equal(20, balance.toNumber())
  })

  it("not allow transfer to no impl contract ", async () => {
    const notImpl = await ReceiverNotImpl.new();
    try {
      const receipt2 = await token.transfer(notImpl.address, 10)
      assert.fail()
    } catch (e) {
      assert.equal("VM Exception while processing transaction: revert", e.message)
    }
  })

  it("allow transfer to has fallback contract ", async () => {
    const hasFallback = await ReceiverHasFallback.new();

    // fallbackあれば呼べちゃうけどまぁこれは仕方ないよね。。。
    const receipt3 = await token.transfer(hasFallback.address, 5)
    const balance3 = await token.balanceOf(hasFallback.address)
    assert.equal(5, balance3.toNumber())
  })

  it("allow transfer to other EOA ", async () => {
    // もちろん他のEOAにも送れる
    const receipt4 = await token.transfer(accounts[1], 30)
    const balance4 = await token.balanceOf(accounts[1])
    assert.equal(30, balance4.toNumber())
  })
})

内容は見て分かる通り、ERC223ReceivingContractを実装したContractと実装してないContractに対してそれぞれtokenを送信したらどうなるかのテストです。
ERC223ReceivingContractを実装してないContractはもちろんERC223の定義通りにエラーとなってtokenの送信ができなくなります。これでContractにtokenが吸い込まれてしまうのを防げます。

ただし、Solidityの言語仕様上fallback functionを持つContractの場合は今まで通り送信できてしまい、意図しないtokenの消失が起きてしまいます。これはまぁ言語仕様的にどうしようもないのでsolidity側で対応してもらうしかないのかなぁ?と思います。


作成したtruffleのprojectはこちらです。
github.com


追記

ちょっと勘違いしてた。

The most important here is a call of tokenFallback when performing a transaction to a contract.

とあるように、重要なのはtokeFallbackを呼び出すことであり、受け取り側のContractが明示的に通知を受けてそれの結果としてどう、動作するのか?を決定できることが重要なんですね。
ERC20ではContract addressに対して一方的にtokenが転送されてしまいそれがContract側には一切通知されないためどうしようもなかったのをERC223では通知がいくように仕様として縛っていると。fallback関数の定義によって意図しないetherの送金を拒否したりできるのと同じですね。