# [ERC1066] コントラクトの実行結果を詳細に取得する仕組みを理解しよう！

> ERC1066は、スマートコントラクトの実行結果に対して共通の「ステータスコード（状態コード）」を導入するための標準仕様です。

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

## はじめに

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

https://amzn.asia/d/gxvJ0Pw

今回は、スマートコントラクト開発者が、成功や失敗だけでなく処理の詳細な状態を共通コードで表現できるようになり、コントラクト間の連携やユーザーへのフィードバックがより明確かつ自動化できる仕組みを提案している**ERC1066**についてまとめていきます！

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

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

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

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

## 概要

**ERC1066**は、スマートコントラクトの実行結果に対して共通の「**ステータスコード（状態コード）**」を導入するための標準仕様です。
これはHTTPステータスコードに着想を得たもので、各スマートコントラクトが同じ意味を持つステータスコードを返すことで、エラー処理やステート管理、ユーザー向けのメッセージ表示をより整備されたものにします。

現在のスマートコントラクトでは、成功以外の状況には即座に `revert`（実行停止）してしまう設計が一般的です。
あるいは単純に `true` や `false` のブール値しか返さないため、開発者やユーザーは失敗理由を理解しづらく適切な対応が難しいです。
**ERC1066**では、失敗や成功のバリエーションを「**意味のあるコード**」で返すことで、スマートコントラクト同士の連携、自動化、UXの向上を図ります。

このステータスコードは `revert` や `revert-with-reason`（理由付きロールバック）とも併用でき、例外処理や制御フローの手段として柔軟に使うことが可能です。
これにより、失敗の種類や成功の意味、処理の遷移などをより詳細かつ機械的に扱えるようになります。

## 動機

**ERC1066**が提案された背景には、スマートコントラクトにおける情報量の乏しさがあります。
現在のEVMでは、処理結果が成功したか失敗したかをブール値や単純な `revert` でしか表現できないため、エラー内容やステート遷移の詳細を知ることが困難です。

ステータスコードを導入することで、コントラクトが実行中にどの地点で、どんな理由でどのような結果になったのかをコード1つで表現できるようになります。
これは、HTTPの `404 Not Found` や `200 OK` のように、事前に定められた意味を持つコードにより、実行結果に対する共通理解を可能にします。

この仕組みによって、ユーザーはより具体的なエラーメッセージを得られるようになり、多言語対応やUI改善にもつながります。
例えば、ステータスコードとともに**ERC1444**を活用すれば、コードに対応するユーザー向けの説明文を取得することもできます。

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

[\[ERC1444\] コントラクトのエラーメッセージを多言語化する仕組みを理解しよう！](/articles/c178ba42bd417867c976)

また、開発者にとっては、より明確なテスト記述が可能となり、処理の分岐点ごとのステータスコードをもとに検証できるため、デバッグや品質向上にも貢献します。
さらに、共通のコードセットを持つことで、各コントラクトが共通のユーティリティやライブラリを用いて処理を記述できるようになり、開発効率も向上します。

加えて、スマートコントラクトが自律的に振る舞うためには、実行結果をより高度に理解する必要があります。
`bool` 値や単純な `revert` だけでは十分な判断ができませんが、明確な意味を持つステータスコードがあれば、コントラクト同士がそれを解釈して次のアクションを選択することが可能になります。

## 仕様

**ERC1066**では、関数の戻り値として「ステータスコード」を返す形式を定めています。
これはスマートコントラクトの処理結果を単なる `true` / `false` ではなく、意味を持ったバイトコード（例: `hex"01"`）で表現することで、より詳細な状態判別を可能にするものです。

**ERC1066**では、ステータスコードは単独で返すことも、他の値と組み合わせて返すこともできます。
例えば、ある関数が成功したかどうかだけを示したい場合は、バイトコードのみを返し、成功した上で何らかの値（数値やアドレスなど）も返す場合には、タプル形式で返却します。

これにより、スマートコントラクトは外部のコントラクトやフロントエンドに対して、状態をよりセマンティックに伝えることが可能になります。
また、戻り値に基づいて処理を自動分岐させることや、ユーザーに翻訳可能なメッセージを表示させることも可能となります。

例えば、以下のようなコードは「**整数であるかどうか**」を確認し、そのステータスコードを返します。

```javascript
function isInt(uint num) public pure returns (byte status) {
    return hex"01";
}
```

