EIP-7702で実現するトランザクション手数料のスポンサーシップ:Web3ウォレットのUX向上に向けた新たな可能性

 こんにちは。大和総研デジタルソリューション研究開発部の桑木です。
 大和総研ではデジタル証券であるセキュリティ・トークン(ST:Security Token)を取り扱うためのウォレット(注1)と呼ばれるシステムの開発、NFTに関する書籍の執筆(注2)等、ブロックチェーン分野の取り組みを長年進めています。また、Ethereum等のパブリックブロックチェーンを活用したWeb3の広がりを見据え、部署横断でWeb3分野の研究開発を行う専門のプロジェクトを発足させ、ブロックチェーン・Web3に関する取り組みを強化しています。
 今回はパブリックブロックチェーンのEthereumの改善提案であるEIP(Ethereum Improvement Proposals)の1つの「EIP-7702」で提案された仕組みを使ってトランザクション手数料のスポンサーシップ(手数料の支払いを他者に支払ってもらうこと)を試してみましたので、その方法について解説します。EIP-7702はトランザクション手数料を柔軟に扱えるようにし、Web3ウォレットのUX(ユーザ体験:User Experience)を向上させる仕組みとして注目を集めています。

1. EIP-7702とは

 EIP-7702はEthereumの機能やプロセスの改善に関する提案が書かれたドキュメントであるEIP(Ethereum Improvement Proposal)の1つで、2024年5月にEthereumの考案者であるVitalik Buterin氏らによって提案されました(注3)。EIP-7702はコミュニティ内での議論を経て2025年5月7日にEthereumで行われたアップグレード(Pectraアップグレードと呼ばれる)で正式に実装されました(注4)。
 EIP-7702は主にUXの向上を念頭に置いています。Ethereumに新しいトランザクションタイプを導入することで、EOA(Externally Owned Account:ブロックチェーンで「アカウント」や「ウォレット」と一般に呼ばれるもの)がスマートコントラクトのコードをロードできるようになり、一時的にスマートコントラクトのように振る舞うことが可能になります。これにより、以下の3つが実現可能になります(表1)。

表1. EIP-7702で実現可能なこと
実現できること
概要
トランザクション手数料のスポンサーシップ 例えば、Aさんが保有するNFTをBさんに移転したい時はAさんがトランザクションを送信する必要があります。その際、Aさんは暗号資産でトランザクション手数料を支払う必要があり、NFTのみを取引したい場合でもトランザクション手数料の支払いのために暗号資産を保有しておく必要があります。
EIP-7702の仕組みを活用することで、Cさんの承認があれば、AさんはCさんにトランザクション手数料を代わりに支払ってもらうことが可能になります。これにより、Aさん自身は暗号資産を保有していなくてもNFTの移転ができるようになります。また、Cさんはトランザクション手数料相当額に支払代行手数料を上乗せしてAさんに法定通貨建てで請求するなどして収益を得ることが可能になります。
バッチ処理 同じユーザからの複数の操作を1つにまとめて実行できるようになります。例えば従来は別々のトランザクションで実行していたERC-20トークンのapproveとtransferFromを1つにまとめて実行することで「すべて成功」か「すべて失敗」というシンプルな状態を実現でき、状態管理が容易になります。
権限の段階的縮小 例えば、
・特定の暗号資産は扱えるが別の暗号資産は扱えない
・1日あたり合計残高の最大10%まで暗号資産を使用できる
・特定のアカウントとは暗号資産をやり取りできない
など、アカウントが持つ機能を細かく制御できるようになります。

出所:大和総研作成

 EthereumのコミュニティではAccount Abstraction(アカウント抽象化)と呼ばれる、アカウントの機能を柔軟にしてUXを改善するための仕組みの実現方法に関する議論が続けられています。EIP-7702以外にも同様のUX改善のためのEIPはありましたが、今後本格的にAccount Abstractionを実現していくための重要なステップとしてEIP-7702が採用されました。

