---
title: "ERC-4337のダミー署名とガストークン転送"
description: "ダミー署名とダミーのpaymasterAndData値を使用して、user operationのガス見積もり時にpreVerificationGasとverificationGasLimitフィールドを取得する方法を解説します。"
---

# ERC-4337のダミー署名とガストークン転送

[ERC-4337 Gas Estimation](https://www.alchemy.com/blog/erc-4337-gas-estimation)では、ERC-4337でガスがどのように機能するか、そして我々のガス見積もり手法について解説した。この手法により、ユーザーがuser operationを送信する際に正確な値を提供できるはずだ。しかし、それほど単純ではない。

ここでは、ERC-4337のガス見積もりを複雑にする他のいくつかの問題を見ていく。

## ダミー`signature`値とは何か

ほとんどのスマートコントラクトアカウント実装では、signatureフィールドはuser operationをハッシュ化し、そのハッシュを何らかの署名方式（最も一般的なのはECDSA）で署名することでオフチェーンで計算される。この署名は、検証フェーズにおいてアカウントコントラクトによってオンチェーンで検証される。

例えば、`SimpleAccount`は[EIP-191](https://eips.ethereum.org/EIPS/eip-191)署名方式を[使用](https://github.com/eth-infinitism/account-abstraction/blob/d1333cf58c17d5cc84e830f3fc3a69081c777979/contracts/samples/SimpleAccount.sol#L93)しており、[OpenZeppelin](https://www.alchemy.com/dapps/openzeppelin)の[ECDSA library](https://docs.openzeppelin.com/contracts/2.x/api/cryptography#ECDSA-toEthSignedMessageHash-bytes32-)を用いて`validateUserOp`関数内でオンチェーン検証されるハッシュに対して署名を行う。

この署名はガス見積もり後に計算されなければならない。なぜなら、それらのフィールドはハッシュに含まれるからだ。

しかし、ガス見積もりのステップの中にはsignatureフィールドが埋まっていることを要求する部分がある：`preVerificationGas`と`verificationGasLimit `である。

### preVerificationGas

本シリーズのpart oneにある`preVerificationGas`見積もりのセクションで、bundlerが計測不能なガスを計上するために使う3つの計算について解説した。

ステップ2と3（user opのcalldataガスコストに占める割合の計算と、実行ガスオーバーヘッドに占めるuser opの割合の計算）は、いずれもuser operationの長さと内容に直接依存しており、`signature`フィールドもこれに含まれる点に注意してほしい。

### verificationGasLimit

有用なスマートコントラクトアカウント実装のほぼすべてが何らかの署名検証を必要とする。このガスは見積もる必要がある。この見積もりプロセスはrevertしてはならず、そうでなければverification gasを実装できない。

どの署名を使うべきかをどうやって選ぶのか？

## ダミーsignature値の計算方法

これらの問題を解決するため、多くの[ERC-4337 bundler](https://www.alchemy.com/overviews/what-is-a-bundler)は、アカウントの種類に応じて`eth\_estimateUserOperationGas`の呼び出し元が提供する必要がある「Dummy Signature」を使用する。

### 制約

このダミー署名にはいくつかの制約がある：

1. ダミー値の長さは最大署名長と等しくなければならず、そのアカウントで有効な非ゼロバイト数の最大数を含まなければならない。
   a. これにより、`preVerificationGas`の計算がcalldataへの寄与とentry pointのオーバーヘッドコストについて最悪ケースの署名を考慮できるようになる。
1. ダミー値は、アカウントのvalidation関数に渡された際に最悪ケースのガス使用量を引き起こさなければならず、revertを引き起こしてはならない。
1. ダミー値は、いかなる有効なuser operationに対しても有効な署名であってはならない。

`SimpleAccount`用のダミー`signature`値は、[eth_estimateUserOperationGas](https://www.alchemy.com/docs/wallets/api-reference/bundler-api/bundler-api-endpoints/eth-estimate-user-operation-gas)メソッドに関する我々のドキュメントに記載されている。

**このダミー署名は以下の特性を持つ：**

1. ECDSA署名の正確な長さである
1. ECDSA署名で許容される非ゼロバイト数の最大数を持つ
1. 有効なECDSA署名である（そのため`.recover\(\)`の呼び出しがrevertしない）
1. 既知のuser operationに対する署名ではないため、`SimpleAccount`は常に`SIG\_VALIDATION\_FAILED`を返す

アカウント実装者は、ダミー署名を供給できるようにvalidation関数を書く必要がある。

**これは以下を意味する：**

1. ダミー署名になり得ない署名に対してのみ`REVERT`を使用する。ダミー署名が供給された場合は`SIG\_VALIDATION\_FAILED`を返す。
1. ダミー署名に対する失敗の「ショートサーキット」を起こさないよう注意する。つまり、ダミー値はvalidation関数全体を通過し、最大量のガスを使用するべきである。
1. 実際には、これは早期returnを取り除くことを意味する。アカウントのvalidation関数が署名が無効であることを早期に判断することはあり得るが、関数のロジックは最後まで実行し続け、最後に失敗を返すべきである。

## ダミー`paymasterAndData`値の計算方法

上記と同じ要件が、ガス見積もり中の`paymasterAndData`フィールドにも適用される：ガスフィールドの値に依存するpaymaster実装（署名の計算などのために）であれば、ダミー値を供給するという同じ問題を解決しなければならない。

### 制約

このダミー`paymasterAndData`にはいくつかの制約がある：

1. ダミー値の長さは最大`paymasterAndData`長と等しくなければならず、そのアカウントで有効な非ゼロバイト数の最大数を含まなければならない。
   a. これにより、`preVerificationGas`の計算がcalldataへの寄与とentry pointのオーバーヘッドコストについて最悪ケースの`paymasterAndData`を考慮できるようになる。
1. ダミー値は、paymasterのvalidation関数に渡された際に最悪ケースのガス使用量を引き起こさなければならず、revertを引き起こしてはならない。
1. ダミー値は、いかなる有効なuser operationに対しても有効な`paymasterAndData`であってはならない。

例えば、user operationハッシュに対するスポンサーシップ署名の検証に依存する[sponsoring paymaster](https://www.alchemy.com/overviews/what-is-a-paymaster)は、見積もり時に上記と同様の特性を持つダミー`paymasterAndData`値を供給する必要がある：

1. ダミー値は有効なpaymasterコントラクトアドレスを含まなければならない
1. `preVerificationGas`の計算のための最大長と最大バイト値
1. paymasterのvalidation関数に渡された際、最大ガスを消費し、`SIG\_VALIDATION\_FAILED`のreturn値をもたらさなければならない

Paymaster実装者は、ダミー`paymasterAndData`を供給できるようにvalidation関数を書く必要がある。

**これは以下を意味する：**

1. ダミーの一部になり得ないデータに対してのみ`revert`を使用する。代わりに` SIG\_VALIDATION\_FAILED`を返す。
1. ダミーに対する失敗の「ショートサーキット」を起こさないよう注意する。つまり、ダミーはvalidation関数全体を通過し、最大量のガスを使用するべきである。
   a. 実際には、これは早期returnを取り除くことを意味する。paymasterのvalidation関数が署名が無効であることを早期に判断することはあり得るが、関数のロジックは最後まで実行し続け、最後に失敗を返すべきである。

## ガストークンの転送

`verificationGasLimit`の見積もりでは、検証フェーズ中のトークン転送のガスコストを考慮しなければならない。多くの[user op](https://www.alchemy.com/overviews/user-operations)は、ガスの前払いのためにトークン転送を行い、操作の最後に消費されなかったガス分の返金を行う。

これには2つのケースがある：

1. Paymasterなし - senderからentry pointコントラクトへのETH転送となる。
1. Paymasterあり - 仕様の許容範囲内であれば何でもよいが、多くの場合senderからpaymasterへのERC-20トークン転送の形をとる。

#### アカウントに十分な資金がない場合どうなるか

`maxFeePerGas`が非ゼロ値に設定されている場合、アカウントが手数料を支払うのに十分なトークンを保有していなければ、検証中の転送はrevertする。つまり、ユーザーはガス見積もりを試みる前にアカウントに資金を入れておかなければならないということだ。

**現時点では実現できない望ましいワークフロー：**

1. ガスを見積もる
1. ガス用にアカウントに資金を入れる
1. operationを送信する

ここでの解決策の一つは、`eth\_estimateUserOperationGas`呼び出し時に`maxFeePerGas`を未設定のまま、またはゼロに設定するようユーザーに伝えることだ。しかし、これによりガスコストがゼロになり、発生すべきトークン転送の値もゼロになってしまう。[多くのアカウント/paymasterの種類](https://github.com/eth-infinitism/account-abstraction/blob/d1333cf58c17d5cc84e830f3fc3a69081c777979/contracts/core/BaseAccount.sol#L101)では、ガスコストがゼロだと`transfer`への呼び出しがスキップされる。これにより、ゼロの`maxFeePerGas`が使われた場合にガスの過小見積もりが発生する。

もう一つの問題は、非ゼロの`maxFeePerGas`を使用し、本シリーズpart 1の「[Attempt 3: Binary Search](https://www.alchemy.com/blog/erc-4337-gas-estimation)」で定義されたbinary search見積もりアプローチを試みることに関係する。

そのアプローチの最初のステップは、最大ガス値を使用してoperationが可能であることを確認することだ。senderはその最大値でガスを支払うのに十分な資産を持っていない可能性があり、bundlerは手数料トークン（ERC-20 paymasterのケースなど）の残高を判断するのに十分な情報を常に持っているわけではないため、正しい上限を決定できない。

### Alchemyのbundlerはトークン転送を伴うガス見積もりをどう解決しているか

`eth\_estimateUserOperationGas`に対してRundlerが採用しているアプローチは以下の通りだ：

#### Paymasterなしのケース

- Rundlerは`maxFeePerGas`と`maxPriorityFeePerGas`を常に無視し、0に設定する。
- Rundlerは、senderからentry pointへのETHデポジット転送を考慮するため、`verificationGasLimit`に常に10Kガスを静的に加算する。
- クライアント側の変更は不要である。

<CalloutBlock>

💡 箇条書き＃1は、「gas limits（および価格）パラメータは任意だが、指定された場合は使用される」と定めているERC-4337仕様からの逸脱である

</CalloutBlock>

#### Paymasterありのケース

- Rundlerは`maxFeePerGas`と`maxPriorityFeePerGas`を常に無視し、0に設定する。
- paymasterのロジックが手数料の値に対して条件付きである場合（ERC-20転送のように）、Rundlerの`verificationGasLimit`は常に過小見積もりとなる
- これらのpaymasterのユーザーは、非ゼロの手数料によって発生する追加のガスをクライアント側で考慮する必要がある。

例えば、検証フェーズ中に転送を行うERC-20 paymasterを使用している場合、`eth\_estimateUserOperationGas`からの`verificationGasLimit`のreturn値に常に75Kガスを静的に加算する。これには、クライアントが呼び出し先のpaymasterコントラクトを認識しており、転送によるガスコストの過小見積もりについて事前知識を持っていることが必要となる。

<CalloutBlock>

💡 Alchemyの[aa-sdk](https://github.com/alchemyplatform/aa-sdk)では、paymasterのミドルウェアがこのガス上限を[それに応じて修正](https://github.com/alchemyplatform/aa-sdk/blob/56bc34be3a50a2709ca546ed90a980f3c489cbbe/packages/core/src/provider/types.ts#L43)できる。

</CalloutBlock>

## これは開発者にとって何を意味するか

ダミー値とトークン転送の問題は、スマートコントラクトアカウント、paymaster、アカウントクライアントを構築する開発者に影響を与える。

### スマートコントラクトアカウント開発者

スマートコントラクトアカウント開発者は、アカウントのvalidation関数がどのように動作するかに基づいて、ダミー署名値が常にクライアント側で決定可能であることを確保する必要がある。この署名はrevertを引き起こしてはならず、最大のガス見積もりをもたらさなければならない。

### Paymaster開発者

Paymaster開発者は、paymasterのvalidation関数がどのように動作するかに基づいて、ダミー`paymasterAndData`値が常に決定可能であることを確保しなければならない。この値はrevertを引き起こしてはならず、最大のガス見積もりをもたらさなければならない。

<CalloutBlock>

💡 Alchemyは、[alchemy_requestGasAndPaymasterAndData](https://www.alchemy.com/docs/wallets/api-reference/gas-manager-admin-api/gas-abstraction-api-endpoints/alchemy-request-gas-and-paymaster-and-data)を通じてガス見積もりプロセスとシミュレーションプロセスを組み合わせることで、sponsoring paymasterにおいてユーザー向けにこれを簡略化している

</CalloutBlock>

### アカウントクライアント開発者

検証フェーズ中に転送を行う（あるいは手数料の値に基づく他のロジックを持つ）paymasterと統合しており、見積もりにAlchemyのエンドポイントを使用しているアカウントクライアント開発者は、見積もりによって返される`verificationGasLimit`に、その転送に伴う潜在的なガスを加算する必要がある。

ERC-4337ガス見積もりの他の複雑な問題について解説する後続の記事にご期待いただきたい！

🦀

## 続きを読む

この4部構成シリーズの次の記事では、OptimismやArbitrumのようなlayer 2ブロックチェーン上でのガス見積もりの課題と、signature aggregatorについて解説する。

シリーズの締めくくりとして、user operationの手数料見積もりプロセスの解説を行う。part oneを見逃した方は、ERC-4337ガス見積もりの仕組みについて学んでほしい！

- [How ERC-4337 Gas Estimation Works](https://www.alchemy.com/blog/erc-4337-gas-estimation)
- [L2 Gas and Signature Aggregators](https://www.alchemy.com/blog/l2-gas-and-signature-aggregators)
- [User Operation Fee Estimation](https://www.alchemy.com/blog/user-operation-fee-estimation)