また以下のコードは、`counter` を安全に加算し、その結果と状態コードを返します。
加算に成功すれば `hex"01"` を、そうでなければ `hex"00"` を返します。

```javascript
function safeIncrement(uint8 interval) public returns (byte status, uint8 newCounter) {
    uint8 updated = counter + interval;

    if (updated >= counter) {
        counter = updated;
        return (hex"01", updated);
    } else {
        return (hex"00", counter);
    }
}
```

### ステータスコードの構造

**ERC1066**では、スマートコントラクトが返す「**ステータスコード**」を16×16のマトリクス、すなわち2桁の16進数で構成することを定めています。
この2桁のコードは、上位4ビット（high nibble）が「**カテゴリ（分類）**」を、下位4ビットが「**ステート（理由）**」を表します。
例えば、`0x01` は「**カテゴリ 0x0（一般）**」の「**成功（0x01）**」という意味になります。

この設計により、スマートコントラクトは実行結果を明確かつ機械的に分類し、他のコントラクトや外部システムとのインターフェースを強化できます。
コードは現在、複数のカテゴリに分けて定義されており、それぞれの範囲内で詳細な状態を表現しています。

#### 0x0* 一般（Generic）

このカテゴリは最も基本的な意味を持つコードで、成功・失敗といった最小限のステータスを定義します。
他のカテゴリが使えない状況でも、このコードセットは基本的な結果を伝えるのに使用されます。

| コード       | 説明            |
| --------- | ------------- |
| `0x00`      | 失敗            |
| `0x01`      | 成功            |
| `0x02`      | 他者の処理を待っている   |
| `0x03`      | 要求を受理済み       |
| `0x04`      | 下限未満または不十分    |
| `0x05`      | 受信者側のアクションが必要 |
| `0x06`      | 上限を超過         |
| `0x07`      | 【予約済み】        |
| `0x08`      | 重複・不要・該当なし    |
| `0x09` 〜 `0x0E` | 【予約済み】        |
| `0x0F`      | 情報提供やメタデータ用   |

#### 0x1* 権限・制御（Permission & Control）

このカテゴリは、アクセス制御やステートマシンの動作に関連するコードを提供します。
例えば、「**操作不可**」や「**許可が必要**」といった制御フローを表現します。

| コード       | 説明                 |
| --------- | ------------------ |
| `0x10`      | 許可されていない、または中止     |
| `0x11`      | 許可済み、または実行可能       |
| `0x12`      | 他者の許可を待っている        |
| `0x13`      | 許可を要求中             |
| `0x14`      | セキュリティ的に危険な状態      |
| `0x15`      | あなたの許可が必要、または継続の要求 |
| `0x16`      | 取り消し済みまたは禁止        |
| `0x17`      | 【予約済み】             |
| `0x18`      | 現在の状態では適用できない      |
| `0x19` 〜 `0x1E` | 【予約済み】             |
| `0x1F`      | 権限や制御条件に関するメタ情報    |

#### 0x2* 検索・比較・範囲（Find, Inequalities & Range）

このカテゴリは、値の検索や一致、不一致、範囲チェックといった操作を表します。
オーダーマッチングやデータベース検索などに適用されます。

| コード       | 説明                |
| --------- | ----------------- |
| `0x20`      | 見つからない、一致しない、範囲外  |
| `0x21`      | 見つかった、一致、範囲内      |
| `0x22`      | 一致を待っている          |
| `0x23`      | 一致リクエストを送信済み      |
| `0x24`      | 範囲下限未満、またはアンダーフロー |
| `0x25`      | 一致の要求             |
| `0x26`      | 範囲上限超過、またはオーバーフロー |
| `0x27`      | 【予約済み】            |
| `0x28`      | 重複、競合、衝突          |
| `0x29` 〜 `0x2E` | 【予約済み】            |
| `0x2F`      | 一致に関するメタ情報や補足     |

#### 0x3\* 交渉・ガバナンス（Negotiation & Governance）

このカテゴリは、意思決定の合意形成や交渉、投票といった「**取引の流れ**」に関する状態を表します。
スマートコントラクト内での提案、同意、不一致、投票待ちといった多段階プロセスを表現する際に用いられます。
「**相手側**」は必ずしも1人に限定されず、複数のアクターであることも考慮されています。