2. EIP-7702を使ったトランザクション手数料のスポンサーシップ

 ここからはEIP-7702を使ったトランザクション手数料(ガス代とも呼ばれる)のスポンサーシップ(肩代わり)を試してみます。今回は以下のような構成で、Ethereumのテストネット(テスト用のネットワーク)であるSepoliaを使って、SenderのEOAからReceiverのEOAにERC-20トークンを移転するためのトランザクションを送信します(図1)。
 Ethereumではトランザクションを実行するにはトランザクション手数料をEther(略称:ETH。以降、ETHと表記します。)で支払う必要があります。テストネットでも同様であり、テストネットで発行されているETHで支払う必要がありますが、今回はEIP-7702の仕組みを使い本来Senderが支払うべきトランザクション手数料をSponsorに代わりに支払ってもらいます。

図1. EIP-7702を使ったデモの流れ
出所:大和総研作成

 ERC-20トークンは、テスト用にSepoliaで発行されているステーブルコインのUSDCを使用します。下記のURLから無料で入手可能です。Sponsorには0.1 ETH、Senderには10 USDCを初期の残高として持たせておきます。SenderにはETHを保有させません。

テスト用USDCの配布サイト
https://faucet.circle.com/

 各登場人物の資産(ETH、ERC-20)の初期保有量とトランザクションの実行による残高の増減は以下のようになります(表2)。

表2. 資産の増減
登場人物
資産の種類
初期保有量
残高の増減
残高の増減の理由
Sender ETH 0 ETH 変化なし -
ERC-20 10 USDC 減少(-1) ERC-20の移転のため
Receiver ETH 0 ETH 変化なし -
ERC-20 0 USDC 増加(+1) ERC-20の移転のため
Sponsor ETH 0.1 ETH 減少(減少量は実行時のネットワークの状況に応じて変動) トランザクション手数料の支払いのため

出所:大和総研作成

2.1 トランザクションの概要

 トランザクション手数料のスポンサーシップはdelegation という仕組みを使って実現できます。まず、SponsorはSenderのEOAにトランザクションを送信します。するとSenderのEOAは一時的にスマートコントラクト(ここではDelegate Contractと呼ぶことにします)をロードします。そして、Delegate ContractをロードしたSenderのEOAはERC-20トークンのスマートコントラクトを実行し、SenderからReceiverにトークンを移転します(図2)。

図2. トランザクションの流れ
出所:大和総研作成

 EIP-7702に対応したトランザクションの構成は以下のようになります。EIP-7702では従来のトランザクションに加えてauthorization_listというデータを含める必要があるのがポイントです。authorization_listを使うことで、指定したEOAが指定したDelegate Contractをロードできるようになります。

図3. EIP-7702に対応したトランザクション
出所:大和総研作成

 したがって、Sponsorが送信するトランザクションの構成を図示すると大まかに以下のようになります(図4)。

図4. EIP-7702に対応したトランザクションの構成
出所:大和総研作成

2.2 Delegation Contractの作成

 Delegate Contract用に以下のようなスマートコントラクトをデプロイしました(アドレス:0xebe707c39CFdA896376D618369bd80973318Fe8b)。解説用にロジックをシンプルにしており、toで指定したスマートコントラクトをdataの内容で実行するだけのスマートコントラクトです。処理の内容を確認しやすくするために2種類のeventを用意していますがなくても問題ありません。

※検証用なのでセキュリティ面での検討を行っていません。本番環境ではそのまま使用しないようにしてください。

Delegation Contract(大和総研作成)
pragma solidity ^0.8.0;

contract EIP7702Delegation {
    struct Call {
        address to;
        uint256 value;
        bytes data;
    }
    event CallExecuted(
        address indexed sender,
        address indexed to,
        uint256 value,
        bytes data
    );
    event Executed(address value);

    function execute(Call calldata call) external payable {
        (bool success, ) = call.to.call{value: call.value}(call.data);
        require(success, "reverted");
        emit Executed(address(this));
        emit CallExecuted(msg.sender, call.to, call.value, call.data);
    }
}

2.3 トランザクションの作成のためのソースコード

 ソースコード(Typescript)の全文を以下に掲載します。トランザクションの作成や送信のためにethers.jsというライブラリ(バージョン6.13.7)を使用しています(注5)。次節以降でポイントを解説します。

