# [ERC6372] コントラクトが使用している時間表現を取得する仕組みを理解しよう！

> スマートコントラクトは、特定のタスクを実行する時に時間情報を使用することがよくあります。例えば、特定の条件が満たされるまで待機する必要がある場合や、トランザクションのタイムスタンプを記録して取引の履歴を管理する場合などです。

- URL: https://cardene.dev/articles/eacc6a32cbac790df52d
- 公開日: 2023-09-19
- 更新日: 2023-09-19
- トピック: Blockchain
- タグ: ethereum, solidity, smartcontract, ブロックチェーン

## はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、コントラクトで使用している時間表現を判別できる規格を提案している**ERC6372**についてまとめていきます！

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

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

:::message alert
**6372**は現在（2023年9月7日）では「**Review**」段階です。
:::

## 概要

スマートコントラクトは、特定のタスクを実行する時に時間情報を使用することがよくあります。
例えば、特定の条件が満たされるまで待機する必要がある場合や、トランザクションのタイムスタンプを記録して取引の履歴を管理する場合などです。

しかし、問題は、スマートコントラクトが内部でどの時間情報を使っているかが外部から分かりにくいことです。
一部のスマートコントラクトはEthereumのブロック番号を使い、他のものはタイムスタンプ（実際の時刻情報）を利用しています。
この違いを知ることなく、他のスマートコントラクトとの連携や統合を行うのは難しいです。

そこで、このEthereum Improvement Proposal（EIP）は、スマートコントラクトがどの時間情報を使っているかを一貫した方法で外部に公開できるようにすることを提案しています。
これにより、他のスマートコントラクトやプログラムが容易に時間情報を取得し、それに基づいて連携や処理を行うことが可能になります。
これは、スマートコントラクト間の連携やデータの整合性を向上させ、より多くのアプリケーションが円滑に動作するための基盤を提供することを意味しています。

## 動機

スマートコントラクトは、さまざまな目的で時間に関連する情報を必要とします。
例えば、タイムロックコントラクトは、特定の操作を実行する前に一定の待機時間を要求します。
同様に、分散型自治組織（DAO）は、提案を承認または拒否するための投票期間を設け、その期間内にステークホルダーが意思決定を行います。
また、投票トークンは、投票権の履歴を時間ごとに保存し、過去の投票に基づいて権限を付与します。

こうしたスマートコントラクトの中には、時間の計測に実際の時刻情報である「**タイムスタンプ**(`timestamp`)」を利用するものもありますし、ブロックチェーンの「**ブロック番号**」を使用するものもあります。
さらに、より複雑な方法で時間を追跡するコントラクトも存在します。

問題は、外部のユーザーやコントラクトが特定のスマートコントラクトがどの時間情報を利用しているかを容易に認識できないことです。
これが問題となる理由は、他のスマートコントラクトやアプリケーションと連携する際に、そのスマートコントラクトがどのような時間情報を利用しているかを知らないと、連携や統合が難しくなり、誤った仮定をするリスクがあるからです。

この問題を解決するために、この提案が行われています。
提案の目的は、スマートコントラクトがどの時間情報を使用しているかを外部から簡単に認識できる方法を提供することで、スマートコントラクト間の相互運用性を向上させ、開発者に確実性を提供することです。

## 仕様

```javascript
interface IERC6372 {
  function clock() external view returns (uint48);
  function CLOCK_MODE() external view returns (string);
}
```

もちろん、各関数について説明を行います。

#### clock

```javascript
function clock() external view returns (uint48);
```

**概要**
スマートコントラクトが動作しているモードに応じて、現在の時間を返す関数。

**詳細**
時間はチェーンの進行に連動し、減少が行われない関数である必要があります。
例えば、`block.timestamp`や`block.number`などが考えられます。

**戻り値**
- `timepoint`
    - 現在の時間を表す値を返します。

---

#### CLOCK_MODE

```javascript
function CLOCK_MODE() external view returns (string);
```

**概要**
スマートコントラクトがどのような方法で時間を表現しているかの情報を返す関数。