| コード       | 説明                   |
| --------- | -------------------- |
| `0x30`      | 送信者が反対、または「いいえ」      |
| `0x31`      | 送信者が同意、または「はい」       |
| `0x32`      | 承認（ラチェフィケーション）を待っている |
| `0x33`      | 提案を送信済み、または投票済み      |
| `0x34`      | 定足数（クオーラム）未達         |
| `0x35`      | 受信者側の承認が必要           |
| `0x36`      | 提案または投票の上限に達した       |
| `0x37`      | 【予約済み】               |
| `0x38`      | すでに投票済み              |
| `0x39` 〜 `0x3E` | 【予約済み】               |
| `0x3F`      | 交渉ルールまたは参加者に関する情報    |

#### 0x4* 利用可能性・時間（Availability & Time）

このカテゴリは、サービスやアクションが「**いつ利用可能か**」という時間的な可用性に関する状態を表します。
処理の一時停止、遅延、順番待ち、期限切れといった概念をコントラクトレベルで扱うことが可能になります。

| コード       | 説明                        |
| --------- | ------------------------- |
| `0x40`      | 利用不可                      |
| `0x41`      | 利用可能                      |
| `0x42`      | 一時停止中                     |
| `0x43`      | キューに登録済み                  |
| `0x44`      | まだ利用できない                  |
| `0x45`      | あなたの応答待ち（利用可能になるのを待っている）  |
| `0x46`      | 有効期限切れ                    |
| `0x47`      | 【予約済み】                    |
| `0x48`      | すでに実行済み                   |
| `0x49` 〜 `0x4E` | 【予約済み】                    |
| `0x4F`      | 利用に関するルールや情報（いつまで／いつからなど） |

#### 0x5* トークン・資金・金融（Tokens, Funds & Finance）

このカテゴリは、資産の移転や決済、保留中の支払いといった金融的な状態を定義します。
トークン転送、資金不足、エスクロー処理など、資金のやり取りに関するステータスを詳細に区別できるよう設計されています。

| コード       | 説明              |
| --------- | --------------- |
| `0x50`      | 転送失敗            |
| `0x51`      | 転送成功            |
| `0x52`      | 他者からの支払いを待っている  |
| `0x53`      | 保留またはエスクロー      |
| `0x54`      | 資金不足            |
| `0x55`      | 資金を要求中          |
| `0x56`      | 転送量が制限を超えた      |
| `0x57`      | 【予約済み】          |
| `0x58`      | 資金が不要           |
| `0x59` 〜 `0x5E` | 【予約済み】          |
| `0x5F`      | トークンまたは金融に関する情報 |


#### 0x6*〜0x9* 未定義カテゴリ（TBD）

`0x6*` から `0x9*` の範囲は、現在の時点では仕様が未定義であり、将来的な拡張のために予約されています。
これらのコードは現状使用すべきではなく、今後の **ERC1066** 拡張や他提案によって意味づけされることが期待されています。

#### 0xA* アプリケーション固有コード（Application-Specific Codes）

このカテゴリは、特定のアプリケーションやドメインに特化した状態を表現するためのコードです。
仕様としては広範な意味だけを定め、各実装者が自分のコントラクトに合った詳細な意味を自由に追加できるようになっています。
ただし、定義される内容はカテゴリの基本的な意図と整合性が取れている必要があります。

| コード       | 説明               |
| --------- | ---------------- |
| `0xA0`      | アプリ固有の失敗         |
| `0xA1`      | アプリ固有の成功         |
| `0xA2`      | アプリ固有の他者待機状態     |
| `0xA3`      | アプリ固有の受理済み       |
| `0xA4`      | アプリ固有の条件未満       |
| `0xA5`      | アプリ固有の受信者アクション要求 |
| `0xA6`      | アプリ固有の期限切れまたは上限  |
| `0xA7`      | 【予約済み】           |
| `0xA8`      | アプリ固有の不適用条件      |
| `0xA9` 〜 `0xAE` | 【予約済み】           |
| `0xAF`      | アプリ固有のメタ情報や補足    |

#### 0xB*〜0xD* 未定義カテゴリ（TBD）

`0xB*`、`0xC*`、`0xD*` の範囲も現在は未定義であり、すべて将来の拡張のために予約されています。
この領域も仕様としてまだ意味が与えられていないため、任意の用途での使用は推奨されません。

#### 0xE* 暗号・認証・証明（Encryption, Identity & Proofs）

