# [EIP3074] 2つの新しい命令を追加しコントラクトにEOAの制御を委任する仕組みを理解しよう！

> EIP（Ethereum Improvement Proposal、イーサリアム改善提案）におけるこの提案は、EVM（Ethereum Virtual Machine、イーサリアム仮想マシン）に新たな命令セット「AUTH」と「AUTHCAL

- URL: https://cardene.dev/articles/f55a6d2df6d13030e20e
- 公開日: 2024-04-14
- 更新日: 2024-04-14
- トピック: Blockchain
- タグ: ethereum, solidity, smartcontract, ブロックチェーン

## はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、二つの新しいEVM命令AUTHとAUTHCALLを導入し、スマートコントラクトにEOAの制御を委任できるようにする仕組みを提案している**EIP3074**についてまとめていきます！

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

https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3074.md

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

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

## 概要

EIP（Ethereum Improvement Proposal、イーサリアム改善提案）におけるこの提案は、EVM（Ethereum Virtual Machine、イーサリアム仮想マシン）に新たな命令セット「`AUTH`」と「`AUTHCALL`」を導入することを提案しています。
ここでの目的は、外部所有アカウント（EOA）の制御をスマートコントラクトに委譲する機能を追加することです。

- **AUTH**
    - この命令は、ECDSA（Elliptic Curve Digital Signature Algorithm、楕円曲線デジタル署名アルゴリズム）署名に基づいて「`authorized`」というコンテキスト変数を設定します。
    - 署名が検証されると、その結果に基づいて`authorized`変数が設定されます。
    - これにより、署名者が認証されたことがEVMに知らされます。

:::message
楕円曲線デジタル署名アルゴリズム（ECDSA）は、デジタル署名を生成するための一般的な方法の一つで、特に暗号通貨やセキュリティが要求される通信でよく使用されます。
ECDSAは、楕円曲線暗号を基にしたアルゴリズムであり、公開鍵暗号方式の一種です。

#### 楕円曲線とは
楕円曲線とは、特定の代数的方程式で定義される曲線です。
ECDSAで使用される楕円曲線は、以下のような形の方程式で表されます。

```math
y^2 = x^3 + ax + b
```
ここで、$a$ と $b$ は定数で、この曲線上の点が演算の基盤となります。

#### ECDSAの主要なステップ
1. **鍵の生成**
    - 秘密鍵
        - ランダムに選ばれる数値。
    - 公開鍵
        - 楕円曲線上の点で、秘密鍵から算出される。

2. **署名の生成**
    - メッセージからハッシュ値を計算します。
    - 秘密鍵とハッシュ値を用いて、署名（通常は2つの数値のペア）を生成します。
    - この署名過程では、楕円曲線上での点の加算と乗算が用いられます。

3. **署名の検証**
    - 送信者の公開鍵とメッセージのハッシュ値、および受信した署名を使用して、署名が有効であるかを検証します。
    - 正しい公開鍵と署名が与えられれば、計算は元のハッシュ値を再生し、これによりメッセージの真正性が保証されます。

#### ECDSAの利点
- **セキュリティ**
    - 比較的小さい鍵長でも高いセキュリティを提供します。
- **効率**
    - 他の暗号方式に比べて計算効率が良い場合があります。

#### 使用例
ビットコインやイーサリアムなどの多くの暗号通貨で、トランザクションの認証や秘密保持のためにECDSAが使用されています。

ECDSAはそのセキュリティと効率から、現代のデジタルセキュリティ環境において重要な役割を担っています。
:::

- **AUTHCALL**
    - この命令は、認証されたアカウントとして別のアドレスにコール（関数呼び出しやトランザクション実行など）を行うことができます。
    - 実質的に、`AUTHCALL`は`AUTH`で設定された認証情報を使用して、認証されたアカウントの代わりに操作を行うことができるようにします。

この機能により、スマートコントラクトはユーザーの許可を得てそのユーザーのアカウントで特定のアクションを実行することが可能になります。
これは、ユーザーが直接トランザクションに署名する代わりに、信頼できるスマートコントラクトがユーザーの代理として機能する新たなパラダイムを開くことを意味します。

このような機能は、DeFiや金融サービスでの利便性とセキュリティの向上に寄与する可能性がありますが、認証メカニズムやスマートコントラクトのセキュリティ設計には細心の注意が必要です。

## 動機

このEIP（イーサリアム改善提案）は、外部所有アカウント（EOA）の機能を拡張するという長年の要求に対する新しいアプローチを提案しています。
これまでの要求には、トランザクションのバッチ処理、ガススポンサーシップ、有効期限の設定、スクリプトの実装などが含まれており、これらの追加はプロトコルの複雑さが増し、新しい要件や変更に対応することが困難になります。
また、攻撃対象領域の増加も意味している場合があります。

この提案は、これらの機能をトランザクションの有効性要件としてプロトコルに固定するのではなく、ユーザーが自身のEOAの制御をスマートコントラクトに委譲できるようにすることで、開発者にEOAのための新しいトランザクションスキームを開発するための柔軟なフレームワークを提供します。
このEIPの魅力的なユースケースの一つは、EOAがスマートコントラクトウォレットのように振る舞えるようになることであり、これにより新たなコントラクトを展開する必要がなくなります。

さらに、このEIPの主要な動機の一つは「**スポンサードトランザクション**」です。
これは、トランザクションのガス代をトランザクションを実行するアカウントとは異なるアカウントが支払う場合を指します。

