Pectra 升级的核心:EIP-7702的原理分析和实操

什么是 EIP-7702

EIP-7701 是以太坊 Pectra 升级的内容之一。是一种新的交易类型( 0x4 )。提高了以太坊的账号抽象的能力,支持直接使用 EOA 账号去执行临时智能合约。可以实现批量交易、gas 代付 等能力,这将会在钱包开发中起到很大作用。

EIP-7702 的能力

  • 批量交易:可以在一次 EOA 账号发起交易时,发送多次交易。(非 EIP-7702 类型的 EOA 账号一次只能发送一笔交易)

  • gas 代付:允许第三方(例如接收方或代理机构)为你支付本次交易的 gas 费用。(原始 EOA 交易没有 gas 代付能力)

  • 安全访问:授予临时的对合约的访问,用完后 EOA 账号恢复成为普通账号。调用时无须暴露私钥。

  • 合约共享:逻辑合约可以共享,只需部署一次,便可提供给多个 EOA 账号使用。逻辑合约可永久存在链上(临时合约用完即毁)。

EIP-7702 在钱包场景下的作用

可以用在交易所钱包的 归集 操作上。传统的以太坊 EOA 账号进行归集操作,从用户地址发送到归集地址,只能一笔一笔进行归集,并且需要交易所下发一笔小额资金作为归集 gas 费用。效率十分低下且存在粉尘资金增多、额外消耗 gas 的问题。而采用 EIP-7702 的新交易类型,可以在共用 EOA 账号的同时,平滑升级到支持批量归集gas 代付的能力。

EIP-7702 实现的核心原理

  • 签名授权 EOA 账号在签名时候,签订一个授权信息,内容包括 链 IDnonce委托地址EIP-712 的签名。这个授权信息供验证者节点打包交易时,从委托地址中查出运行代码,然后附加到 EOA 账号中。

    image.png - 临时代码注入 节点收到 EOA 账号发送的交易后,验证 EOA 账号的签名,从链上读取委托合约的 bytecode 然后临时注入到 EOA 账号的地址上。

  • 自动代码卸载 在交易执行完后,该地址又会变回普通 EOA 地址,EXTCODEHASH(address) == 0x0。代码区会变回 0。且状态不会存储到链上,确保不存在污染。

EIP-7702 实操及流程解析

git clone https://github.com/quiknode-labs/qn-guide-examples.git
cd qn-guide-examples/ethereum/eip-7702
  1. 安装依赖 安装 forge 库和 OZ 代码库
forge install foundry-rs/forge-std
forge install OpenZeppelin/openzeppelin-contracts
  1. 启动 anvil 注意,在未完全升级之前,必须携带--hardfork prague 参数,否则无法执行。
anvil --hardfork prague
  1. 使用 script 部署合约
❯ forge script script/BatchCallAndSponsor.s.sol \
  --rpc-url http://127.0.0.1:8545 \
  --broadcast \
  --tc BatchCallAndSponsorScript -vvvv

观察到以下结果,代码部署成功。 image.png 6. 观察日志 - performDirectExecution() 批量转账日志观察

image.png - performSponsoredExecution() gas 代付日志观察

image.png 6. 部署流程解析 - 原始 EOA 转账 首先来分析一下没有 EIP-7702 的原始转账情况,用户 A 通过离线签名,将交易发送到以太坊 RPC 节点,在通过对用户 A 的签名认证之后,可以将交易广播到以太坊网络。此时,交易只能一笔一笔的发送,且无 gas 代付能力。

image.png

  • performDirectExecution() 批量转账 而在使用了 EIP-7702 后,交易流程发生了变化。首先,我们来看一个总的执行图。后面再回去根据代码分析。

image.png 1. 在这个执行图中(A 代指 AliceB 代指 Bob),EOA 账户 Alice 离线发起委托签名,签名时,将委托的逻辑合约包含在其中,发送给以太坊 RPC 节点。

![image.png](https://img.learnblockchain.cn/attachments/2025/04/Nk5ilkKQ68047cd0a9dee.png)
  1. 然后,RPC 节点经过验证签名有效后,读取这个逻辑合约的字节码,注入给 EOA 用户 Alice。此时,用户 Alice 从一个 EOA 账户升级成为一个临时合约账户(合约的地址和用户 Alice 的地址一致),可以执行合约的逻辑(批量转账等)

    image.png

  2. 在此处 Alice 的临时合约中,因为合约的调用者是 Alice,无须对 Alice 进行验签处理,使用 require(msg.sender == address(this)) 即可完成签名的验证。 image.png

  3. 此外,由于发送给 RPC 节点时 from 地址为 Aliceto 地址也为 Alice。在此过程中,Alice 为合约账户,属于合约内部交易,所以这条记录不会被记录在以太坊的交易记录中。

  4. 最后,这个账户就拥有了合约的调用能力,其中的交易给 Bob 的两笔交易(ETHERC20 代币)都通过 B.call()的方式进行发送到以太坊网络中。(from 地址为 Aliceto 地址为 Bobfrom 地址属于合约地址,to 地址属于 EOA 地址,属合约内部交易,故也不存在交易记录中)

image.png - performSponsoredExecution() gas 代付

![image.png](https://img.learnblockchain.cn/attachments/2025/04/jPWUZ6gc6804768f7da6c.png)
`gas` 代付的情况相对于普通批量转账的场景而言,稍微复杂与一点。可以分为以下几步:
1. **Alice 构造委托合约,并签名**:
![image.png](https://img.learnblockchain.cn/attachments/2025/04/O9z63gLv68047ea636c22.png)
2. **Bob 持有 Alice 的数据,并签名**:
![image.png](https://img.learnblockchain.cn/attachments/2025/04/MQ09Dfrq68047f02cc427.png)
3. **Bob 发送交易到 RPC 节点**:

![image.png](https://img.learnblockchain.cn/attachments/2025/04/bLiUK24Q68047f58ec0dd.png)

4. `RPC` 节点对 `Bob` 进行验签,通过后读取 `Alice` 委托的逻辑合约代码,注入到 `Alice` 的地址中。然后广播交易。此时,用户 `Alice` 从一个 `EOA` 账户升级成为一个临时合约账户(合约的地址和用户 `Alice` 的地址一致),可以执行合约的逻辑(批量转账等)

 5. 并且,由于在这种 `gas` 代付的方案中,交易的发起者是 `Bob`,所以 `RPC` 节点在进行验签的时候,只会验证 `Bob` 的签名,`Alice` 的签名并不会去处理。在合约中,没办法像上面批量交易那样使用 `require(msg.sender == address(this))` 故我们临时合约中还需要去验证 `Alice` 的签名,以防止伪造交易的情况出现。

![image.png](https://img.learnblockchain.cn/attachments/2025/04/zFru4hLj68047facb70cb.png)

6.  此外,由于发送给 `RPC` 节点时,发送者 `from` 为 `Bob`,接受者 `to` 地址为 `Alice`,`Bob` 是一个 `EOA` 账户,`Alice` 为一个合约账户,故这笔交易记录会被记录上。  
  ![image.png](https://img.learnblockchain.cn/attachments/2025/04/6Lio6sv068047942d73ca.png)
 7. 但是,由于在 `Alice` 合约内部,发生了从 `Alice` 转账给 `Tom`(也可以是 `Bob`) 的情况,`Alice` 属于合约地址,`Tom`(`Bob`) 属EOA 地址,属合约内部交易,故这笔记录也不会存在以太坊的交易记录中。

image.png

全部评论(0)