# [ERC7444] ロック解除日時を統一的に取得できる仕組みを理解しよう！

> ERC7444で扱われるさまざまな仕組みの中には、特定の日付まで引き出しや移動ができない**タイムロック（一定期間ロックされる仕組み）**が多く存在します。しかし、「いつロックが解除されるのか」を標準的な形式で示す方法がありませんでした。

- URL: https://cardene.dev/articles/5a3104e83f0a7c560e80
- 公開日: 2025-12-01
- 更新日: 2025-12-01
- トピック: Blockchain
- タグ: ethereum, solidity, smartcontract, ブロックチェーン

## はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

今回は、タイムロック資産がいつ解除されるかを標準的に取得できる仕組みを提案している**ERC7444**についてまとめていきます！

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

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

他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。

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

## 概要

**ERC7444**で扱われるさまざまな仕組みの中には、特定の日付まで引き出しや移動ができない**タイムロック（一定期間ロックされる仕組み）**が多く存在します。
しかし、「**いつロックが解除されるのか**」を標準的な形式で示す方法がありませんでした。

**ERC7444**の目的は、タイムロックが解除される日付を共通の方法で表現できる仕組みを定義することです。
共通の形式で解除日を確認できるようになると、異なるタイプの資産であっても、いつ価値が実現されるのかを明確に判断できます。

タイムロックされた資産は、ロックが解けるまでの残り時間によって価値が変動します。
これは金融分野でいう**セータ減価（価値が時間とともに少しずつ変化するイメージ）**に近い性質です。
解除日がはっきり分かることで、資産の評価がより正確になり、扱いやすくなります。

## 動機

ブロックチェーン上には、トークンの権利移転、ステーキング、ベスティング報酬など、多くの場面でタイムロックが使われています。
しかし、ロック解除日を標準化して通知する手段が存在しないという課題がありました。

この問題があると、以下のような不便が生じます。

- **正確な評価が難しい**
    タイムロックされた資産は、解除までの時間によって価値が変わります。
    解除日が分かりにくいと、資産の現在価値を正しく判断しづらくなります。
- **権利移転が複雑になる**
    タイムロックされた権利そのものを、NFT（**ERC721**）やセミファンジブルトークン（**ERC1155**）として他者に譲渡するケースがあります。
    このとき、解除日が明確でなければ、受け取る側が資産の価値やリスクを判断できません。
- **資産管理が煩雑になる**
    プロジェクトごとに独自方式で日付を扱っていると、ユーザーやアプリが統一的に扱うことが難しくなります。

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

[\[ERC721\] ERC721を1からわかりやすく解説](/articles/0570a8d05bc7c9b9593f)

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

[\[ERC1155\] ERC1155を1からわかりやすく解説](/articles/c3ef92722b057161bebd)

**ERC7444**では、タイムロック解除日を共通フォーマットで表現する標準を設けることで、資産のロック解除日時（解除されて利用可能になる日）を誰でも確認できるようにすることを目的としています。

これにより、特に以下の点で改善が期待できます。

* タイムロック資産の価値をチェーン上でより正確に算定できる
* NFT化された権利の売買や移転がスムーズになる
* ユーザーやアプリが異なるプロジェクトのロック解除日を簡単に扱えるようになる

タイムロックが絡む資産をより透明で扱いやすいものにするための基盤を提供する、という位置づけになります。

## 仕様

#### ERC165への準拠

**ERC7444**を実装するコントラクトは、**ERC165**によるインターフェース検出機能を必ず実装する必要があります。
これは、外部のコントラクトやアプリケーションが「**このコントラクトはERC7444に対応しているか**」を判定できるようにするための仕組みです。

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

[\[ERC165\] コントラクトが特定のインターフェースをサポートしているか確認する仕組みを理解しよう！](/articles/541184977a5cba51b759)

**ERC165**は、インターフェース識別子（interfaceId）を使って対応状況を確認する標準です。
これにより、ウォレットや他のコントラクトが安全に**ERC7444**機能の有無を認識できます。

#### インターフェース仕様

**ERC165**の中心となるのは、特定のタイムロックの解除時刻を返す `getMaturity` 関数です。
以下はインターフェースです。

```js
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.0;

interface ERC-7444 {
    /*
     * @notice      This function returns the timestamp that the time lock specified by `id` unlocks at
     * @param       id The identifier which describes a specific time lock
     * @return      maturity The timestamp of the time lock when it unlocks
     */
    function getMaturity(bytes32 id)
        external
        view
        returns (uint256 maturity);
}
```

この関数が提供する情報は以下のとおりです。

* **id**
    タイムロックを識別するための値です。
    複数のタイムロックを扱う場合に、それぞれを区別するために使われます。

* **戻り値 maturity**
    該当するタイムロックの解除タイミングを示す数値で、**Unixタイムスタンプ** 形式で返されます。
    Unixタイムスタンプとは、1970年1月1日（協定世界時）からの経過秒数を示す一般的な形式で、Solidityでは `block.timestamp` と同じ形式です。