:::message
スポンサードトランザクションについては以下の記事を参考にしてください。
:::

https://chaldene.net/erc20permit#st-toc-h-7

イーサリアムのブロックチェーン上でトークンを使用する場合、通常はトランザクション（送金やスマートコントラクトの実行など）を行うためにガス料金が必要です。
このガス料金はETHで支払われます。
しかし、多くのユーザーはETHを持っていない状況で、ETH以外の価値あるトークン（例えば**ERC20**トークン）を持っている場合があります。

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

https://chaldene.net/erc20

#### 問題点
ユーザーがETHを持っていない場合、彼らが持っている他のトークンをETHに変換してガス料金を支払う必要があります。
しかし、この変換自体もトランザクションを必要とするため、ETHがないとトークンをETHに変換すること自体ができません。
これが循環依存の問題です。

#### スポンサードトランザクションの解決策
スポンサードトランザクションは、この問題を解消するために提案されました。
これは、ユーザーがトランザクションを実行する時に、自分でガス料金を支払う代わりに、別のアカウント（スポンサー）がガス料金を支払う仕組みです。
スポンサーがガス料金を支払うことで、ユーザーは自分の持っているトークンをETHに変換することなく、トランザクションを実行できます。

#### 利点
- **アクセシビリティの向上**
    - ETHを持っていないユーザーも、トランザクションを行うことができるようになります。
- **柔軟性**
    - 異なる種類のトークンを持っているユーザーが、ETHの保有なしにイーサリアムのプラットフォームを利用できるようになります。

このようにスポンサードトランザクションは、ユーザーがイーサリアム上での活動をより自由に行えるよう支援し、イーサリアムエコシステムの利用者基盤を拡大する手助けとなります。

このEIPにより、ユーザーはスポンサーになることで、自分のトランザクションに必要なガス料金を支払わなくても、別のアカウントがその料金を負担することができるようになります。
これにより、資金が限られているユーザーや新規ユーザーもイーサリアムプラットフォームをより簡単に利用できるようになります。

## 仕様

#### 規則（Conventions）
- **top - N**
    - EVMスタック上で、最も最近にプッシュされた値からN番目の値を指します。
    - ここで、`top - 0`は最も最近の値です。
- **||**
    - バイトの連結演算子です。
- **invalid execution**
    - 実行が無効であり、現在の実行フレームを直ちに終了し、残りのガスをすべて消費します（スタックアンダーフローや無効なジャンプと同じ方法で）。

#### 定数（Constants）
| Constant | Value |
|----------|-------|
| MAGIC    | 0x04  |

- **MAGIC**
    - **EIP3074**署名で使用される定数で、他の署名形式との署名衝突を防ぐために用います。

#### コンテキスト変数（Context Variables）
| Variable    | Type    | Initial Value |
|-------------|---------|---------------|
| authorized  | address | unset         |

- **authorized**
    - 現在の実行フレームでの`AUTHCALL`命令のためのアクティブなアカウントを示します。
    - 設定されている場合、`authorized`にはそのコントラクトに代わって行動する許可を与えたアカウントのみが含まれます。
    - 未設定の場合、まだアクティブなアカウントが設定されておらず、`AUTHCALL`命令には使用できません。

#### コンテキスト変数のスコープ
- authorizedはプログラムカウンタと同じスコープを持ち、一つの実行フレーム内で持続しますが、任意のコール（`DELEGATECALL`を含む）を通じて渡されません。
- 同じコントラクトが異なる実行フレームで実行される場合（例えば、自己への`CALL`）、各フレームは独立した`authorized`の値を持ちます。
- 実行フレームが開始される時、`authorized`は常に未設定の状態からスタートします。
    - これは、以前の実行フレームで値が設定されていたとしても変わりません。

このEIPの導入により、スマートコントラクトはより柔軟にEOAの代わりに動作することが可能になり、ユーザーに代わって特定の操作を許可する新しい方法を提供します。

### AUTH (0xf6)

新しいオペコード `AUTH` (0xf6) についての説明です。
この命令はEVM（イーサリアム仮想マシン）のスタックから3つの要素を入力として受け取り、1つの要素を出力として返します。
この命令の目的は、特定の署名が正当であるかを検証し、検証が成功した場合には `authorized` というコンテキスト変数を設定することです。

#### 入力
`AUTH` 命令は以下のスタック要素を入力として受け取ります。

| Stack     | Value     |
|-----------|-----------|
| top - 0   | authority |
| top - 1   | offset    |
| top - 2   | length    |

また、メモリの特定範囲を指定します。
その範囲は以下のフォーマットでデータを含みます。

- `yParity`
    - `memory[offset : offset+1]`
- `r`
    - `memory[offset+1 : offset+33]`
- `s`
    - `memory[offset+33 : offset+65]`
- `commit`
    - `memory[offset+65 : offset+97]`

:::message
この命令はECDSA（Elliptic Curve Digital Signature Algorithm）署名を検証するために、メモリから特定のデータを読み込みます。

#### メモリレイアウト

##### `yParity`
- アドレス
    - `memory[offset : offset+1]`

署名の `yParity` 値を含みます。
これはECDSA署名における公開鍵のY座標が奇数か偶数かを示す値（`0`または`1`）です。
これは公開鍵の回復に使われます。
  
##### `r`
- アドレス
    - `memory[offset+1 : offset+33]`

署名の `r` 成分を含みます。
これは署名生成過程において得られる値で、署名の有効性検証に使用されます。