ソースコード全文(大和総研作成)
import { ethers } from "ethers";

//=======================================================
// パラメータの準備
//=======================================================

// SponserのEOAの秘密鍵とアドレス
const SPONSOR_ADDRESS: string = "SponcerのEOAのアドレス";
const SPONSOR_KEY: string = "Sponcerの秘密鍵";
const sponsorKey = new ethers.SigningKey(SPONSOR_KEY);

// SenderのEOAの秘密鍵とアドレス
const SENDER_ADDRESS: string = "SenderのEOAのアドレス";
const SENDER_KEY: string = "Senderの秘密鍵";
const senderKey = new ethers.SigningKey(SENDER_KEY);

// ReceiverのEOAのアドレス
const RECEIVER_ADDRESS: string = "ReceiverのEOAのアドレス";

// SepoliaのChain ID
const chainId = 11155111;

// Delegate Contractのアドレス
const DELEGATE_CONTRACT_ADDRESS = "0xebe707c39CFdA896376D618369bd80973318Fe8b";
// ERC-20トークンのスマートコントラクトのアドレス(SepoliaのUSDCを使用)
const ERC20_CONTRACT_ADDRESS = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238";

// ノードへの接続情報
const provider = new ethers.JsonRpcProvider("Ethereum SepoliaノードのURL", {
  name: "sepolia",
  chainId: chainId,
});

const main = async () => {
  //=======================================================
  // Authorization Listの作成
  //=======================================================

  const senderNonce = await provider.getTransactionCount(SENDER_ADDRESS);

  // MAGIC(固定値)とethers.encodeRlp([chainId, Delegate Contractのアドレス, Sender
のNonce])を連結
  const MAGIC = "0x05";
  const authContent = ethers.encodeRlp([
    ethers.stripZerosLeft(ethers.toBeHex(chainId)),
    DELEGATE_CONTRACT_ADDRESS,
    ethers.stripZerosLeft(ethers.toBeHex(senderNonce)),
  ]);

  // Hashを計算しSenderの秘密鍵で署名
  const authHash = ethers.keccak256(ethers.concat([MAGIC, authContent]));
  const senderSignature = senderKey.sign(authHash);

  // [chain_id, address, nonce, y_parity, r, s]の順に整列
  const senderAuthorizationList = [
    ethers.stripZerosLeft(ethers.toBeHex(chainId)),
    DELEGATE_CONTRACT_ADDRESS,
    ethers.stripZerosLeft(ethers.toBeHex(senderNonce)),
    ethers.stripZerosLeft(ethers.toBeHex(senderSignature.yParity)),
    senderSignature.r,
    senderSignature.s,
  ];

  //=======================================================
  // ERC-20トークンのtransfer用のデータの作成
  //=======================================================

  // ERC-20トークンのtransferを呼び出すためのインターフェース
  const erc20Interface = new ethers.Interface([
    "function transfer(address to, uint256 amount) external returns (bool)",
  ]);

  // ERC-20トークンのtransfer用のデータの作成
  const transferData = erc20Interface.encodeFunctionData("transfer", [
    RECEIVER_ADDRESS, // ERC20トークンの送信先EOAのアドレス
    ethers.parseUnits("1", 6), // ERC20トークンの送信量
  ]);

  //=======================================================
  // Delegate Contractのexecuteを呼び出すためのデータの作成
  //=======================================================

  // Delegate Contractのexecuteを呼び出すためのインターフェース
  const delegationInterface = new ethers.Interface([
    "function execute((address to, uint256 value, bytes data) calldata calls) external payable",
  ]);

  const internalTransferCall = {
    to: ERC20_CONTRACT_ADDRESS, // ERC20トークンのスマートコントラクトのアドレス
    value: ethers.parseEther("0"), // ETHは送らないので0を指定
    data: transferData, // ERC-20トークンのtransferを呼び出すためのデータ
  };

  // Delegate Contractのexecuteを呼び出す際に渡すデータ
  const executeCallData = delegationInterface.encodeFunctionData("execute", [
    internalTransferCall,
  ]);

  //=======================================================
  // EIP-7702のトランザクションを作成
  //=======================================================

  const sponsorNonce = await provider.getTransactionCount(SPONSOR_ADDRESS);
  const feeData = await provider.getFeeData();

  const unsignedTx: ethers.RlpStructuredDataish = [
    ethers.toBeHex(chainId),
    ethers.stripZerosLeft(ethers.toBeHex(sponsorNonce)), // SponsorのEOAのnonce
    ethers.stripZerosLeft(ethers.toBeHex(feeData.maxPriorityFeePerGas!)), // maxPriorityFeePerGas
    ethers.stripZerosLeft(ethers.toBeHex(feeData.maxFeePerGas!)), // maxFeePerGas
    ethers.stripZerosLeft(ethers.toBeHex(1000000)), // gasLimit
    SENDER_ADDRESS, // SenderのEOAのアドレス
    ethers.stripZerosLeft(ethers.toBeHex(0)), // value: ETHは送らないので0を指定
    executeCallData, // Delegate Contractのexecuteに渡すcalldata
    [], // Access List
    [senderAuthorizationList], // Authorization List
  ];

  // トランザクションタイプ(EIP-7702は4)
  const txType = "0x04";

  // トランザクションタイプとRLPエンコードした未署名トランザクションを連結
  const unsignedRLP = ethers.encodeRlp(unsignedTx);
  const unsignedSerializedTx = ethers.concat([txType, unsignedRLP]);

  // Hashを計算しSponsorの秘密鍵で署名
  const txHash = ethers.keccak256(unsignedSerializedTx);
  const sponsorSignature = sponsorKey.sign(txHash);

  // Sponsorの署名を未署名トランザクションの末尾に追加
  const signedTx = unsignedTx.concat([
    ethers.stripZerosLeft(ethers.toBeHex(sponsorSignature.yParity)),
    sponsorSignature.r,
    sponsorSignature.s,
  ]);

  // RLPエンコードしてトランザクションタイプを付与したトランザクションを生成
  const signedRLP = ethers.encodeRlp(signedTx);
  const rawTx = ethers.concat([txType, signedRLP]);
  console.log("Raw EIP 7702 Transaction:", rawTx);

  // ethersの6.13.7はまだEIP-7702に対応していないので
  // ethersのsendメソッドを使用してEIP-7702のトランザクションを送信
  const tx = await provider.send("eth_sendRawTransaction", [rawTx]);
  console.log("Transaction Hash:", tx);
};

