[ERC5289] スマートコントラクトに法的拘束力をもたす仕組みを理解しよう！

# はじめに

初めまして。
**CryptoGames**というブロックチェーンゲーム企業でエンジニアをしている **cardene（かるでね）** です！
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームは**クリプトスペルズ**というブロックチェーンゲームです。

https://cryptospells.jp/

今回は、スマートコントラクトに法的拘束力をもたらす仕組みを提案している規格である**ERC5289**についてまとめていきます！

:::note info
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

https://eips.ethereum.org/EIPS/eip-5289

:::note warn
**5289**は現在（2024年1月8日）では「**Review**」段階です。
:::

他にも様々なEIPについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

# 概要

このEIP（イーサリアム改善提案）は、スマートコントラクトが現状では法的に拘束力を持たないという大きな問題を解決しようとしています。
この提案は、スマートコントラクトに法的文書へのIPFSリンクを組み込むことで、コントラクトの利用者が関連する法的文書と直接的な関係を持つことを保証します。
これにより、コントラクトが法的に拘束力を持つようになる可能性があります。

ただし、この提案を作成した筆者は法律の専門家ではなく、この文書は法的な助言として意図されていません。
提案の目的は、実際の法的文書とスマートコントラクトの実行をリンクさせ、利用者が法的文書にアクセスし、理解できるようにすることです。
これにより、コントラクトの透明性と信頼性が向上し、スマートコントラクトのリアルワールドでの応用範囲が広がることが期待されます。
ユーザー間での明確な合意と責任の所在を確立することで、コントラクトの実用性と安全性が向上すると考えられます。

# 動機

NFTはしばしば、特定の作品の著作権を保持し、証明する手段として紹介されます。
しかし、実際には、これが実現している例はほとんどありません。
大多数の場合で、NFTは法的に拘束力を持つものではなく、稀に法的な効力を持つケースがあるとしても、そのNFTは単に初期保持者が作品を利用するための限定的なライセンスを提供するに過ぎません。
つまり、初期保持者は作品を利用する権利を得ることができますが、NFTが転売された場合、その後の保持者にはその作品を利用するライセンスは提供されません。
このように、NFTが提供する「**権利**」は非常に限定的であり、多くの場合、著作権の保持や証明とはかけ離れています。

# 仕様

## 法的契約ライブラリ・インターフェース

```javascript
/// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

import "./IERC165.sol";

interface IERC5289Library is IERC165 {
    /// @notice Emitted when signDocument is called
    event DocumentSigned(address indexed signer, uint16 indexed documentId);
    
    /// @notice An immutable link to the legal document (RECOMMENDED to be hosted on IPFS). This MUST use a common file format, such as PDF, HTML, TeX, or Markdown.
    function legalDocument(uint16 documentId) external view returns (string memory);
    
    /// @notice Returns whether or not the given user signed the document.
    function documentSigned(address user, uint16 documentId) external view returns (bool signed);

    /// @notice Returns when the the given user signed the document.
    /// @dev If the user has not signed the document, the timestamp may be anything.
    function documentSignedAt(address user, uint16 documentId) external view returns (uint64 timestamp);

    /// @notice Sign a document
    /// @dev This MUST be validated by the smart contract. This MUST emit DocumentSigned or throw.
    function signDocument(address signer, uint16 documentId) external;
}
```

上記のコードは、スマートコントラクトを通じて法的文書に対する操作を定義するためのインターフェースである`IERC5289Library`です。
このインターフェースは、**ERC165**に準拠しており、法的文書の管理と署名を行うための機能を提供します。

:::note info
**ERC165**については以下の記事を参考にしてください。
:::

https://qiita.com/cardene/items/541184977a5cba51b759

- `DocumentSigned`イベントは、`signDocument`関数が呼ばれたときに発行され、署名者のアドレスと文書IDを示します。

- `legalDocument`関数は、指定された文書IDに関連する法的文書への不変リンク（IPFS上にホストされることが推奨されます）を返します。
    - このリンクは、PDF、HTML、TeX、Markdownなどの一般的なファイル形式を使用する必要があります。