##### `s`
- アドレス
    - `memory[offset+33 : offset+65]`

署名の `s` 成分を含みます。
これも署名の一部で、`r` と合わせて署名の正当性を確認するのに必要です。

##### `commit`
- アドレス
    - `memory[offset+65 : offset+97]`

追加のデータを含む`32`バイトの値で、特定の条件やコンテキストにおける署名の妥当性を確認するために使用されます。
この値は、契約が事前に定義された特定の条件に従って操作を行っていることを「**証明**」するのに役立ちます。

#### 使用目的
この命令は、トランザクションやコントラクト間の相互作用において、特定のアカウントが行動を許可したことを確認するために使用されます。
たとえば、ユーザーがスマートコントラクトに特定の操作を代行させたい場合に、この署名を使ってその許可が正当であることを証明できます。署名が正しく、指定されたパラメータが予期された値であることが確認できれば、`authorized` 変数が設定され、スマートコントラクトはそのアカウントの代わりに行動することが許可されます。
:::

#### 出力
出力はスタックに戻され、以下のようになります。

| Stack     | Value   |
|-----------|---------|
| top - 0   | success |

メモリはこの命令によって変更されません。

#### 振る舞い

##### 署名の内容と検証
`AUTH` 命令は以下の情報を使用してECDSA署名を検証します。
- **yParity, r, s**
    - secp256k1 曲線上でのECDSA署名の要素です。

署名対象のメッセージは `keccak256(MAGIC || chainId || nonce || invokerAddress || commit)` です。
- `MAGIC`
  - 署名の一意性を保証するための定数（`0x04`）。
- `chainId`
  - 現在のチェーンの一意の識別子で、`32`バイトにパディングされます。
- `nonce`
  - 署名者の現在の`nonce`で、`32`バイトに左詰めでパディングされます。
- `invokerAddress`
  - `AUTH` 命令を実行しているコントラクトのアドレスで、`32`バイトまで`0`でパディングされます。
- `commit`
  - 呼び出し側のロジックにおける特定の追加の有効性条件にコミットするための`32`バイト値。

##### 署名の検証結果に基づく振る舞い
署名が有効で署名者のアドレスが `authority` アドレスと一致する場合、`authorized` 変数は `authority` アドレスに設定されます。
署名が無効または署名者のアドレスが `authority` と一致しない場合、`authorized` は未設定（リセット）されます。
`AUTH` は、`authorized` が設定されていれば`1`を返し、そうでなければ`0`を返します。

#### ガスコスト
`AUTH` のガスコストは以下の要素から構成されます。
- 固定料金
    - 3100（`ecrecover` プリコンパイルのコストとほぼ同等で、さらに keccak256 ハッシュと追加ロジックのコストが含まれます）。
- メモリ拡張ガスコスト (`auth_memory_expansion_fee`)
    - 指定されたメモリ範囲が現在の割り当て外にある場合、メモリが拡張されたときのコストです。
- `authority` がメモリに既に読み込まれている（**warm**）場合は`100`、そうでなければ（**cold**）`2600`（**EIP2929**に基づく）。

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

[\[EIP2929\] 特定のオペコードを使用する時のガスコストを増加させる提案を理解しよう！](/articles/ca94d8fd0159bb3cc9fb)

このオペコードは、スマートコントラクトが特定のアカウントの代わりに行動する許可を確認するために非常に重要であり、Ethereumのセキュリティと柔軟性を向上させる目的があります。

### AUTHCALL (0xf7)

新しいオペコード `AUTHCALL` (0xf7) は、Ethereum Virtual Machine (EVM) における既存の `CALL` (0xF1) 命令と似た振る舞いをする命令ですが、いくつかの点で異なります。この命令は、スタックから7つの要素を入力として取り、1つの要素を出力として返します。`AUTHCALL` は、既に `AUTH` 命令によって設定された `authorized` アカウントとして動作することが特徴です。

#### 入力

`AUTHCALL` 命令は以下のスタック要素を入力として受け取ります。

| Stack     | Value      |
|-----------|------------|
| top - 0   | gas        |
| top - 1   | addr       |
| top - 2   | value      |
| top - 3   | argsOffset |
| top - 4   | argsLength |
| top - 5   | retOffset  |
| top - 6   | retLength  |

#### 説明

- **gas**
    - 呼び出しに割り当てられるガス量。
- **addr**
    - 呼び出すコントラクトのアドレス。
- **value**
    - 送信するETHの量。
- **argsOffset**
    - メモリ内の引数の開始位置。
- **argsLength**
    - 引数の長さ。
- **retOffset**
    - メモリ内の戻り値の開始位置。
- **retLength**
    - 戻り値の長さ。

#### 出力

出力はスタックに戻され、以下のようになります。

| Stack     | Value   |
|-----------|---------|
| top - 0   | success |

#### 振る舞い

`AUTHCALL` は、既存の `CALL` 命令に似ていますが、いくつかの違いがあります。
この命令は、特定のアカウントが `authorized` として設定されている場合に、そのアカウントの権限で別のコントラクトを呼び出すことができます。

##### 主な違いと動作の詳細

1. **authorizedの確認**
    - `authorized` が設定されていない場合、実行は無効です。
    - これは、`AUTHCALL` が有効に機能するためには、`authorized` が事前に `AUTH` 命令などによって設定されている必要があるためです。

2. **呼び出しアドレスの設定**
    - 呼び出し元のアドレスは、`authorized` に設定されたアドレスになります。
    - これにより、`authorized` アカウントが他のコントラクトに対して直接行動を起こすかのように操作が行われます。

