コンテンツへスキップ
0%

user operationsとは?

2023年6月26日 公開読了時間 1 分

ユーザーオペレーションは、送信者のスマートコントラクトアカウントに代わって実行されるトランザクションの詳細を含むオブジェクトです。ユーザーオペレーションは疑似トランザクションオブジェクトであり、ERC-4337をサポートするEthereumおよびレイヤー2ブロックチェーンにおいて、コンセンサスレイヤーの変更を必要とせずにAccount Abstractionを機能させます。

スマートコントラクトウォレット(SCW)を開発する、あるいは分散型アプリケーションをSCWと互換性を持たせるためには、ユーザーオペレーションを定義するパラメータ、ユーザーオペレーション構築プロセス中にユーザーオペレーションの各フィールドがどのように設定されるか、ユーザーオペレーションがBundlerによってどのようにバンドルされるか、そしてペイマスターによってどのように検証・実行されるかを理解しておくことが有益です。

Embedded AccountsとAccount Abstractionインフラストラクチャを使用して、新規ユーザー向けに埋め込み型のメールおよびパスキーウォレットを作成できるようにしましょう!

動画で見る: Solidityでユーザーオペレーションを構築・実行する

ユーザーオペレーションに含まれるフィールドとは?

ユーザーオペレーション(UO)には、通常のトランザクションと似たフィールド(sender、to、calldata、maxFeePerGas、maxPriorityFee、signature、nonceなど)が含まれますが、それに加えてcallGasLimit、verificationGasLimit、preVerificationGas、paymasterAndDataといった、ユーザーオペレーション構造体特有の新しいフィールドも持ちます。

UOフィールドの定義はERC-4337の公式仕様書に記載されています。以下に要約します。

  • callGasLimit - メインの実行呼び出しに使用されるガス
  • verificationGasLimit - 検証ステップを完了するために使用されるガス
  • preVerificationGas - 事前検証の実行およびcalldataコストをカバーするためにBundlerへ支払うガス
  • paymasterAndData - スポンサーとなるペイマスターのアドレスと、そのペイマスターに送信するデータ

ユーザーオペレーションの設計とアーキテクチャについての説明は、AlchemyのAAインフラチームのエンジニアであるDavid Philipsonが執筆した「You Could Invented Account Abstraction」シリーズのパート1で読むことができます。

次に、ユーザーオペレーションのフィールドを正しく設定するための標準的なワークフローを見ていきましょう。

ユーザーオペレーションを送信する流れとは?

Bundlerへユーザーオペレーション(ユーザーオペ)を送信する典型的な流れは、複数のステップから構成されます。

  1. sender、nonce、initCode、callDataを入力した部分的なユーザーオペを構築する
  2. eth_estimateUserOperationGasを通じて、部分的なユーザーオペのガスをBundler RPCへ見積もる
  3. preVerificationGas、verificationGasLimit、callGasLimitを設定する
  4. ユーザーオペの内容に依存しないペイマスター(例えばERC20ペイマスターなど)を使用する場合、この段階でpaymasterAndDataを設定できる
  5. オペレーションに必要なガス手数料を見積もり、maxFeePerGasとmaxPriorityFeePerGasを設定する
  6. (任意)署名のためにユーザーオペをスポンサーとなるペイマスターへ送信し、paymasterAndDataを設定する
  7. ペイマスターの署名には上記のすべてのフィールドが設定されている必要があるため、このステップで行う必要がある
  8. ユーザーオペに署名し、signatureを設定してから、eth_sendUserOperationを通じてBundlerへユーザーオペを送信する

開発者はネイティブのethers.jsを使って各ユーザーオペレーションフィールドの値を取得することもできますが、UO構築をより簡単にするweb3開発者向けツールがいくつか存在します。

開発者はユーザーオペレーションの構築にどんなツールを使えるか?

AlchemyのオープンソースAA SDKのようなユーザーオペレーション構築ツールを使うと、ネイティブのethers.jsでユーザーオペを作成するよりも簡単にユーザーオペレーションを構築できます。

AlchemyのAA SDK

AlchemyのAA SDKはviemをベースに構築されており、開発者に軽量なバンドルを提供します。GitHub上のaa-sdkは、aa-ethersライブラリを通じてethers.jsのSignerおよびProviderもサポートしています。

aa-sdkを使ってユーザーオペレーションを構築する主な利点の1つは、次の2つのユーティリティメソッドです。

  1. sendUserOperation - ガス見積もり、paymasterAndDataのリクエスト、署名などを処理する
  2. sendTransaction - トランザクションオブジェクトのデータ(from、to、data、value)をユーザーオペレーションに変換する

ユーザーオペレーション構築の処理順序は複雑ですが、AlchemyのAA-SDKはgetDummyPaymasterDataestimateGasによるガス見積もり、続いてgetFeeData、そして最後にgetPaymasterAndDataという一連の処理を実行することでUO構築を簡略化します。

ユーザーオペのフィールドの値を取得した後、target、callData、そして任意のvalueを使ってユーザーオペレーションを構築し、署名します。その後、Bundlerへユーザーオペを送信し、ユーザーオペのハッシュを受け取ります。

Alchemyのペイマスター、別のペイマスターを使用したい場合、あるいは独自のSmartAccountsのサポートを追加する予定がある場合は、UOを簡単に作成する方法の完全な説明についてAlchemy AA SDKのドキュメントをお読みください。

ユーザーオペレーションはどのようにユーザーオペmempoolへ追加されるか?