- `documentSigned`関数は、指定されたユーザーが特定の文書に署名したかどうかを返します。

- `documentSignedAt`関数は、指定されたユーザーが文書に署名した時刻を返します。
    - ユーザーが文書に署名していない場合、タイムスタンプは任意の値になる可能性があります。

- `signDocument`関数は、ユーザーが文書に署名するためのもので、スマートコントラクトによって検証される必要があります。
    - この関数は`DocumentSigned`イベントを発行するか、例外を投げる必要があります。

このインターフェースは、スマートコントラクトを利用して法的文書の確認と署名プロセスを自動化し、透明性と信頼性を高めることを目的としています。

---

### `legalDocument`

```javascript
function legalDocument(uint16 documentId) external view returns (string memory);
```

**概要**

特定の文書IDに紐づく法的文書への不変リンクを提供する関数。

**詳細**

この関数は、文書IDを指定することで、対応する法的文書へのリンクを返します。
IPFSでホストされることが推奨されており、PDF、HTML、TeX、Markdownなどの一般的なファイル形式を使用する必要があります。

**引数**

- `documentId`
	- 指定したい文書のID。

**戻り値**

- `string memory`
	- 指定された文書へのリンク。

---

### `documentSigned`

```javascript
function documentSigned(address user, uint16 documentId) external view returns (bool signed);
```

**概要**

指定されたユーザーが特定の文書に署名したかどうかを確認する関数。

**詳細**

この関数は、ユーザーのアドレスと文書IDを入力として受け取り、そのユーザーが指定された文書に署名したかどうかの真偽値を返します。

**引数**

- `user`
	- 確認したいユーザーのアドレス。
- `documentId`
	- 確認したい文書のID。

**戻り値**

- `bool signed`
	- ユーザーが文書に署名したかどうか。

---

### `documentSignedAt`

```javascript
function documentSignedAt(address user, uint16 documentId) external view returns (uint64 timestamp);
```

**概要**

指定されたユーザーが特定の文書に署名した時刻を返す関数。

**詳細**

ユーザーのアドレスと文書IDを引数として受け取り、ユーザーが文書に署名したタイムスタンプを返します。
ユーザーが文書に署名していない場合、タイムスタンプは任意の値となる可能性があります。

**引数**

- `user`
	- 確認したいユーザーのアドレス。
- `documentId`
	- 確認したい文書のID。

**戻り値**

- `uint64 timestamp`
	- ユーザーが文書に署名した時刻。

---

### `signDocument`

```javascript
function signDocument(address signer, uint16 documentId) external;
```

**概要**

ユーザーが特定の文書に署名するための関数。

**詳細**

この関数は、スマートコントラクトによって検証され、`DocumentSigned`イベントを発行するか、例外を投げる必要があります。
署名するユーザーのアドレスと文書IDを引数として受け取ります。

**引数**

- `signer`
	- 署名するユーザーのアドレス。
- `documentId`
	- 署名する文書のID。

**戻り値**

この関数は戻り値を持ちませんが、正常に完了するとDocumentSignedイベントが発行されます。

---

## 署名の依頼

特定の文書への署名を要求するには、**ERC5568**シグナルを使ってリバートするプロセスが必要です。
このプロセスは、ABIエンコードされた（アドレス、uint16）のペアという形式の指示データを使用します。
このペアの中で、アドレスはライブラリのアドレスを指し、`uint16`は文書の`documentId`を指します。

```javascript
throw WalletSignal24(0, 5289, abi.encode(0xcbd99eb81b2d8ca256bb6a5b0ef7db86489778a7, 12345));
```

例えば、`throw WalletSignal24(0, 5289, abi.encode(0xcbd99eb81b2d8ca256bb6a5b0ef7db86489778a7, 12345));`というコードは、アドレス`0xcbd99eb81b2d8ca256bb6a5b0ef7db86489778a7`にあるライブラリのdocumentId `12345`の文書に対して署名を要求するものです。

