CTOの西出です。 引き続きPolkadot/Substrateのリサーチ中です。新しい技術を触るときはワクワクしますね(後編をおまたせしてすみません)
Substrateで実装するサンプルのネタとして、過去にSolidityで作ったアプリを眺めていたところ、ふと思い出したトピックがあるので書き起こすことにしました。
表題に対していきなり真逆の結論からのべてしまいますが、ERC20という規格そのものは非常に汎用性が高く、スマートコントラクトを用いてERCトークン間やネイティブのイーサとの間で取引き・価値の交換を完結できるという点においては素晴らしい仕組みです。万能ではないのは、正確には現状のウォレットエコシステムということになります。
以前開発したコントラクトにおいて、満たしたかった要件/うち、満たせなかった要件について理由とともにご紹介します。
前提
- 執筆時点の著者の知識の範囲から導いた結論です。考察不足・調査不足ということは大いに有り得るため、誤っているという指摘があればぜひ頂きたいです
- ここで扱うユーザー資産は全てERC20トークンもしくはネイティブイーサで完結しており、かつユーザー自身のウォレットに保有されている/させるものを対象とします(Non-custody)
- 法的なトピックはここでは扱いません
満たしたかった要件
- フロントエンドを除き、ロジックは全てオンチェーン上で処理される(=アプリケーションサーバーを持たない)
- 各手続き(※)の決済は、イーサの汎用ウォレット(例えばMetaMask)で完結させる
- 各手続きは、ウォレットのトランザクション
1回
で行う
※ここでいう「手続き」とは、取り引きであったり、ゲームで何かを実行するといったことを指します。前提に従い、例えばユーザー間でERC20とネイティブイーサを交換する(いわゆるDEX)ことや、ゲーム内でとあるERC20(例えばスタミナ)を消費してERC721(モンスターの討伐戦利品)を取得する、というような不可分(Atomicであるべき)な一連の処理です。
満たせた要件
以下のユースケースに対しては上に挙げた要件3つを同時に満たすことができました。
- ユーザーがネイティブイーサを使用して、ERCトークンを取得する
これはよく例えに使われる「自動販売機」の実現を意味します。ただし、得られるトークンの種類や数量の予測は、現行のウォレットの機能では行えないため、希望する条件通りのものが得られるかはコントラクトの中身を読み解かないと判断がつきません。自動販売機がバグってお金を入れたのにジュースが出てこない、なんて事が起こらないかを判断するのも重要である一方でそう容易では無いのですが、今回の論点からは外れるためそれについては議論しません。
満たせなかった要件
以下のユースケースに対しては上に挙げた要件3つを同時に満たすことができませんでした。
これは「両替機」、もしくは「自動買い取り機」をイメージされると理解しやすいと思います。ERCトークンを送付する機能がウォレットに搭載されているにもかかわらず、送付した結果何かを受け取ることは同時には行なえないのです。
なぜ満たせたのか?満たせなかったのか?
なぜ「自動販売機」は実現できたのか?から説明します。
これは、Solidityのコントラクト実行がすべてメソッド呼び出しを起点として行われることが原因です。コントラクトのアドレスにイーサを送付すれば無名メソッドが暗黙に呼び出され、誰がいくら送付したかコントラクトから判断できるためその人に対価となる資産を移転すればトランザクションは完結します。売り物が一つしかない場合はこれで問題ありません。売り物が複数ある場合は、パラメーターつきのメソッド呼び出しにイーサを添付するような形で呼び出すことができます。いずれのケースでも、お釣りがある場合は元のアドレスに余剰イーサを送付すればよいわけです。また、送付されたイーサが商品の最低単価に満たない場合はメソッド呼び出しを失敗することで無かったことにできるでしょう(ガス代は消費されますが)
一方、「両替機」ないし「自動買い取り機」はなぜ実現できなかったのでしょうか?
これは、現在のERC20の仕組みに起因します。コントラクトにトークンを送付して対価に何かを受け取ろうとした場合、呼び出さなければいけないコントラクトが少なくとも2つあるのです。すなわち、ERC20のトークンのコントラクトと、「両替機/自動買い取り機」のコントラクトです。ネイティブイーサのようにトークンを「添付」して両替機/自動買い取り機コントラクトを呼び出すことはできず、必ず2回に分けて呼び出さないといけないのです。このせいで、以下の要件を満たすことができません。
- 各手続きは、ウォレットのトランザクション
1回
で行う
これはUX上、極めて厄介なことです。どうあっても最低2回承認をしないといけないのです。事前にトークンを預かっておき、2回の承認を1度に代行してくれるようなコントラクトを作ることはできますが、これは前提の Non-custody
に反します。
今後どうなれば解決できるのか?
この要件を本質的に解決できる方法として思いついたのは以下です。
- ERC20にありがちな2回のコントラクト呼び出し
approve / call
の組み合わせを、ウォレットが一つに取りまとめてみせることでUI側でサポートする - ERC20を拡張し、使用されるコントラクト側の呼び出しをまとめて行うインターフェイスを定義する
このことから、表題のERC20はユーザー体験と言う意味で万能ではない、と考えました。
その後の調査
ERC20を使った試行錯誤をしていたのは2018/3ぐらいのことです。その後調べてみたところ、実は拡張した規格 ERC223
が2017/3にはすでに提案されており、さらに2017/7には ERC677
が提案されていたことがわかりました。実際、CoinMarketCapの上位にくる時価総額のトークンではこれらの規格で実装されているものがすでにあります。あとは、これらの規格が最新のウォレットでUI的に十分サポートされていれば根本的に解決できそうです。ウォレット側の対応状況についても今後調査してみたいと思いますが、 ERC20
を採択する際には狭義の ERC20
で実装してしまうと実利用する際に大きな支障が出る可能性があるため十分な検討が必要であると結論付けます。 ERC223
や ERC677
も ERC20
としてのインターフェイスは備えているため、 狭義の(実装としての)ERC20
は万能ではないが 広義の(インターフェイスとしての)ERC20
は万能といってしまっていいかもしれません。