この形式に統一することで、ツールやアプリケーションが簡単に扱えるようになります。

#### Unixタイムスタンプの採用

`maturity` の戻り値は、Solidityで一般的に使用されている **Unixタイムスタンプ**で実装する必要があります。
Solidityでは多くの時間関連処理がこの形式に依存しているため、他の仕組みと一貫性を保つことができます。

例として `block.timestamp` が挙げられますが、これはブロックが生成された時点のUnixタイムスタンプです。

#### 単一のタイムロックを持つ資産での扱い

資産によっては、複数の `id` を扱わず、1つのタイムロックだけを持つ場合があります。
こうしたケースでは、`getMaturity` に渡される `id` は特に意味を持ちません。

そのため、仕様では以下のように定められています。

* 単一のタイムロックしか持たない場合、`id` の値は無視して構いません。
* そのような実装に対して問い合わせを行う場合、`id` には `0x0` を渡すことが推奨されます。

これにより、単一ロック型の資産でも、複数ロック型の資産と共通のインターフェースで扱えるようになります。

## 補足

#### ロック資産のロック解除日時の統一的な取り扱い

DeFiでは、利回り獲得のための仕組みや、一定期間引き出せない状態で報酬を付与する仕組みが広く使われています。
具体例として、イールドファーミングやベスティング型エスクローがあります。
これらはどれも「**特定の解除日を持つロック資産**」を前提にしています。

このように多くのプロトコルがタイムロックを採用する中で、ロック解除日時を共通の方法で取得できる仕組みが必要になってきました。
**ERC7444**は、どのプロトコルでも同じ方法でロック解除日時を参照できるようにすることで、アプリケーションやウォレットが異なる資産を扱いやすくすることを目的としています。

#### ブラック–ショールズモデルによるロック資産の評価

ロック資産は、通常の資産と異なり時間の経過によって価値が変化する特性を持ちます。
解除までの期間が長いほどリスクや不確実性が大きくなり、価値に影響します。

このような資産を定量的に評価するためには、金融工学で用いられる数学的モデルが必要です。
その代表例が **ブラック–ショールズモデル（Black-Scholes Model）**、またはその発展形である **ブラック–ショールズ–マートンモデル（Black-Scholes-Merton Model）** です。

ブラック–ショールズモデルは、本来はオプション価格の算出に使われるモデルですが、
「**時間による価値の変化を数学的に扱える**」という点でロック資産にも適用できます。

以下はブラック–ショールズモデルの主要な構成要素です。

| 要素                     | 内容                                   |
| ---------------------- | ------------------------------------ |
| ボラティリティ  | 価格の変動幅を示す指標です。     |
| リスクフリーレート   | 無リスク資産の利回りです。 |
| 残存期間（Time to maturity） | 権利が行使可能になるまでの時間で、ロック資産の評価では最も重要な値です。 |

ロック資産の価値評価には、解除までの残り時間が大きな意味を持ちます。
そのため、ロック解除日時を正確に取得できる共通インターフェースが不可欠という背景があります。

#### 時間の影響を受けるモデルの重要性

ブラック–ショールズモデルの特徴は、時間の経過に伴う価値の変化を計算に組み込める点です。
ロック資産では、解除までの期間が短くなるほど価値が高まることが多いため、ロック解除日時を正確に扱えないと評価が不正確になります。

**ERC7444**は、こうしたモデルに必要な基礎データである「**ロック解除日時**」を標準的に取得できるようにすることで、
ロック資産をより透明に、かつ正確に評価できる環境を整える役割があります。

## 互換性

#### ERC721・ERC1155との互換性

**ERC7444**は、既存のトークン規格である **ERC721**（NFT）と**ERC1155**（マルチトークン）に自然に組み込める設計になっています。
すでにロック機能を持つトークンに対しても、後から専用のコントラクトを追加することでロック解除日時を取得できるようになります。

この仕組みによって、既存プロジェクトがトークンの作り直しをすることなく、**ERC7444**の機能を取り込むことが可能になります。

#### 既存資産への対応

ロック機能を持つ既存トークンは、ロック解除日時を記録していなかったり、独自方式で記録していたりします。
しかし、**ERC7444**では「**ロック解除日時を返すコントラクトを後付けで用意する**」という形で拡張できるため、多くのプロジェクトに適用できます。

例えば、以下のような仕組みで対応できます。

| 対応方法         | 内容                                          |
| ------------ | ------------------------------------------- |
| 専用コントラクトの追加  | 既存トークンの情報を参照し、ロック解除日時を返す仕組みを別コントラクトとして実装します。    |
| トークンへの最小限の拡張 | 必要であれば既存トークンに小さな改修を行い、ロック解除日時取得用の関数へつなぐことができます。 |