**詳細**
タイムスタンプ、ブロック番号、または他の時間計測方法のいずれかが返ってきます。
この情報は機械可読な文字列形式で提供され、JavaScriptで`new URLSearchParams(CLOCK_MODE)`を用いてデコードできる形式でなければなりません。
この関数を使用することで、他のスマートコントラクトやプログラムが、正確な時間情報を理解できるようになります。

**戻り値**
- `descriptor`
    - スマートコントラクトが使用している時計モードの詳細情報を示す文字列を返します。
    - この文字列はURLクエリ文字列の形式である必要があります。

「`clock()`」関数は、時間に関する情報を提供するための特別な関数です。
しかし、この関数には重要なルールがあります。
それは、「`clock()`」関数が返す時間は、過去に戻ることは絶対に許されず、一貫して進む方向にしか進行してはいけないということです。

つまり、もし「`clock()`」関数がある時点で特定の時間を返した場合、それ以降の時刻では、その返された時間よりも未来の時間を返さなければなりません。
過去の時間に戻ることは、許容されません。

## 補足

「`clock()`」関数は、スマートコントラクト内部の時間情報を提供するための特別な関数です。
この関数が返す時間情報は、「`uint48`」というデータ型で表現されています。
この「`uint48`」は、現実的な時間情報を格納するのに十分な大きさを持っています。

具体的な例を挙げると、タイムスタンプモードでは、「`uint48`」は最大`8921556`年までの時間を表現できます。
また、ブロック番号モードでも、`1`秒あたり`10000`ブロックという非常に速いブロック生成速度を仮定しても、最大で`2861`年まで対応できます。
このため、「`uint48`」を使用することで、十分に長期間の時間情報を保持できます。

さらに、「`uint48`」は「`uint256`」と比べて小さなデータ型であるため、スマートコントラクト内部で時間情報を他の関連データと一緒に収納する際に、ストレージへの書き込みと読み取りのコストを大幅に削減できます。
これは効率的なデータ管理を実現するのに役立ちます。

ただし、ブロックチェーン技術は進化し続けており、将来的にはより小さいデータ型、例えば「`uint32`」を使用することが問題を引き起こす可能性があるかもしれません。
したがって、データ型の選択は状況に応じて検討する必要があります。

さらに、時間差や遅延を表現する場合も考慮が必要です。
通常、「`uint48`」は時間情報を表すのに適していますが、「`uint32`」は短い時間差や遅延を表現するのにも十分です。
例えば、秒単位で動作するクロックを使用する場合、約`136`年以上の時間差を表現できます。

:::message
スマートコントラクトには、ある特定のアクションを実行する前に、`10`日間の待機期間（遅延）を設けたい場合を考えてみます。
この遅延期間を「**時間差**」または「**遅延**」として表現します。

1. `uint48`を使用する場合
   - `10`日間は秒で換算すると、約`864,000`秒です。
   - `uint48`は最大で約`281,474,976,710,656`までの整数を表現できます。
   - したがって、`uint48`を使用すると、`10`日間の遅延期間を表現するのに十分なスペースがあります。

2. `uint32`を使用する場合
   - `10`日間は秒で換算すると、約`864,000`秒です。
   - `uint32`は最大で約`4,294,967,295`までの整数を表現できます。
   - `uint32`でも、`10`日間の遅延期間を表現するのに十分なスペースがあります。

このように、秒単位のクロックを使用している場合、`uint48`と`uint32`の両方が`10`日間の遅延期間を表現するのに十分です。
しかし、「`uint32`」の方がストレージスペースを節約できるためおすすめされています。
:::

したがって、一般的には、「`uint48`」は時間情報を格納するのに適しており、「`uint32`」は時間差や遅延を格納するのに適しているとされています。
ただし、具体的な使用ケースや時間情報の範囲に応じて、データ型の選択を検討することが重要です。

## セキュリティ考慮事項

特になし。

## 引用

Hadrien Croubois (@Amxx), Francisco Giordano (@frangio), "ERC-6372: Contract clock [DRAFT]," Ethereum Improvement Proposals, no. 6372, January 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-6372.

## 最後に

今回は「コントラクトで使用している時間表現を判別できる規格を提案している**ERC6372**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://chaldene.net/

https://zenn.dev/heku

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58