このカテゴリは、署名、復号、認証、鍵の使用など、暗号学的な処理や本人確認に関連する状態を表します。
アプリケーションにおけるセキュリティ処理やIDベースのアクセス制御と密接に関係する場面で使用されます。

特に `0xEF` は、署名方式や暗号アルゴリズムなど、詳細なメタデータを伝えるためのコードとして予約されています。

| コード       | 説明                          |
| --------- | --------------------------- |
| `0xE0`      | 復号に失敗                       |
| `0xE1`      | 復号に成功                       |
| `0xE2`      | 他者の署名や鍵の提供待ち                |
| `0xE3`      | 署名済み                        |
| `0xE4`      | 未署名または信頼できない                |
| `0xE5`      | 署名が必要                       |
| `0xE6`      | 鍵や署名が漏洩または危殆化していると判明している    |
| `0xE7`      | 【予約済み】                      |
| `0xE8`      | すでに署名済み、または暗号化されていない        |
| `0xE9` 〜 `0xEE` | 【予約済み】                      |
| `0xEF`      | 暗号・ID・証明に関するメタ情報（方式や処理内容など） |

#### 0xF* オフチェーン処理（Off-Chain）

このカテゴリは、スマートコントラクトが「**オフチェーンで行われる処理**」に関して状態を伝えるために使用されます。
**ERC1066**において、`0xF*` は `0x0*`（一般カテゴリ）と同様に汎用的で、主に「**何がオフチェーンで起きたか**」、「**何を待っているか**」を示すために使われます。

例えば、フロントエンドでユーザーの署名を待っていたり、外部のAPIとの通信を伴う処理を開始したといったケースに、オンチェーンのロジックから明示的な状態通知を返すことができます。
これにより、スマートコントラクトが自律的にオフチェーンとの協調を判断しやすくなり、ユーザーや開発者へのフィードバックが向上します。

また、`0xFF` は「**オフチェーンの詳細（処理内容やメタデータ）**」を示すためのコードとして予約されており、具体的なオフチェーンプロセスの説明と併用されることが想定されています。

| コード       | 説明                   |
| --------- | -------------------- |
| `0xF0`      | オフチェーン処理が失敗          |
| `0xF1`      | オフチェーン処理が成功          |
| `0xF2`      | オフチェーン処理の完了を待っている    |
| `0xF3`      | オフチェーン処理を開始済み        |
| `0xF4`      | オフチェーンサービスに接続できない    |
| `0xF5`      | オフチェーンでのアクションが必要     |
| `0xF6`      | オフチェーンで期限超過または上限到達   |
| `0xF7`      | 【予約済み】               |
| `0xF8`      | 同じオフチェーンリクエストが重複している |
| `0xF9` 〜 `0xFE` | 【予約済み】               |
| `0xFF`      | オフチェーンに関する情報やメタデータ   |

### 全体マトリクス（16×16グリッドの構成）

**ERC1066**では、全体のステータスコードが16×16の構造で定義されており、カテゴリ（上位4ビット）×理由（下位4ビット）でコード体系が構成されています。
以下はその全体構成の一覧です。