この柔軟性のおかげで、**ERC7444**は既存のエコシステムに自然に溶け込むことができます。

## 参考実装

### LockedERC20の実装

```js:LockedERC20ExampleContract.sol
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract LockedERC20ExampleContract implements ERC-7444{
    ERC20 public immutable token;
    uint256 public totalLocked;

    //Timelock struct
    struct TimeLock {
        address owner;
        uint256 amount;
        uint256 maturity;
        bytes32 lockId;
    }

    //maps lockId to balance of the lock
    mapping(bytes32 => TimeLock) public idToLock;    

    function constructor(
        address _token,
    ) public {
        token = ERC20(_token);
    }

    //Maturity is not appropriate
    error LockPeriodOngoing();
    error InvalidReceiver();
    error TransferFailed();

    /// @dev Deposit tokens to be locked in the requested locking period
    /// @param amount The amount of tokens to deposit
    /// @param lockingPeriod length of locking period for the tokens to be locked
    function deposit(uint256 amount, uint256 lockingPeriod) external returns (bytes32 lockId) {
        uint256 maturity = block.timestamp + lockingPeriod;
        lockId = keccack256(abi.encode(msg.sender, amount, maturity));

        require(idToLock[lockId].maturity == 0, "lock already exists");

        if (!token.transferFrom(msg.sender, address(this), amount)) {
            revert TransferFailed();
        }

        TimeLock memory newLock = TimeLock(msg.sender, amount, maturity, lockedId);

        totalLocked += amount;

        idToLock[lockId] = newLock;
        
    }

    /// @dev Withdraw tokens in the lock after the end of the locking period
    /// @param lockId id of the lock that user have deposited in
    function withdraw(bytes32 lockId) external {
        TimeLock memory lock = idToLock[lockId];

        if (msg.sender != lock.owner) {
            revert InvalidReceiver();
        }

        if (block.timestamp > lock.maturity) {
            revert LockPeriodOngoing();
        }

        totalLocked -= lock.amount;

        //State cleanup
        delete idToLock[lockId];

        if (!token.transfer(msg.sender, lock.amount)) {
            revert TransferFailed();
        }

    }

    function getMaturity(bytes32 id) external view returns (uint256 maturity) {
        return idToLock[id].maturity;
    }
}
```

## セキュリティ

#### 伸長可能なタイムロックについて

**ERC7444**を利用する時に、特に注意すべき点として伸長可能なタイムロック（Extendable Time Locks）があります。
これは、ロック解除日時として返されるタイムスタンプが、後からプロトコル側によって変更される可能性があるケースを指します。

ロック資産の多くは「**一定期間が経過したら解除される**」という前提で設計されています。しかし、実装によっては解除時刻そのものを更新できるものがあります。たとえば、以下のような状況です。

* プロトコルの仕様によって、ロック期間を延ばす機能が含まれている
* 管理者権限を持つアドレスがロック解除日時を更新できる
* ロック期間が条件付きで変化する仕組みになっている

こうしたケースでは、`getMaturity` が返す解除時刻が後から変更される可能性があるため、ユーザーや他のプロトコルは返却されたタイムスタンプを信用しすぎないよう注意する必要があります。

以下に、想定されるリスクと対策のポイントをまとめます。

| 内容   | 説明       |
| --------------- | ------------------------ |
| 解除時刻が変更されるリスク   | 資産を取引する時、解除が近いと思って購入した資産が実は延長されてしまう可能性があります。  |
| プロトコル間の連携時のトラブル | 借入や担保などでタイムロック資産を扱う際、ロック解除日時が変更されると期待した返済計画が崩れます。 |
| 対策として必要な確認      | 返されたロック解除日時が固定の値なのか、変更可能な仕組みなのかを必ず確認する必要があります。    |

ロック資産を売買したり、担保として利用したりする場面では、ロック解除日時時が変動する設計かどうかを慎重に確認しないと、意図せぬ損失を招く可能性があります。
特に他者との取引や、借入プロトコルとの連携では、参照しているロック解除日時が信頼できる値であるかを判断することが重要です。

**ERC7444**はロック解除日時の取得方法を標準化する規格ですが、ロック解除日時の値そのものが改ざんされない保証を提供するものではありません。
そのため、資産の実装仕様や管理者権限の有無を理解し、安全に取引するための追加チェックが不可欠になります。

## 引用

Thanh Trinh (@thanhtrinh2003) <thanh@revest.finance>, Joshua Weintraub (@jhweintraub) <josh@revest.finance>, Rob Montgomery (@RobAnon) <rob@revest.finance>, "ERC-7444: Time Locks Maturity [DRAFT]," Ethereum Improvement Proposals, no. 7444, June 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7444.

## 最後に

今回は「タイムロック資産がいつ解除されるかを標準的に取得できる仕組みを提案している**ERC7444**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

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