3. **ガスコストとガス供給**
    - ガスの計算は `CALL` 命令と同様ですが、ガスオペランドが`0`の場合は、**EIP150**に従い利用可能なガス全てが送られます。
    - 利用可能なガスがオペランドで指定されたガスより少ない場合は、実行は無効です。

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

[\[EIP150\] オペコードのガスコストを増加させる提案を理解しよう！](/articles/38750e8f3708f86bbb7a)

4. **送金とバランスの確認**
    - `value` は `authorized` アカウントのバランスから差し引かれます。もし `value` が `authorized` のバランスを超えている場合、実行は無効です。
    - ガス手当（stipend）は提供されません。
    - これは、非ゼロの値が送金される場合でも適用されます。

5. **コール深度の増加**
    - `AUTHCALL` はコール深度を1だけ増加させます。
    - `authorized` アカウントを経由してターゲットにコールするのではなく、直接ターゲットにコールするため、コール深度が2増加することはありません。

:::message
コール深度（call depth）は、Ethereum Virtual Machine (EVM) におけるトランザクション実行時のコンテキストスタックの深さを表します。
これは、スマートコントラクトが他のコントラクトを呼び出す際に重要となる概念です。

#### コール深度とは何か？

EVMにおいて、トランザクションがスマートコントラクトを実行すると、最初の実行レベルが開始されます。
この時点でのコール深度は`0`です。
スマートコントラクトが他のコントラクトを呼び出すたびに、新しい実行フレームがスタックにプッシュされ、コール深度が`1`増加します。
つまり、あるコントラクトが別のコントラクトを呼び出すと、コール深度は`1`になり、その呼び出されたコントラクトがさらに別のコントラクトを呼び出すと、コール深度は`2`になる、という具合です。

#### コール深度の上限

EVMでは、コール深度の上限が`1024`に設定されています。
この限界を超えると、その呼び出しは単に失敗し、実行されないことになります。
この規則は、スタックオーバーフロー攻撃などのセキュリティリスクを防ぐために設けられています。

#### コール深度の影響

コール深度は、特にガスの消費やトランザクションの複雑性に影響を与えます。
深いコールチェーンは、それぞれのレベルでガスを消費し、トランザクションのコストを増大させます。
また、深いコールチェーンを持つトランザクションは、エラーの発生やデバッグの難しさを増す可能性があります。

#### コール深度の管理

スマートコントラクトを設計する時には、コール深度を適切に管理することが重要です。
特に、複数のコントラクト間で相互に呼び出しを行うような設計の場合、予期せぬ深さまでコールが続くことがあり、それによりトランザクションが失敗するリスクが高まります。
したがって、可能な限りフラットな構造を保持し、不要な外部呼び出しを避けることが望ましいです。
:::

6. **戻りデータの取り扱い**
    - `RETURNDATASIZE` と `RETURNDATACOPY` によってアクセスされる戻りデータエリアは、`CALL` 命令と同じ方法で設定されます。

7. **authorizedのリセット**
    - 重要な点として、`AUTHCALL` の実行後に `authorized` はリセットされず、変更されないまま残ります。

これらの特徴により、`AUTHCALL` はスマートコントラクトが他のアカウントの権限を借りて操作を行うことを可能にし、複雑な交渉や条件付きの取引を実行するための柔軟性を提供します。

#### ガスコスト

`AUTHCALL` のガスコストは、いくつかのコンポーネントの合計で構成されます。
これには静的なガスコスト、メモリ拡張に関連するガスコスト、動的なガスコスト、およびサブコール実行に使用可能なガスが含まれます。

##### ガスコストの計算

- **静的ガスコスト (`warm_storage_read`)**
    - これは、既にアクセスされたアドレスやデータを読み取るために必要な基本的なガスコストです。

- **メモリ拡張ガスコスト (`memory_expansion_fee`)**
    - `CALL` 命令と同じ方法で計算され、メモリの使用量が増加する場合に追加のガスコストが発生します。

- **動的ガスコスト (`dynamic_gas`)**
    - 初期値は`0`ですが、以下の条件によって増加します。
        - 対象のアドレス `addr` が以前にアクセスされていない場合（`cold_account_access`）、動的ガスコストに`2500`が加算されます。
        - 送金額 `value` が`0`より大きい場合、`6700`が加算されます。
        - さらに、対象のアドレスが空（コントラクトがデプロイされていない）である場合は、`25000`が加算されます。

- **サブコールで実行可能なガス (`subcall_gas`)**
    - 利用可能なガスから動的ガスコストを差し引いた残り (`remaining_gas`) から、その`1/64`を除いた量 (`all_but_one_64th`) を計算します。
    - もし `gas` オペランドが`0`であれば、`subcall_gas` は `all_but_one_64th` 全量に設定されます。
    - これは**EIP150**に基づき、サブコールに可能な限り多くのガスを割り当てるためです。
    - `gas` オペランドが`0`ではなく、`all_but_one_64th` が `gas` より少ない場合、実行は無効となりエラーが発生します（例外が投げられます）。
    - それ以外の場合、`subcall_gas` は `gas` に設定されます。

:::message
Ethereum Virtual Machine（EVM）における`gas`オペランドは、スマートコントラクトの実行時に非常に重要な役割を果たします。
`gas`はEthereumネットワークにおける計算資源の消費を制御し、スマートコントラクトの実行に必要な計算やストレージ操作に対する料金をユーザーが支払う方式です。
各トランザクションや関数呼び出しにおいて、実行に必要な`gas`の量を指定することで、その操作がどれだけの計算リソースを消費するかを制御します。