|       | 0x0\* General        | 0x1\* Permission & Control | 0x2\* Find/Range    | 0x3\* Governance            | 0x4\* Time/Availability | 0x5\* Finance           | 0x6\*–0xD\* Reserved | 0xE\* Encryption         | 0xF\* Off-Chain            |
| ----- | -------------------- | -------------------------- | ------------------- | --------------------------- | ----------------------- | ----------------------- | -------------------- | ------------------------ | -------------------------- |
| 0x\*0 | 0x00 Failure         | 0x10 Disallowed            | 0x20 Not Found      | 0x30 Disagrees              | 0x40 Unavailable        | 0x50 Transfer Failed    | \[reserved]          | 0xE0 Decrypt Failure     | 0xF0 Off-Chain Failure     |
| 0x\*1 | 0x01 Success         | 0x11 Allowed               | 0x21 Found          | 0x31 Agrees                 | 0x41 Available          | 0x51 Transfer Success   | \[reserved]          | 0xE1 Decrypt Success     | 0xF1 Off-Chain Success     |
| 0x\*2 | 0x02 Awaiting Others | 0x12 Await Permission      | 0x22 Awaiting Match | 0x32 Awaiting Ratification  | 0x42 Paused             | 0x52 Awaiting Payment   | \[reserved]          | 0xE2 Awaiting Signatures | 0xF2 Awaiting Off-Chain    |
| 0x\*3 | 0x03 Accepted        | 0x13 Permission Requested  | 0x23 Match Sent     | 0x33 Offer Sent             | 0x43 Queued             | 0x53 Escrow             | \[reserved]          | 0xE3 Signed              | 0xF3 Off-Chain Started     |
| 0x\*4 | 0x04 Lower Limit     | 0x14 Insecure              | 0x24 Underflow      | 0x34 Quorum Not Reached     | 0x44 Not Yet Available  | 0x54 Insufficient Funds | \[reserved]          | 0xE4 Untrusted           | 0xF4 Off-Chain Unreachable |
| 0x\*5 | 0x05 Action Required | 0x15 Needs Permission      | 0x25 Match Request  | 0x35 Ratification Requested | 0x45 Awaiting You       | 0x55 Funds Requested    | \[reserved]          | 0xE5 Signature Required  | 0xF5 Off-Chain Action Req. |
| 0x\*6 | 0x06 Upper Limit     | 0x16 Revoked               | 0x26 Overflow       | 0x36 Vote Limit Reached     | 0x46 Expired            | 0x56 Volume Exceeded    | \[reserved]          | 0xE6 Compromised         | 0xF6 Off-Chain Expired     |
| 0x\*7 | \[reserved]          | \[reserved]                | \[reserved]         | \[reserved]                 | \[reserved]             | \[reserved]             | \[reserved]          | \[reserved]              | \[reserved]                |
| 0x\*8 | 0x08 Duplicate       | 0x18 Not Applicable        | 0x28 Conflict       | 0x38 Already Voted          | 0x48 Already Done       | 0x58 Not Required       | \[reserved]          | 0xE8 Already Signed      | 0xF8 Duplicate Off-Chain   |
| 0x\*9 | \[reserved]          | \[reserved]                | \[reserved]         | \[reserved]                 | \[reserved]             | \[reserved]             | \[reserved]          | \[reserved]              | \[reserved]                |
| 0x\*A | \[reserved]          | \[reserved]                | \[reserved]         | \[reserved]                 | \[reserved]             | \[reserved]             | \[reserved]          | \[reserved]              | \[reserved]                |
| 0x\*F | 0x0F Metadata        | 0x1F Permission Info       | 0x2F Match Info     | 0x3F Governance Info        | 0x4F Time Info          | 0x5F Finance Info       | \[reserved]          | 0xEF Crypto Meta         | 0xFF Off-Chain Meta        |

### ステータスコードを用いた関数改善の例

スマートコントラクトにおいて、関数の実行結果を `bool` 値で返すだけでは、処理が失敗した理由や具体的な状態が分かりません。
**ERC1066**では、このような場面に「**ステータスコード（status code）**」を導入することで、コントラクト外からでもより豊富な意味を読み取れるようにしています。

以下は、従来の `bool` を返す関数と、ステータスコードを返すよう改善されたバージョンの比較です。

#### 従来の関数（Before）

```js
uint256 private startTime;
mapping(address => uint) private counters;

function increase() public returns (bool _available) {
    if (now < startTime && counters[msg.sender] == 0) {
        return false;
    }

    counters[msg.sender] += 1;
    return true;
}
```

この関数は、ユーザーのカウンターを増やすかどうかを `bool` で返しますが、なぜ失敗したのかはわかりません。
`false` が返ってきても、`startTime` による制限か、`counters[msg.sender]` による制限かを区別できません。

#### 改善後の関数（After）

```js
function increase() public returns (byte _status) {
    if (now < start) { return hex"44"; } // まだ利用できない
    if (counters[msg.sender] == 0) { return hex"10"; } // 権限なし

    counters[msg.sender] += 1;
    return hex"01"; // 成功
}
```

このように改善することで、呼び出し元はそれぞれの条件に対応した処理を行えるようになります。

* `0x44` は「Not Yet Available」（まだ利用できない）
* `0x10` は「Disallowed」（許可されていない）
* `0x01` は「Success」（成功）

これにより、エラーの原因を区別し、UI表示やリトライ戦略の最適化が可能になります。

### ステータスコードを用いたシーケンス図の例

#### 例1：DEXでの購入フロー

このシーケンス図では、DEXに対して `buy()` リクエストを送信し、その状態に応じて異なるステータスコードが返されています。