main();

2.4 authorization_listの作成

 まず、authorization_listを作成します。下図の赤枠の部分に該当し、authorization_listで指定したEOAが、指定したスマートコントラクトをロードできるようになります(図5)。ここでは、SenderのEOAがDelegate Contractをロードできるようにしており、MAGIC という固定値を連結したうえでSenderの秘密鍵で署名する必要があります。MAGICの値については、下記サイトの「Parameters」の場所に記載があります。
https://eips.ethereum.org/EIPS/eip-7702#parameters

図5. authorization_listの作成
出所:大和総研作成


Authorization Listの作成(大和総研作成)
  //=======================================================
  // Authorization Listの作成
  //=======================================================

  const senderNonce = await provider.getTransactionCount(SENDER_ADDRESS);

  // MAGIC(固定値)とethers.encodeRlp([chainId, Delegate Contractのアドレス, SenderのNonce])を連結
  const MAGIC = "0x05";
  const authContent = ethers.encodeRlp([
    ethers.stripZerosLeft(ethers.toBeHex(chainId)),
    DELEGATE_CONTRACT_ADDRESS,
    ethers.stripZerosLeft(ethers.toBeHex(senderNonce)),
  ]);

  // Hashを計算しSenderの秘密鍵で署名
  const authHash = ethers.keccak256(ethers.concat([MAGIC, authContent]));
  const senderSignature = senderKey.sign(authHash);

  // [chain_id, address, nonce, y_parity, r, s]の順に整列
  const senderAuthorizationList = [
    ethers.stripZerosLeft(ethers.toBeHex(chainId)),
    DELEGATE_CONTRACT_ADDRESS,
    ethers.stripZerosLeft(ethers.toBeHex(senderNonce)),
    ethers.stripZerosLeft(ethers.toBeHex(senderSignature.yParity)),
    senderSignature.r,
    senderSignature.s,
  ];

