優れたスマートコントラクトを設計するには?

~システムモデラー社長の万事よろずの諸々~

スマートコントラクトの設計に関して、技術的な側面で考慮すべきポイントを上げるとしたら、いくつも重要な点があります。 今回は、Ethereumを題材に、細かなテクニックよりも設計の考え方に着目してナレッジをシェアします。

セキュリティが担保されているか?

例えば、EthereumのSolidityではオーバーフローやアンダーフローによる致命的な問題が発生しうる。 Solidityでは負の整数をコード内で扱うことはできず、0 – 1 の計算結果がマイナス1にならない。このような計算により意図せぬ結果が生じることを避けるために、OpenZepplin が公開している SafeMath を使用することが望ましい。

delegatecallの使用方法を間違えると、コントラクトのオーナー権限の乗っ取りなどのように致命的な問題が発生しかねない。 delegatecall は、参照元のコントラクトから参照先のコントラクトのファンクションを呼ぶが、ストレージは参照元のコントラクトが更新されるという特別な方式で処理が実行される。この呼び出し方式はライブラリのようにストレージを持たない機能の呼び出しに使われることがふさわしいが、通常のコントラクトの呼び出しに使うにはリスクが高い。

  • このような問題をアプリケーション設計者が全て設計時に潰しこむことは現実的には困難なので、Mythrilなどのコントラクトセキュリティ診断ツールを利用することでソースコードのセキュリティリスクを低減することができます。

処理は軽いか?

Ethreumのパブリックネットワークの場合はガス代という分かりやすい形でコストが可視化されるが、プライベートネットワークにおいてもコントラクトの処理が重いと、トランザクション処理速度にダイレクトに影響があることを忘れてはならない。単純なデータ記録とERC20型トークンの送金相当の計算を行うコントラクトでは、トランザクション処理速度で数割の速度の違いがあることを弊社の研究結果で確認している。

  • ブロックチェーンは改ざんを許さないことが本来の機能であり、例えば必ずしもブロックチェーンで実行する必要のない複雑な処理はオフチェーンで実行するように、分別して設計することが賢明な判断です。

コントラクトの可読性は高いか、メンテナンスしやすいか?

スマートコントラクトを実装する際に、OpenZepplinのOSSのソースコードをまるごとコピー&インポートして動作させるのであれば、それはある意味最も信頼性が高いソースコードの一つになるだろう。しかし、アプリケーションの開発においては、これから構築すべきアプリケーションに必要なソースコード以外は実装しないことが望ましい。OSSの一部のコードを利用したいがために本当は必要のないソースコードをまるごと実装したりすれば、初期のシステム構築者以外には極めて難解なシステムになってしまう。

SEの間では良く知られていることであるが、RDBMSのテーブルを正規化することは、データの冗長性を排除できて良いことだが、一方で正規化によってテーブルの数が増えると、テーブル同士の結合が増えるためにデータ調査の難易度があがってしまう。これと似たようなことが、スマートコントラクトの体系にも言える。インタフェースとコントラクトとイベント処理をそれぞれ別々に定義することは一見良いことに思えるが、運用フェーズの人員交代を考えると、あまりにコントラクトのファイル数を多くしてしまうと好ましくない結果を生む可能性があるので注意が必要である。

  • 世界のトレンドやベストプラクティスに則っとっていることは良いことですが、それで十分というわけではないことも頭の隅にいれておくと良いでしょう。 アプリケーション開発とその運用は一人の人間が行うものではないので、 実際に将来現場にアサインされるであろう技術者の属性や習熟度を加味して、人が理解しやすい設計をすることも重要なポイントです。

構造はシンプルか?

例えば、「アップグレードが可能なスマートコントラクト」と聞くと、一見すれば手放しで評価して良さそうに思えるが、実際には、そのアプリケーションにとって本当にアップグレード可能なコントラクトが必要なのかを検討した方が良い。例えば、スマートコントラクトには「枯れた処理(過去に十分な検証が済んだ処理)」を実装する方針として、将来の変更が予期されている処理は暫定的にオフチェーンで実装し、結果の保存処理のみをオンチェーンに実装するという選択肢もありえる。
アップグレード可能なコントラクトにすることで、例えばプロキシ・コントラクトが delegatecall でロジックコントラクトを呼ぶような実装方式を採用すれば、アプリケーション開発者の学習負荷は単純なスマートコントラクトのそれよりも高くなるし、アップグレードの運用・ガバナンスを設計する必要もある。

  • アプリケーションは原則シンプルな構成にすべきです。複雑な構成にせざるを得ないのは、ビジネス要件に基づいてそれ以外のワークアラウンドがない時に限られます。

今日はこのあたりまでにしておきましょう。