```mermaid
sequenceDiagram
  participant AwesomeCoin
  participant DEX
  participant TraderBot

  TraderBot->>DEX: buy(AwesomeCoin)
  DEX-->>AwesomeCoin: buy()
  AwesomeCoin->>DEX: Status [0x44]（まだ利用できない）
  DEX-->>TraderBot: Status [0x44]

  TraderBot->>DEX: isDoneYet()
  DEX-->>TraderBot: Status [0x44]

  AwesomeCoin->>DEX: Status [0x41]（利用可能）
  DEX-->>TraderBot: Status [0x41]

  TraderBot->>DEX: buy()
  DEX-->>AwesomeCoin: buy()
  AwesomeCoin->>DEX: Status [0x31]（他者が同意済み）
  DEX-->>TraderBot: Status [0x31]
```

このやり取りでは、「**まだ購**入できない（`0x44`）**」、「購入可能になった（`0x41`）**」、「**他の参加者が同意済み（`0x31`）**」といった状態をステータスコードによって明確に表現しています。

#### 例2：トークンバリデーションフロー

複数のコントラクトが協調しながら、購入者がトークンを買える状態にあるかどうかを確認しています。

```mermaid
sequenceDiagram
  participant Buyer
  participant RegulatedToken
  participant TokenValidator
  participant IDChecker
  participant SpendLimiter

  Buyer->>RegulatedToken: buy()
  RegulatedToken->>TokenValidator: check()
  TokenValidator->>IDChecker: check()
  IDChecker-->>TokenValidator: Status [0x10]（許可されていない）
  TokenValidator-->>RegulatedToken: Status [0x10]
  RegulatedToken-->>Buyer: revert()

  Note over Buyer: ID情報が更新された後...

  Buyer->>RegulatedToken: buy()
  RegulatedToken->>TokenValidator: check()
  TokenValidator->>IDChecker: check()
  IDChecker-->>TokenValidator: Status [0x11]（許可された）
  TokenValidator->>SpendLimiter: check()
  SpendLimiter-->>TokenValidator: Status [0x11]
  TokenValidator-->>RegulatedToken: Status [0x11]
  RegulatedToken-->>Buyer: Status [0x01]（成功）
```

この例では、`0x10`（Disallowed）や `0x11`（Allowed）などを使ってアクセス制御やリミット確認を段階的に行い、処理結果に応じて次のアクションを変えています。

## 補足

#### エンコーディングとバイト構造

ステータスコードは `byte` 型（`bytes1`）として表現され、上位4ビットを「**カテゴリ（Category）**」、下位4ビットを「**理由（Reason）**」として扱います。
例えば、`0x01` は「**一般カテゴリ（`0x0`）**」の「**成功（`0x1`）**」、`0x10` は「**制御カテゴリ（`0x1`）**」の「**拒否（`0x0`）**」を意味します。

偶数（even）のコードは「**ブロッキング状態（ユーザーが自由に進めない状態）**」、奇数（odd）は「**非ブロッキング状態（ユーザーが自由に進める状態）**」として扱われるため、`status % 2 == 1` のようなシンプルなビット判定で挙動を分岐できます。

また、`bytes1` は軽量かつ `uint8` との相互運用も容易で、`enum` からのキャストにも適しており、効率的な表現が可能です。

#### 代替案との比較

他の案として `uint8` や `bytes32` も検討されましたが、それぞれに問題があります。

`uint8` はHTTPステータスコードのような可読性がある一方で、16進2桁でのカテゴリ構成（16×16マトリクス）という視認性に欠けます。
`bytes32` に複数のコードをパックする方式は理論上魅力的ですが、解釈が複雑になり、無意味な組み合わせ（例：0x00と0x01が同時に含まれる）を生む可能性があります。

そのため、単一の `byte` を戻り値の先頭に据える形式が最もシンプルで、互換性にも優れています。

#### 複数戻り値との親和性

ステータスコードは複数戻り値の最初の値として返されるのが一般的です。
これにより、HTTPレスポンスのヘッダーや、BEAM系言語におけるタグ付きタプルのように、返却値の意味を直感的に判別できます。

#### 人間に優しい可読性とカテゴリ設計

開発者が256個のコードをすべて記憶する必要はありませんが、カテゴリと理由ごとに整理された構造により、認知負荷は大きく下がります。
例えば、`0x10`（Disallowed）と `0x11`（Allowed）は同カテゴリでの対比であり、`0x04`（下限未満）と `0x24`（範囲下限未満）も理由の意味を共有しています。