#### `gas` オペランドの概要

`gas`オペランドは、スマートコントラクトの各命令が実行される際に消費される`gas`の量を指定します。
これにより、トランザクションの実行コストと時間を管理し、ネットワークの過負荷を防ぎます。
`gas`の料金は、`gas`の価格（`gas price`）と消費された`gas`の量に基づいて計算されます。
トランザクションを送信する時、ユーザーは`gas price`を指定することができ、これによりトランザクションの優先度が決定されます。

#### `gas` オペランドの使用方法

##### トランザクションの`gas`
トランザクションを送信する時、`gas limit`（トランザクションによって消費される最大の`gas`量）と`gas price`（単位`gas`あたりの料金）を設定します。
`gas limit`はそのトランザクションが消費可能な`gas`の上限を示し、これを超えるとトランザクションは「**Out of Gas**」エラーになります。

##### 関数呼び出しの`gas`
関数を呼び出す時にも、どれだけの`gas`を割り当てるかを指定できます。
特に重要なのは、他のコントラクトを呼び出す際や複雑な計算を行う場合です。

#### `gas` オペランドの重要性

- **セキュリティ**
    - `gas`システムにより、悪意のあるユーザーやバグを持つコントラクトによる無限ループや過度の計算が防がれ、ネットワークの安全性が保たれます。
- **効率**
    - `gas`を使用することで、ブロックチェーンの各ノードがどれだけの計算を行うべきかを予測でき、システムの全体的な効率が向上します。
- **エコノミクス**
    - `gas`はEthereumネットワークの経済システムの一部であり、マイナーにとっての報酬となり、ネットワークの維持・運営を動機付けます。

`gas` オペランドの理解と適切な管理は、Ethereum上で効果的かつ経済的にスマートコントラクトを運用するために不可欠です。
:::

##### ガスコストの請求
`CALL` 命令と同様に、`AUTHCALL` でもガスコストはコールが実際に実行されるかどうかにかかわらず、直ちに全額が請求されます。
これは、EVMがサブコールを行う前に必要なガスを保証するためです。

これらのルールにより、`AUTHCALL` はガスの使用とコールの管理を厳密に行いながら、`authorized` アカウントの権限の下で他のコントラクトを呼び出すことが可能になります。
これによって、スマートコントラクトが他のアカウントの資源を効果的に利用し、複雑なインタラクションを行う能力が強化されます。

## 補足

### 署名形式とメモリの利用

#### 署名形式の柔軟性
`AUTH` 命令が動的なメモリ範囲を受け入れるのは、将来的にコントラクトアカウント（非ECDSA署名を使用する可能性がある）にも対応可能にするためです。
現在は外部所有アカウント（EOA）のみがサポートされていますが、これにより将来的に異なる署名スキームに対応できるようになります。

### 署名アドレスの扱い

#### authority引数の含意
`authority`（署名アドレス）を `AUTH` 命令の引数として含めることで、将来のアップグレード時にコントラクトアカウントとEOAの両方に対応できるように設計されています。
複数の署名スキームが許可される場合、署名だけから承認アカウントのアドレスを計算することは不可能になります。このため、`authority` は署名者のアドレスを指定するために必要です。

### 利用可能なガスの割当て

#### 利用可能なガスの予約
`AUTHCALL` は**EIP150**に従って、利用可能なガスの`63/64`以上をサブコールに渡すことはありません。
これは、ガスの消費を制御し、呼び出しの深さによる問題を避けるためです。

### `authorized` 未設定時の処理

#### 未設定の `authorized` に対するエラー処理
コントラクトが `AUTHCALL` を実行する前に `authorized` が正しく設定されているべきです。
`authorized` が設定されていない状態で `AUTHCALL` を実行しようとすると、現在の実行フレームを直ちに終了させるのが最も安全な振る舞いです。
この振る舞いは、トランザクションのスポンサー／中継に関連して特に重要であり、スポンサーと受け手（sponsee）の間で責任を明確に区別する必要があります。
誤ったサブコールや `AUTH` の失敗など、スポンサーに起因する問題が受け手に不公平な料金を課すことを防ぐためです。

### 新しいトランザクションタイプの導入

このアプローチでは、新しいトランザクションタイプを導入して、手数料の支払いを行うアカウントと実際のアクションを起こすアカウントを分離します。
この方法はクライアントの大規模な変更を必要とし、アップグレードが他のソリューションよりも困難です。
アカウント抽象化（Account Abstraction, AA）との互換性がすぐには得られないという問題もあります。
AAコントラクトはプライベートキーを持たないため、スポンサーのアカウントからの署名済みトランザクションを発行することができません。
新しいトランザクションタイプの主な利点は、有効性要件がプロトコルによって強制されるため、無効なトランザクションがブロックスペースを汚染しないことです。

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

[\[ERC4337\] プロトコルの変更をせずにAAを実装する仕組みを理解しよう！](/articles/8c97ca7c93c4557ebfc2)

### EVM内での新メカニズムの導入