2.5 ERC-20のtransfer用のデータの作成

 次にDelegate Contractに実行させるERC-20トークンのtransferのためのデータを作成します。下図の赤枠の部分に該当します(図6)。

図6. ERC-20のtransfer用のデータの作成
出所:大和総研作成


ERC-20トークンのtransfer用のデータの作成(大和総研作成)
  //=======================================================
  // ERC-20トークンのtransfer用のデータの作成
  //=======================================================

  // ERC-20トークンのtransferを呼び出すためのインターフェース
  const erc20Interface = new ethers.Interface([
    "function transfer(address to, uint256 amount) external returns (bool)",
  ]);

  // ERC-20トークンのtransfer用のデータの作成
  const transferData = erc20Interface.encodeFunctionData("transfer", [
    RECEIVER_ADDRESS, // ERC20トークンの送信先EOAのアドレス
    ethers.parseUnits("1", 6), // ERC20トークンの送信量
  ]);

2.6 Delegate Contractのexecuteを呼び出すためのデータの作成

 次に、Delegate Contractのexecuteを呼び出すためのデータを作成します。先ほど作成したERC-20トークンのtransferを呼び出すためのデータを内包させます。下図の赤枠の部分に該当します(図7)。

図7. Delegate Contractのexecuteを呼び出すためのデータの作成
出所:大和総研作成


Delegate Contractのexecuteを呼び出すためのデータの作成(大和総研作成)
  //=======================================================
  // Delegate Contractのexecuteを呼び出すためのデータの作成
  //=======================================================

  // Delegate Contractのexecuteを呼び出すためのインターフェース
  const delegationInterface = new ethers.Interface([
    "function execute((address to, uint256 value, bytes data) calldata calls) external payable",
  ]);

  const internalTransferCall = {
    to: ERC20_CONTRACT_ADDRESS, // ERC20トークンのスマートコントラクトのアドレス
    value: ethers.parseEther("0"), // ETHは送らないので0を指定
    data: transferData, // ERC-20トークンのtransferを呼び出すためのデータ
  };

  // Delegate Contractのexecuteを呼び出す際に渡すデータ
  const executeCallData = delegationInterface.encodeFunctionData("execute", [
    internalTransferCall,
  ]);

2.7 EIP-7702のトランザクションの作成

 最後に、これまで作成したデータを使ってEIP-7702のトランザクションを組み立てます(図8)。トランザクションにはSponsorの署名が必要です。本記事の執筆時点でethersがEIP-7702の署名に対応していないため、トランザクションタイプ(EIP-7702は4)を付与したうえで署名し、手動でEIP-7702に対応したトランザクションを組み立てています。

図8. EIP-7702のトランザクションの作成
出所:大和総研作成