この構造は、ヘルパーとして用意されているenumに頼らずとも、開発者が自然に16進数で扱う習慣を身につけられるよう配慮されています。

#### ローカライズ対応（ERC1444との連携）

**ERC1066**は人間が読むメッセージに変換するための翻訳機能を考慮して設計されています。
翻訳処理は別提案の**ERC1444**に切り出され、コードに対応する説明文や多言語対応などの役割を担います。

#### 拡張性とアプリケーション対応

`0xA*` はアプリケーション固有のステータスコード用に予約されており、個々のコントラクトやシステムに適した独自コードを定義できます。
将来的に256個のコードでは不足する場合、`bytes1[]` のような配列構造への拡張も想定されています。

#### EVMとの整合性

EVMはすでに `0x00`（失敗）と `0x01`（成功）をトランザクションのステータスコードとして採用しています。
**ERC1066**はこの意味体系と一致しており、将来的にはEVMレベルのステータス記述にも展開可能な設計となっています。

#### 空白領域の存在と意図

HTTPステータスコードと同様、**ERC1066**でも未定義のコード領域が多く残されています。
これは、将来のユースケースに対応するための余白として意図的に設けられており、柔軟な進化が可能です。

#### 単なるエラーコードではない

**ERC1066**は単にエラー状態を記録するためのものではなく、コントラクト間通信やプロトコル設計、オフチェーン処理をまたぐ情報の伝達までを視野に入れた「**ステートコードの共通言語**」です。

たとえば、HTTPにおいて `200 OK` と `201 Created` が異なる意味を持つように、`0x01`（成功）と `0x03`（受理済み）は同じ成功でも異なる意味を持ちます。これにより、スマートコントラクト間の協調がより高い表現力を持って行えます。

#### `revert` との共存性

**ERC1066**は `revert-with-reason` と完全な互換性を持ち、排他的な関係ではありません。
共通のコードとともに `revert` することで、デバッグ時のエラー判定がしやすくなります。
また、**ERC1444**などと組み合わせれば、ユーザーにとっても人間の言語で自動的に意味が解釈されるようになります。

#### ニブル順と可読性

カテゴリ（上位ニブル）と理由（下位ニブル）の順序は機械処理上は関係ありませんが、人間にとって自然な分類を意識して現在の順番に設計されています。
HTTPとは異なる方式ですが、使い慣れることで違和感なく受け入れられます。

#### ショートフォームと計算効率

`hex"01"` は `1` として扱えるため、整数との変換も容易です。
また、特定カテゴリに属する処理（例: `0x10` 系は認証・検証）では、カテゴリのプリフィックスを使って効率的にコードを構成できます。

以下はその一例です。

```js
byte constant prefix = hex"10";

if (now >= deadline)  { return prefix | 5; } // Needs your permission
if (whitelist[_user]) { return prefix | 1; } // Allowed
return prefix; // Default: Disallowed
```

このようなビット演算により、余計な条件分岐を排除しながら、意味を明示したコード返却が可能になります。

#### `enum` とアプリケーション向けコードの変換

アプリケーション固有の状態（例えば `Sleep` 状態など）を `enum` で定義した場合、ステータスコードに変換するヘルパーも簡潔に書けます。

```js
enum Sleep {
    Awake,
    Asleep,
    BedOccupied,
    WindingDown
}

function appCode(Sleep _state) returns (byte code) {
    return byte(160 + _state); // 160 = 0xA0（アプリ固有カテゴリ）
}
```

または以下のように計算式で生成することも可能です。

```js
function appCode(Sleep _state) returns (byte code) {
    return byte((16 * _state) + 10); // 10 = 0xA
}
```

これにより、`enum` との統合とガス効率の両立が図れます。

## 引用

Brooklyn Zelenka (@expede), Tom Carchrae (@carchrae), Gleb Naumenko (@naumenkogs), "ERC-1066: Status Codes [DRAFT]," Ethereum Improvement Proposals, no. 1066, May 2018. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-1066.

## 最後に

今回は「スマートコントラクト開発者が、成功や失敗だけでなく処理の詳細な状態を共通コードで表現できるようになり、コントラクト間の連携やユーザーへのフィードバックがより明確かつ自動化できる仕組みを提案している**ERC1066**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

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