このアプローチでは、EVMに新しいメカニズムを導入して、他のアカウントとして動作する機能（masquerade）を提供します。
`AUTH`と`AUTHCALL`は、外部所有アカウント（EOA）としてコールを行う機能を実現します。
これは、コントラクトアカウントがより直接的にETHを送受信できるようにするなど、将来の展開に対する即時の利点があります。
この方法は、新しいトランザクションタイプを導入するよりも侵襲性が低く、既存のウォレットやその他のツールに対する変更が少なくて済みます。
`AUTHCALL`のCALLからの唯一の逸脱は、`CALLER`を設定することであり、スポンサードトランザクションのための送信者抽象化を実現する最小限の機能を実装します。

### 署名と信頼性

#### 初期の提案とその問題点

最初の提案では、ノンス（トランザクションごとに一意に増加する数値で、トランザクションの一意性を保証する）を追跡するために、プリコンパイルされた（つまり、ブロックチェーンに予め組み込まれた）ストレージを持つスマートコントラクトの使用が検討されました。
しかし、この方法はEthereumにとって前例のないものであり、技術的な複雑さやセキュリティリスクが懸念されました。

#### 変更されたアプローチ

これらの問題を解決するため、リプレイ保護の機能は個々の契約者（invoker）に委ねることになりました。
これにより、ノンスの管理は各invokerコントラクトが行うことになり、システム全体としての複雑さを軽減します。

#### ユーザーとinvokerの信頼関係

##### 署名とinvokerの結びつき
ユーザーがトランザクションに署名する時には、その署名が特定のinvokerにのみ関連付けられるようになっています。
これは、署名が特定のコントラクトのコンテキスト内でのみ有効であることを意味し、他のinvokerがその署名を不正利用することを防ぎます。

##### ユーザーの安心感
ユーザーは、自分が信頼するinvokerを選択することができ、そのinvokerがトランザクションを適切に管理し、自分の意図した通りにトランザクションが実行されることを信頼できます。
これにより、ユーザーは自分のトランザクションが正確に処理されることを確信できます。

このように、スポンサードトランザクションにおいてリプレイ保護（既に実行されたトランザクションが再び悪意を持って実行されることを防ぐためのメカニズム）の管理は、よりシンプルでセキュリティが確保された方法へと進化しています。
ユーザーは特定のinvokerとの関係を通じて、自分のトランザクションの安全を確保することができるようになりました。

### Commit 機能の理解

#### コミットの役割
ユーザーは特定のトランザクション（またはコール）のプロパティ（例えば、送金額やガス量など）に対して「**コミット**」します。
これは、トランザクションの特定の詳細に対するハッシュ値を計算することによって行われます。
このハッシュ値（コミット値）は、トランザクションが実行される前にその値が検証され、承認されることをユーザーが保証するために使用されます。
これにより、リプレイ攻撃などに対する保護が可能になります。

![auth-msg.png](/images/qiita-13dfa116-da17-f66f-4827-6186c1ac3a1e.webp)
引用: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3074.md

#### 拡張可能性
コミット機能を使用することで、インボーカー（呼び出しを管理するコントラクト）は任意の制約を実装することができます。
例えば、複数のノンスを並行して管理することや、単一の署名で複数のコールにコミットすることが可能です。
これにより、複数のトランザクションフローを単一のトランザクションにまとめることができ、例えば**ERC20**の`approve`と`transfer`を一つの署名で実行できるようになります。

![auth-msg-multi-call.png](/images/qiita-5a1c626a-c11b-a2c5-efce-e1664ddea739.webp)
引用: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3074.md


### Invoker Contracts

#### インボーカーコントラクトの役割
インボーカーコントラクトは、スポンサーとスポンシー（手数料の支払いを受ける側）の間の信頼できる中間者として機能します。
スポンシーは、信頼できる特定のコントラクトだけが自分のトランザクションを処理するように要求するために、インボーカーに署名します。
これにより、スポンシーはスポンサーを信頼する必要なく、安全にトランザクションを実行することができます。

#### セキュリティ上の配慮
インボーカーコントラクトは、アップグレード可能であってはならず、一度デプロイされたコードは変更されるべきではありません。
アップグレード可能なインボーカーは、悪意のあるコードに置き換えられるリスクがあり、セキュリティ上の脆弱性を引き起こす可能性があります。

### コール深度とガスの管理

EVMはネストされたコールの最大数を制限しており、スポンサーがコール深度を操作してインボーカーに到達する前に深度を増加させることは、スポンシーに対する妨害攻撃となり得ます。
しかし、`63/64`のガスルールとAUTHCALLのコストを考慮すると、実際のコールスタックはガスパラメータによってかなり制限されます。
したがって、インボーカーは最小限のガス量を保証するだけで十分であり、合理的なガス量ではハードマキシマムのコール深度に到達することはありません。

### 途中でのEOAからの値の控除

#### トランザクションプールの不変性
以前は、トランザクション実行中に外部所有アカウント（EOA）から値を控除することが問題視されていました。
これは、トランザクションプールがトランザクションの有効性を静的に決定できるという不変性に基づいています。

#### 不変性の破壊
さらなる調査により、この不変性を破っても安全であることが判明しました。
特に、攻撃者が多数のトランザクションをキューに入れ、それらを一度に無効にする攻撃が理論的には可能ですが、ネットワーク全体に対する実質的な影響は小さいため、問題視されていません。

### `tx.origin` を署名者として許可

#### `tx.origin` を署名者として許可する利点

##### トランザクションバッチ処理の簡素化
`tx.origin`を`authorized`と等しく設定することで、外部トランザクションの送信者が署名アカウントとなります。
これにより、例えば**ERC20**トークンの承認（`approve`）とその後の転送（`transfer`）を別々のトランザクションで行う必要がなくなり、一つのトランザクションで完了できるようになります。