EIP-7702のトランザクションの作成(大和総研作成)
  //=======================================================
  // EIP-7702のトランザクションを作成
  //=======================================================

  const sponsorNonce = await provider.getTransactionCount(SPONSOR_ADDRESS);
  const feeData = await provider.getFeeData();

  const unsignedTx: ethers.RlpStructuredDataish = [
    ethers.toBeHex(chainId),
    ethers.stripZerosLeft(ethers.toBeHex(sponsorNonce)), // SponsorのEOAのnonce
    ethers.stripZerosLeft(ethers.toBeHex(feeData.maxPriorityFeePerGas!)), // maxPriorityFeePerGas
    ethers.stripZerosLeft(ethers.toBeHex(feeData.maxFeePerGas!)), // maxFeePerGas
    ethers.stripZerosLeft(ethers.toBeHex(1000000)), // gasLimit
    SENDER_ADDRESS, // SenderのEOAのアドレス
    ethers.stripZerosLeft(ethers.toBeHex(0)), // value: ETHは送らないので0を指定
    executeCallData, // Delegate Contractのexecuteに渡すcalldata
    [], // Access List
    [senderAuthorizationList], // Authorization List
  ];

  // トランザクションタイプ(EIP-7702は4)
  const txType = "0x04";

  // トランザクションタイプとRLPエンコードした未署名トランザクションを連結
  const unsignedRLP = ethers.encodeRlp(unsignedTx);
  const unsignedSerializedTx = ethers.concat([txType, unsignedRLP]);

  // Hashを計算しSponsorの秘密鍵で署名
  const txHash = ethers.keccak256(unsignedSerializedTx);
  const sponsorSignature = sponsorKey.sign(txHash);

  // Sponsorの署名を未署名トランザクションの末尾に追加
  const signedTx = unsignedTx.concat([
    ethers.stripZerosLeft(ethers.toBeHex(sponsorSignature.yParity)),
    sponsorSignature.r,
    sponsorSignature.s,
  ]);

  // RLPエンコードしてトランザクションタイプを付与したトランザクションを生成
  const signedRLP = ethers.encodeRlp(signedTx);
  const rawTx = ethers.concat([txType, signedRLP]);
  console.log("Raw EIP 7702 Transaction:", rawTx);

  // ethersの6.13.7はまだEIP-7702に対応していないので
  // ethersのsendメソッドを使用してEIP-7702のトランザクションを送信
  const tx = await provider.send("eth_sendRawTransaction", [rawTx]);
  console.log("Transaction Hash:", tx);

2.8 トランザクションの確認

 今回送信したトランザクションのハッシュは、0x6f8a54706c8d7b073e05bca95b77614aef620595f72b732d0669feab9f4b9181となりました。
 Ethereum(Sepoliaを含む)のトランザクションや暗号資産、NFTなどの残高を確認することができるEtherscanというサイトを使って、実際に送信したEIP-7702のトランザクションの内容やトランザクション送信前後でのERC-20トークンの残高の変動を確認してみます。

Sepolia向けEtherscan
https://sepolia.etherscan.io/

関連するURLは下記の通りです。

2.8.1 トランザクション送信前の残高の確認

 まず、SenderのEOAの残高を確認します。左上のOverviewからETHを0、USDCを10保有していることが分かります(図9)。

図9. Etherscanで確認したSenderのEOAの詳細情報
出所:Etherscanより引用(2025年05月07日閲覧)

 次にSponsorのEOAの残高を確認します。左上のOverviewからETHを0.1保有していることが分かります。Transactionsには他のEOAから0.1 ETHを受け取ったトランザクションが表示されています(図10)。

図10. Etherscanで確認したSponsorのEOAの詳細情報
出所:Etherscanより引用(2025年05月07日閲覧)

2.8.2 トランザクション送信後の残高の確認

 Senderのトランザクション送信後の残高です。左上のOverviewからUSDCが9になっていることが分かります。また、TransactionsからERC-20トークンのTransferが実行されたことが分かります(図11)。

図11. Etherscanで確認したSenderのEOAの詳細情報
出所:Etherscanより引用(2025年05月07日閲覧)

 Sponsorのトランザクション送信後の残高です。左上のOverviewからETHが減少していることが分かります。また、TransactionsからTransferが実行され手数料が支払われたことが分かります(図12)。

図12. Etherscanで確認したSponsorのEOAの詳細情報
出所:Etherscanより引用(2025年05月07日閲覧)

 EIP-7702のトランザクションの詳細です。「Txn Type: 4 (EIP-7702)」となっており、EIP-7702のトランザクションとして処理されていることが分かります。トランザクションそのものはSponsorからSenderへのトランザクションとして表示されています(図13)。

図13. Etherscanで確認したEIP-7702のトランザクションの詳細情報(Overview)
出所:Etherscanより引用(2025年05月07日閲覧)

 EIP-7702のトランザクション特有の項目として「Authorization List」が表示されています。SenderがDelegate Contractをロードしたということが表示されています(図14)。

図14. Etherscanで確認したEIP-7702のトランザクションの詳細情報(Authorization List)
出所:Etherscanより引用(2025年05月07日閲覧)