ユーザーオペがmempoolへ追加される前に、ERC-4337仕様書に示された期待される動作に従っていることを確認するための一連のチェックに合格する必要があります。ユーザーオペはまた、有効であり、そのガス代を(送信者のウォレットまたはペイマスターのスポンサーシップポリシーを通じて)支払えることを確認するための検証シミュレーションチェックにも合格する必要があります。

1. ユーザーオペの有効性がチェックされる

最初の一連のチェックは、ERC-4337仕様書の「Client behavior upon receiving a UserOperation」セクションで説明されており、以下に要約します。

  • 送信者が既存のコントラクトであるか、(コントラクトを作成するために使用される)initCodeが空でないか(ただし両方が同時に成り立つことはない)
  • initCodeが空でない場合(ユーザーオペがアカウントを作成するため)、factoryがステークされているかどうかを判定する
  • verificationGasLimitが十分に低い(MAX_VERIFICATION_GAS以下である)
  • preVerificationGasがcalldataガスおよびオーバーヘッドガス手数料を支払うのに十分な高さである
  • paymasterAndDataが空であるか、ペイマスターのアドレスで始まっている
  • ペイマスターが存在する場合、それはオンチェーン上に空でないコードを持ち、ユーザーオペの支払いに必要な資金を持ち、かつ禁止されていない
  • callgasが、非ゼロ値を持つCALLのコスト以上である
  • maxFeePerGasmaxPriorityFeePerGasが、クライアントが受け入れる最小値を上回っている
  • 送信者がプール内に別のユーザーオペを持っていない(または、そのユーザーオペが既存のエントリを置き換えるために構築されている)

これらのチェックに影響を与えうるルールは数多くあり、仕様書で詳しく説明されています。

このユーザーオペレーションの入門記事では、ユーザーオペの有効性を判定するために行われる高レベルのチェックについて説明するにとどめます。

2. ユーザーオペレーションがシミュレートされる

ユーザーオペがこれらの基本的なチェックに合格すると、クライアントはユーザーオペレーションをシミュレートし、そのユーザーオペが自身の資金またはペイマスターを使って実行費用を支払えることを検証する必要があります。

ユーザーオペをシミュレートするために、BundlerはsimulateValidation()メソッドを呼び出します。このメソッドは、送信者のアカウントのvalidateUserOp関数を呼び出すか、あるいはユーザーオペの実行にかかるガス手数料をスポンサーするためにペイマスターが使用される場合は、ペイマスターのコントラクトアカウントのvalidatePaymasterUserOpを呼び出します。

**simulateValidation()**メソッドが呼び出されると、ValidationResultレスポンスと共にリバートします。この関数がリバートすることは意図された動作であり、これは成功した結果とみなされます。

ValidationResultが別のエラーでリバートした場合、そのユーザーオペは検証シミュレーションに合格しなかったことになり、mempoolには追加されません。sigFailを返すユーザーオペはmempoolから除外され、またvalidUntilレスポンスが期限切れになった場合もUOはmempoolから除外されることがあります。

注: ユーザーオペにinitCodeが存在する場合、アカウントファクトリによってアカウントが作成され、その後、新しく作成されたアカウントを使ってシミュレーションプロセスが進められます。

ユーザーオペレーションが構築され、チェックされ、シミュレートされ、mempoolへ追加されたので、次はentry pointコントラクトへ送信され、検証と実行が行われます!

ユーザーオペレーションはどのように検証・実行されるか?

ユーザーオペレーション内のトランザクションの詳細がオンチェーンで公開されるためには、entry pointコントラクトがそのユーザーオペレーションを検証する必要があります。UOが検証に合格すると、entry pointコントラクトがトランザクションを実行し、その後Bundlerへガス手数料を払い戻します。

ユーザーオペの検証と実行の基本的なステップは以下の通りです。

  1. BundlerがhandleOps()メソッドを通じて、単一のentry pointコントラクトへユーザーオペを送信する
  2. 各オペについて、entry pointがそのオペの送信者ウォレットに対してvalidateOpを呼び出す*
  3. いずれかのオペが検証ステップに失敗した場合、それらは破棄される
  4. 次に、各オペの送信者ウォレットに対してexecuteOpを呼び出し、使用されたガス量を記録する
  5. 各オペの実行に使用されたガスを支払うため、送信者のウォレットまたはペイマスターからBundlerへETHを送金する

*すべての検証が実行され、それが完了して初めて、検証済みのユーザーオペのすべての実行が行われます。

以下は、送信者のスマートコントラクトウォレットに代わってentry pointコントラクトがユーザーオペレーションをどのように検証・実行するかを示す図です。

ユーザーオペレーションがどのように検証・実行されるか

ユーザーオペレーションは、スマートコントラクトウォレットがEthereumおよび同等のL2上でユーザーのプライマリウォレットとして機能することを可能にする疑似トランザクションオブジェクトです。スマートコントラクトウォレットはweb3のUX上の利点をもたらし、ブロックチェーンをより身近なものにしますが、それを可能にしているのがEthereumおよびL2上のAAインフラストラクチャプロバイダーです。

あなたのweb3プロダクトがスマートコントラクトウォレットをサポートするのであれば、Ethereum、Polygon、Arbitrum、Optimism、そしてSepoliaなどの人気のテストネット向けに、Gas Manager APIやBundler APIを含むAlchemyのAAインフラストラクチャをぜひご覧ください!

Background gradient

ブロックチェーンで魔法を生み出す

Alchemyは、最も強力なweb3開発者向けプロダクトとツールを、豊富なリソース、コミュニティ、そして卓越したサポートと組み合わせて提供します。