#### `tx.origin` 使用に関するセキュリティ上の懸念

##### スマートコントラクトへの影響
**EIP3074**により、`AUTH`および`AUTHCALL`を通じて`msg.sender == tx.origin`が複数の実行層で成立する可能性があります。
これは通常、トランザクションの最上位層でのみ発生する状況で、`require(msg.sender == tx.origin)` チェックを含むスマートコントラクトに影響を与えます。

##### セキュリティチェックの使用例

- **EOA確認**
    - `msg.sender`がEOAであることを確認するために使用されます。
    - このチェックは、実行層の深さに依存しないため、この提案によって影響を受けません。
- **アトミックサンドイッチ攻撃防止**
    - このような攻撃は、ターゲットコントラクトの実行前後に状態を変更することに依存します。
    - このEIPによりこの保護が破られる可能性がありますが、`tx.origin`をこのように依存することは一般的に悪い実践と見なされています。
   - **リエントランシー防止**
       - この提案は、特にこの形式のリエントランシー保護に影響を与える可能性がありますが、この形式の保護を使用している例は見つかっていません。

#### 解決策と軽減策

##### 他のアプローチ
`tx.origin`を定数のENTRY_POINTアドレスやinvokerアドレスに設定する。
`tx.origin`を送信者、invoker、または署名者のアドレスから導出された特別なアドレスに設定する。
`authorized == tx.origin`を禁止する（ただし、将来的にはこの制限を緩和する可能性がある）。

これらのポイントは、`tx.origin`を使用することの潜在的な利点とリスクを総合的に評価するために重要です。

### セキュリティリスクと対策

#### atomicサンドイッチ攻撃
`tx.origin` の使用は、atomicサンドイッチ攻撃（特定のコントラクトの前後で状態を変更する攻撃）に対する保護を弱める可能性がありますが、これは一般的に悪い実践と見なされています。

:::message
「**アトミックサンドイッチ攻撃**」は、ブロックチェーンおよびスマートコントラクトのセキュリティに関連する特定のタイプの攻撃手法です。
この攻撃は、特にEthereumのようなプラットフォームで見られる問題で、攻撃者が特定のトランザクションの前後で自分のトランザクションを挿入することによって、ターゲットとなるトランザクションの結果を操作します。

#### アトミックサンドイッチ攻撃の仕組み

1. **トランザクションの観察**
    - 攻撃者は、ブロックチェーンネットワーク上で特定のトランザクションを観察します。
    - これは通常、大きな資産の移動や重要なコントラクト関数の実行を伴うトランザクションです。

2. **アトミックな挿入**
    - 攻撃者は、対象となるトランザクションの直前に自分のトランザクションを配置し、対象トランザクションの直後にもう一つのトランザクションを配置します。
    - これにより、攻撃者は対象トランザクションの実行環境を事前に操作し、実行後の状態も利用できるようになります。

3. **状態の操作**
    - 最初のトランザクションで、攻撃者はターゲットトランザクションが依存する状態を変更することができます（例えば、市場価格や流動性プールの残高など）。
    - 対象トランザクションが実行された後、攻撃者は再び状態を操作して、元のトランザクションから利益を得るためのアクションを実行します。

#### アトミックサンドイッチ攻撃の例

##### 価格操作
分散型金融（DeFi）プラットフォームにおいて、攻撃者はスリッページ（価格の滑り）を利用して、ある資産の価格を意図的に上げたり下げたりします。
これにより、その価格変動を利用して不正な利益を得ることが可能になります。

##### フラッシュローン攻撃
攻撃者はフラッシュローン（短期間に大量の資金を借りることができる仕組み）を利用して大量の資産を借り、市場に影響を与えるトランザクションを挟みます。
その後、資産を返却する前に、市場の操作から利益を得ることができます。

#### 防御策

##### トランザクション順序のランダム化
マイナーやブロック生成者によるトランザクションの順序をランダムにすることで、このタイプの攻撃の効果を軽減することができます。

##### スリッページ保護
ユーザーがトランザクションを発行する際に、許容するスリッページの量を設定することで、価格操作の影響を受けにくくすることができます。

アトミックサンドイッチ攻撃は、特にDeFi領域で懸念される問題であり、ユーザーとプラットフォームはこのタイプのリスクを理解し、適切な防御策を講じることが重要です。
:::

#### 再帰性の防止
`msg.sender == tx.origin` のチェックは再帰的な呼び出しを防ぐために使用されることがありますが、この提案ではその有効性が低下する可能性があります。
しかし、再帰性を防ぐ他の方法が存在します（例えば、ストレージ変数の使用）。

### その他の提案された解決策

#### `tx.origin` の設定変更
`tx.origin` を固定のエントリーポイントアドレスやインボーカーアドレスに設定することで、不変性を維持しつつ制限を緩和することが提案されています。


### AUTHCALL と CALL の比較

#### コストの違い
`CALL`命令で非ゼロの値を送信する場合、そのコストは追加で`9,000`ガス増加します。
このうち`6,700`はバランス転送のオーバーヘッドをカバーするため、残りの`2,300`はサブコールのガスカウンターを種付けするための手当（stipend）として使用されます。
`AUTHCALL` はサブコールに対して手当を提供しないため、基本的な`6,700`のみが使用されます。

#### インプロトコルリボケーション（In-Protocol Revocation）