最後に「Logs」を確認します。トランザクション実行時に発生したeventが確認できます。Eventは3つあり、下記のようなeventとなっています(表3、図15)。


表3. eventの概要
event名
内容
Transfer ERC-20トークンのスマートコントラクトのeventが表示されており、SenderのEOAからReceiverのEOAに1000000(=1 USDC)移転されたことが分かります。
Executed Delegate Contractのeventが表示されています。スマートコントラクト内ではaddress(this)としていました。Delegate Contract そのもののアドレスではなくSenderのEOAのアドレスが表示されているため、SenderのEOAがDelegate Contractをロードして実行していることが分かります。
CallExecuted Delegate Contractのeventが表示されています。スマートコントラクト内ではCallExecuted(msg.sender, call.to, call.value, call.data) としていました。msg.senderがSponsorのEOAのアドレス、call.toがERC-20トークンのスマートコントラクトのアドレスとなっていることが分かります。

出所:大和総研作成

図15. Etherscanで確認したEIP-7702のトランザクションの詳細情報(Logs)
出所:Etherscanより引用(2025年05月07日閲覧)

3. まとめ

 本記事では、EIP-7702の仕組みを解説し、実際にトランザクションを送信しました。従来は、例えばパブリックブロックチェーン上でステーブルコインやセキュリティ・トークン、NFTなどの暗号資産以外の資産のみを扱いたい場合でも、それを他の人に移転する際などはトランザクション手数料を支払うために暗号資産(Ethereumの場合はETH)が必要でした。EIP-7702の仕組みによりSenderはトランザクション手数料を支払う必要がなくなるため暗号資産を保有する必要がなくなります。これにより、以下のようなことが可能になります。

  • トランザクション手数料の支払いを代行するサービスが登場し、それを利用することで暗号資産を保有することなくさまざまな資産を扱うことができるようになる。

  • トランザクション手数料をステーブルコインで支払うことができるようになる。

  • トランザクション手数料支払い用のアカウントを別に設けて暗号資産を他のアカウントと分けて保有することで暗号資産が複数のアカウントに分散することを防ぎ、残高管理や財務処理がしやすくなる。

  • トランザクション手数料というブロックチェーン特有の要素が抽象化されることでウォレットの操作性やUXが向上する。

 このように、暗号資産やトランザクション手数料を柔軟に扱うことができるようになり、ブロックチェーン・Web3全般に対する参入障壁が下がることで新たなビジネスモデルやサービスの登場が期待されます。一方で、EOAが従来とは異なりプログラムを実行することができるようになるため、本来意図しないプログラムを実行させられたり、トランザクションを再利用され資産の移転を複数回実行させられたりしてしまう(リプレイ攻撃)などのリスクがあり、セキュリティ面には十分注意する必要があります。

(本ブログの内容は2025年5月時点のものです)

お問い合わせ先

 大和総研では、ブロックチェーン・Web3分野の研究開発を行う専門のプロジェクトを発足し、ウォレットに関する特許を取得するなど、ブロックチェーン・Web3に関する取り組みを行っています。長年にわたるブロックチェーン・Web3関連の取り組みの実績を活かし、お客様のブロックチェーン・Web3ビジネスの検討やシステムの構築をサポートします。ご要望・ご不明点などがありましたら、ITソリューションサービスサイトよりお問い合わせください。

参考文献

(注1)本邦初の PTS(私設取引システム)取扱セキュリティ・トークンの引受及び、 セキュリティ・トークンウォレット「Crossllet」開発のお知らせ
https://ssl4.eir-parts.net/doc/8601/ir_material3/218042/00.pdf
(注2)大和総研出版書籍「図解まるわかり NFTのしくみ」
https://www.dir.co.jp/publicity/book/20221201.html
(注3)ethereum.org 「EIP-7702: Set Code for EOAs」
https://eips.ethereum.org/EIPS/eip-7702
(注4)ethereum.org 「Pectra Mainnet Announcement」
https://blog.ethereum.org/2025/04/23/pectra-mainnet
(注5)ethers.js
https://docs.ethers.org/v6/