この方法は、スマートコントラクトを通じて自動的に文書に署名する要求を送信するためのものです。
これは、文書の確認や署名が必要な場合に特に有用で、関連する文書に対する迅速かつ効率的な注意と行動を促す方法を提供します。
このようにして、関係者は簡単かつ確実に文書に署名を行うことができるようになります。

:::note info
**ERC5568**については以下の記事を参考にしてください。
:::

https://qiita.com/cardene/items/0645beb4327317d388b7

## 文書への署名

文書への署名が要求されると、ウォレットはまず`legalDocument`関数を呼び出します。
この関数は特定の文書を取得し、ウォレットはその文書をユーザーに表示します。
次に、ユーザーに対してその文書に署名するか、または操作をキャンセルするかを選択させます。

ユーザーが署名を選択した場合、ウォレットは`signDocument`関数を呼び出す必要があります。
これにより、ユーザーの署名が正式に文書に追加され、その意志がスマートコントラクトに記録されます。
このプロセスは文書の内容をユーザーが十分に理解し、意識的に同意して署名することを保証するために設計されています。
この手順により、スマートコントラクトを通じての法的文書の扱いがより安全かつ確実になります。

![example-popup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570269/6396b5d9-3c39-ed6d-8ac3-93f616051ade.png)

引用: https://eips.ethereum.org/EIPS/eip-5289

# 補足

タイムスタンプの返り値として`uint64`が選択されたのは、`64`ビットの時間レジスタが標準であるためです。
これにより、日付と時刻を正確に記録し、長期間にわたるトラッキングに適しています。
一方で、文書IDとして`uint16`が選ばれたのは、`65536`件という大量の文書を扱うことができ、ほとんどのユースケースに対応可能であるためです。
また、必要に応じてコントラクトを再デプロイすることで、さらに多くの文書を扱うことも可能です。

`signDocument`関数は、将来的なアカウント抽象化との互換性を考慮して、ECDSA署名を取らない設計になっています。
これは、将来的な技術変更に柔軟に対応できるようにするためです。
また、将来の拡張機能でECDSA署名の受け取りなどの機能が追加される可能性もあります。

IPFSの使用は必須とされています。
これは、IPFSが分散型のファイルストレージシステムであり、署名された文書の真正性を証明するのに非常に適しているからです。
IPFSを利用することで、文書の安全性と信頼性が大きく向上します。

これらの設計選択は、コントラクトの効率、将来への互換性、そして文書の真正性と安全性を確保するために慎重に行われました。

# 互換性

互換性の問題は見つかっていません。

# 実装

参考実装はそれぞれ以下になります。

- [IERC5289Library](https://eips.ethereum.org/assets/eip-5289/interfaces/IERC5289Library.sol)
- [ERC5289Library](https://eips.ethereum.org/assets/eip-5289/ERC5289Library.sol)

# セキュリティ

ユーザーが自分のプライベートキーが盗まれ、詐欺的にコントラクトに「**署名**」されたと主張する可能性があるため、文書は制限的ではなく許可的な性質のものでなければなりません。
制限的な文書は、ユーザーが不正な署名を否定する可能性が高いため、リスクが伴います。
例えば、NFTに添付された画像の使用ライセンスを付与する文書は許容される例です。
署名者がそのような文書の署名を否定する合理的な理由は通常存在しません。

このように、文書が許可的な内容であれば、プライベートキーの盗難などによる詐欺的な署名の主張によるリスクを軽減し、コントラクトの信頼性と有効性を保持することができます。
ユーザーに何かを許可する内容であることで、より安全な取引が可能になります。

# 引用

Gavin John (@Pandapip1), "ERC-5289: Ethereum Notary Interface [DRAFT]," Ethereum Improvement Proposals, no. 5289, July 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5289.


# 最後に

今回は「スマートコントラクトに法的拘束力をもたらす仕組みを提案している規格である**ERC5289**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://chaldene.net/

https://zenn.dev/heku

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4