##### リボケーションの必要性
`AUTH`メッセージのリボケーションがない場合、このEIPは開発者にとって非常に強力で柔軟なプリミティブを提供しますが、安全でないまたは悪意のあるインボーカーを使用するユーザーにとってはリスクが伴います。
ユーザーが単一のトランザクションで多くの操作をバッチ処理できる新しい能力により、アカウントから資金が抜かれるリスクが高まります。
このリスクは、プロトコルレベルおよびアプリケーションレベルでのサポートが試みられることにより、このEIPの採用に関わらず増加し続けるでしょう。

##### リプレイ保護とセキュリティリスク
インボーカーがリプレイ保護を実装している場合、それによってリスクの影響範囲が大幅に制限されるはずです。
しかし、バグが敵にリプレイ保護メカニズムを迂回することを許す場合、それは敵に脆弱なインボーカーと相互作用した任意のEOAへの完全なアクセスを与えるかもしれません。

##### ノンスとリボケーション
プロトコル内でのリボケーションがないため、ユーザーは自分のアカウントを脆弱なインボーカーから削除する方法がありません。
このため、`AUTH`はメッセージ内のノンスが署名者の現在のノンスと一致することを要求します。
これにより、EOAからの単一のトランザクションがノンスを増加させ、すべての未処理の承認を無効にします。

## 互換性

### 背景

現在のEthereumアカウントモデルには、外部所有アカウント（EOA）とスマートコントラクトアカウントの2種類があります。
EOAはプライベートキーによるECDSA署名で識別され、トランザクションを認証します。

### 懸念点

#### 将来的なアカウントモデルの変更
このEIPは、ECDSA署名に依存していますが、将来的にはEOAの概念を完全に取り除き、同じ振る舞いをエミュレートするスマートコントラクトウォレットに置き換えることが望ましいかもしれません。
この変更が実施されると、ユーザーはさらに進んで、例えばマルチシグ（複数の署名による認証）など、他の認証方法に「**アップグレード**」する選択肢を持つことになります。

#### 旧来の認証方法の持続的使用
現在のEIPの実装では、スマートコントラクトウォレットが他の認証メソッドにアップグレードされた場合でも、AUTHは古いプライベートキーによるアクションを許可し続ける可能性があります。
これは、新しいロジックがAUTHによって尊重されないため、セキュリティ上の問題を引き起こす可能性があります。

### 提案された解決策

#### AUTHのロジックの修正
EOAsが削除される時に、AUTHのロジックを修正して、アカウントに対して標準的なメッセージを呼び出し、そのアカウントが署名または証人が有効であるかを判断させるようにする提案があります。
これにより、AUTHはアカウントの新しい認証ロジックを尊重することができ、より柔軟で将来に対応した方法で動作する可能性があります。

### 今後の研究の必要性

この変更がどのようにインボーカーに影響を与えるか、そしてインボーカーを将来にわたってどのように設計するのが最善かについてさらに研究を行う必要があります。
これは、Ethereumのアカウントおよび認証システムの将来の進化に適応するために重要です。

## セキュリティ

### セキュアなインボーカー

インボーカーはスマートコントラクトを介してユーザーの命令を実行するエンティティですが、セキュリティが確保されていないと大きなリスクを招く可能性があります。

#### リプレイ保護

インボーカーはリプレイ攻撃を防ぐためにノンスを実装し、コミットに含める必要があります。
これにより、悪意あるアクターが同じ署名を再利用して同じアクションを繰り返すことを防ぎます。

#### 値のコミット:
トランザクションで転送される値（`value`）はコミットに含めるべきです。
これにより、スポンサーが意図しない効果を引き起こすことを防ぎます。

#### ガスのコミット
ガス量もコミットに含めることが重要です。
これにより、スポンサーが意図的にガスを使い果たさせてトランザクションを失敗させることを防ぎます。

#### アドレスとコールデータ
トランザクションの宛先アドレス(`addr`)とコールデータ(`calldata`)もコミットに含めるべきです。
これにより、悪意あるアクターが任意の関数を任意のコントラクトで呼び出すことを防ぎます。

### `tx.origin` としての署名者の許可

`tx.origin`を`authorized`と同じに設定することは、以下のリスクを含みます。

#### atomicサンドイッチ攻撃の防御の破壊
`tx.origin`が署名者として使用されると、atomicサンドイッチ攻撃を防ぐための保護が破壊される可能性があります。
これは、トランザクションの前後で状態を変更する攻撃に対する防御が弱まるためです。

#### リエントランシー防御の破壊
`require(tx.origin == msg.sender)`スタイルのリエントランシー防御が破壊される可能性があります。
この提案では、リエントランシー防御に依存しているコントラクトが影響を受ける可能性があります。

### スポンサードトランザクションリレイヤー

スポンサードトランザクションリレイヤーは、トランザクションの手数料を代行して支払いますが、以下のリスクがあります。

#### 認証の無効化
承認されたアカウントが自身のノンスを増加させることで認証を無効にし、リレイヤーがガスを無駄に消費させる可能性があります。

#### 資産の払い出し
承認されたアカウントが関連する資産を払い出すことにより、リレイヤーがガスを無駄に使う可能性があります。

これらのリスクを緩和するために、リレイヤーは担保の預入れや評判システムの導入など、潜在的な損失を考慮に入れた設計を検討する必要があります。

## 最後に

今回は「二つの新しいEVM命令AUTHとAUTHCALLを導入し、スマートコントラクトにEOAの制御を委任できるようにする仕組みを提案している**EIP3074**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下の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
