Ethereumのユニバーサルスマートマルチ署名契約

数日前、 BitClaveで Parity Technologiesの マルチ署名ウォレットに関する最近の事件について読み、スマート契約のコードを詳しく調べることにしました。 最新の Zeppelin Solutionsブログ投稿では、技術的な観点からインシデントについて詳しく説明しているため、この記事ではスマートコントラクトの設計の原則にもっと焦点を当てたいと思います。



イーサリアムウォレット



略語SOLIDには、いくつかの有名なOOP原則が含まれています。





これらの原則の使用には多くの支持者と反対者がいますが、 Solidity言語の多くのライブラリを見て、 Zeppelin Solutionsのアプローチが最も便利で安全であるという結論に達しました。 OpenZeppelin.orgライブラリは、 Solidity言語の多重継承を使用して、より洗練されたmixin動作を実現するためにコンパイルできる多くの小さなスマートコントラクトを提供します。 最終的なスマートコントラクトの責任を、 1つの責任を持つ多数のスマートコントラクトに分解する必要があります。各スマートコントラクトは、単一の目的を果たす必要があります。 さらに、 Zeppelin Solutionsが提供するようなライブラリで、必要な契約の一部を見つけることができます。 とりわけ、各契約を個別にテストすることもできます。



これらの原則に基づいて、トークンの販売に関するスマートコントラクトgithub.com/bitclave/crowdsaleを開発しました 。 リポジトリでは、スマートコントラクトBonusCrowdsale



およびTokensCappedCrowdsale



を見ることができます。これらは、投資の時間と量に応じてボーナスメンバーを処理したり、販売されたトークンの総数を制御したりするなど、販売の側面を処理するように設計されています。 私たちのコードでは、スマートコントラクトのセキュリティコントラクト監査人からかなり賞賛の返事を受け取りました。



「既存のOpenZeppelinライブラリ契約を再利用するすばらしい仕事です!」 追加のコントラクトは、非常に思慮深く設計されており、このフレームワークの優れた拡張のように見えます」(「既存のOpenZeppelinライブラリを再利用するすばらしい作業です。追加のコントラクトは、非常に思慮深く設計され、フレームワークの優れた拡張です」)-Zeppelin Solutions 完全な結論はここにあります


これらの原則を実際にうまく適用するには、多重継承がどのように機能するかを明確に理解する必要があります。 実際、Solidityコンパイラーは、多重継承を単一継承に変換します。 したがって、コンパイル後、各スマートコントラクトには親が1つだけ存在し、 super



キーワードを介してアクセスできます。 おそらく次の例は、C3多重継承の線形化がどのように機能するかを理解するのにさらに役立つでしょう。



 contract A { } contract B { } contract C is A, B { } // C(A,B) = ABC contract D is C, A { } // D(C(A,B),A) = D(ABC,A) = ABCAD !!! Error !!! contract E is A, C { } // E(A,C(A,B)) = E(A,ABC) = ABCE
      
      





問題は、 C



B



オーバーライドするため、スマートコントラクトA



C



オーバーライドできないことです。



 TypeError: Linearization of inheritance graph impossible contract D is C, A { } ^ — — — — — — — — — — ^ Compiliation failed. See above.
      
      





また、子クラスを継承するプロセスで、コントラクトの直接継承を変換できることを考慮する必要があります。 次の例でコントラクトW



どのようにコンパイルされ、その親コン​​トラクトZ



X



から直接継承するのではなく、コントラクトY



継承者( X



継承者)になることに注意してください。



 contract X {} contract Y is X {} // Y(X) = XY contract Z is X {} // Z(X) = XZ contract W is Y, Z {} // W(Y(X),Z(X)) = W(XY, XZ) = XYZW
      
      





マルチ署名ウォレットParity Technologiesのスマートコントラクトに戻ると、完全に分解されていないことがわかりました。 私たちが気づいた唯一のアーキテクチャソリューション:契約のダウンロードのコストを削減するために、すべてのウォレットの共通コードを単一のライブラリに転送します。 ちなみに、ランダムな開発者がすべてのウォレットの動作を混乱させ、共通のコードで単一のライブラリを破壊できるようにしたのはこの機能でした。 リソースの複数の所有権のトピックについて考えOpenZeppelinライブラリの方法でこの問題の解決策を準備しました。 Multiownable.sol契約をご紹介します。これにより、契約にマルチ署名機能を簡単に追加できます。 その使用は、通常のOwnable



コントラクトを使用するのと同じくらい簡単です-あなたはそれから継承し、 onlyAnyOwner



onlyManyOwners



を必要な関数に追加するだけです:



 contract SimplestMultiWallet is Multiownable { bool avoidReentrancy = false; function () payable { } function transferTo(address to, uint256 amount) onlyManyOwners { require(!avoidReentrancy); avoidReentrancy = true; to.transfer(amount); avoidReentrancy = false; } }
      
      





スマートコントラクトのtransferTo



メソッドは、すべてのウォレットの所有者が同じ引数で呼び出した後にのみ呼び出されます。 信じられないかもしれませんが、これはイーサ通貨の最もシンプルなマルチ署名ウォレットの完全なコードです。 さらに、ERC20仕様と互換性のあるトークンのサポートを実装できます。ここにメソッドがあります。



 function transferTokens(address token, address to, uint256 amount) onlyManyOwners { require(!avoidReentrancy); avoidReentrancy = true; ERC20(token).transfer(to, amount); avoidReentrancy = false; }
      
      





コミュニティのフィードバックをお待ちしています: github.com/bitclave/Multiownable



PSライブラリの最新の変更を考慮に入れて例を更新しました-受信者がtransfer



方法を持つ契約の場合、ネストされた呼び出しに対する保護を追加しました。



All Articles