Contract Metadata

SolidityコンパイラはJSONファイル形式でコントラクトのメタデータを自動生成します。 このメタデータは現在のコントラクト情報を含みます。そして、このJSONファイルを使って、コンパイラバージョンやソースコード、ABIやNatSpec(Ethereum Natural Language Specification Format)のドキュメントなど、ソースコードを検証しコントラクトをより安全に利用するための情報を知ることができます。

EVMコンパイラはこのメタデータのSwarmハッシュを各コントラクトにおけるバイトコードの末尾に追加します。 これにより、中央集権的なデータプロバイダに頼ることなくファイルを認証された方法で取得することができます。

また、他人がメタデータファイルにアクセスするためにはSwarm(または類似サービス)上にそのファイルをアップロードしなければなりません。 このとき ContractName_meta.json と呼ばれるファイルを生成するには solc --metadata コマンドを使います。 このファイルにはソースコードのSwarmリファレンスが含まれています。そのため、すべてのソースファイルとメタデータファイルをアップロードする必要があります。

メタデータは次のようなフォーマットです。この下の例は人間が読みやすいように書かれています。 適切にフォーマット化されたメタデータは、引用符を正しく使い、空白を最小限におさえ、すべてのオブジェクトのキーを個々のフォーマットに当てはめるように使うべきです。 また、ここではコメントは何かしらの説明をする目的以外に使うことはできません。

{
  // Required: メタデータフォーマットのバージョン。
  version: "1",
  // Required: ソースコード言語。基本的には特定のサブバージョンを指定します。
  language: "Solidity",
  // Required: コンパイラについての詳細。内容は使用する言語に依存します。
  compiler: {
    // Required for Solidity: コンパイラのバージョン。
    version: "0.4.6+commit.2dabbdf0.Emscripten.clang",
    // Optional: 出力を生成するコンパイラバイナリのハッシュ。
    keccak256: "0x123..."
  },
  // Required: コンパイルソースファイル/ユニット。ここではキーはファイルの名前を指します。
  sources:
  {
    "myFile.sol": {
      // Required: ソースファイルのkeccak256ハッシュ
      "keccak256": "0x123...",
      // Required ("content"を使用していない場合):
      // ソートされたソースファイルに対応するURL。
      // プロトコルは多少なりとも任意ですが、Swarm URLをおすすめします。
      "urls": [ "bzzr://56ab..." ]
    },
    "mortal": {
      // Required: ソースファイルのkeccak256ハッシュ
      "keccak256": "0x234...",
      // Required ("url"を使用していない場合): 正確なソースファイルの内容
      "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
    }
  },
  // Required: コンパイラ設定
  settings:
  {
    // Required for Solidity: remappingsのソート済みリスト
    remappings: [ ":g/dir" ],
    // Optional: オプティマイザー設定 (デフォルト値はfalse)
    optimizer: {
      enabled: true,
      runs: 500
    },
    // Required for Solidity: コントラクト名とファイル、またはこのメタデータが作成されるライブラリ名。
    compilationTarget: {
      "myFile.sol": "MyContract"
    },
    // Required for Solidity: 使われているライブラリのアドレス
    libraries: {
      "MyLib": "0x123123..."
    }
  },
  // Required: コントラクト生成に関する情報
  output:
  {
    // Required: コントラクトのABI定義
    abi: [ ... ],
    // Required: コントラクトのNatSpecユーザードキュメント
    userdoc: [ ... ],
    // Required: コントラクトのNatSpec開発者ドキュメント
    devdoc: [ ... ],
  }
}

警告

結果として生じるコントラクトのバイトコードにはメタデータのハッシュが含まれているため、メタデータのどんな些細な変更であってもバイトコードが変更されることになります。バイトコードはファイル名やパスに対する変更も含んでおり、また、メタデータはすべてのソースファイルのハッシュを含むため、たとえホワイトスペースを1つ付け加えるなどの変更においても結果として別々のメタデータとバイトコードが生成されることになります。

注釈

上記のABIの定義には決まった順序はありません。コンパイラのバージョンによって変わる可能性があります。

Encoding of the Metadata Hash in the Bytecode

将来的にメタデータファイルを取得する他の方法がサポートされる可能性があるため、 {"bzzr0": <Swarm hash>} のマッピングは CBOR でエンコードされ保存されます。このエンコーディングの始点を見つけることは簡単ではありません。そのため、そのエンコーディング長は2バイトのビッグエンディアンで追加されます。Solidityコンパイラの現在のバージョンでは、デプロイされたバイトコードの末尾まで以下のように追加します:

0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29

このデータを取得するために、デプロイされたバイトコードの末尾をチェックすることができます。 そのパターンに一致させ、Swarmハッシュを使用してファイルを取得します。

注釈

Solidityコンパイラは現在メタデータの"swarm version 0"ハッシュを使用しています。 しかし、将来的にこれは変更されるため 0xa1 0x65 'b' 'z' 'z' 'r' '0' から始まるシーケンスを完全には信用しないでください。私たちは他にも このCBORストラクチャに他のデータを追加するでしょう。そのため、ベストな選択肢は適切なCBORパーサーを使用することです。

Usage for Automatic Interface Generation and NatSpec

次の方法でメタデータは使用されます: コントラクトと関わるコンポーネント(e.g. Mistやその他のウォレット)がコントラクトコードを取得します。そして、Swarmハッシュを取得します。ファイルは上記のようにJSON形式でデコードされています。 その後、コンポーネントはABIをもとにコントラクトにおける基本的なユーザーインターフェースを自動生成します。

さらに、ウォレットはNatSpecユーザードキュメントを利用して、ユーザーがコントラクトと対話するときはいつでもトランザクション署名の許可を要求するとともに、確認メッセージをユーザーに表示することができます。

Ethereum Natural Specification (NatSpec)に関する詳しい情報は ここ で参照することができます。

Usage for Source Code Verification

コンパイル検証のために、メタデータファイル内のリンクを通じてSwarmからソースを取得することができます。正しいバージョンのコンパイラ("official"なコンパイラとして確認されているもの)が指定の設定のもと呼び出されます。そして、結果として得られるバイトコードはトランザクション生成のデータや CREATE オペコードのデータなどと比べられます。ここでハッシュはバイトコードの一部であるため、自動的にメタデータを検証します。 残りのデータはコンストラクタにおける入力データに相当します。これはインタフェースに従ってデコードされ、ユーザに提示されるべきです。