> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monad.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Monad 上的 EIP-7702

## 摘要

Monad 支持 [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702),工作流程与以太坊相同:
用户签署一条授权消息以委托给特定账户,然后由用户本人或其他人使用交易类型 `0x04` 提交。
提交完成后,该 EOA 变为"已委托"状态,即可以像具有代码(该代码等于其所委托账户的代码)的智能合约账户
一样被调用。

在大多数情况下,EIP-7702 委托账户在 Monad 上的行为与在以太坊上相同。

两个主要细节是:

1. 如果一个 EOA 被 EIP-7702 委托,任何会将其余额降至 10 MON 以下的交易将
   无条件回滚。
   * 如果余额低于 10 MON 但此交易未改变或增加了余额,则交易成功
   * 如果委托被移除,则在某些条件下允许低于 10 MON
   * [详情](#delegated-eoas-can%E2%80%99t-dip-below-10-mon)
2. 当 EOA 被视为智能合约时,该代码不能调用 `CREATE` 或 `CREATE2`。
   [详情](#delegated-contract-code-cannot-call-create%2Fcreate2)

## EIP-7702 入门

[EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) 允许外部拥有账户(EOA)
向自身添加代码,从而使其能够获得以前专属于智能合约账户的新能力,
例如交易批处理、gas 赞助以及替代身份验证。

为此,EOA 会签署一个授权,指定一个特定地址作为其代码的来源。
EIP-7702 引入了一种新的交易类型(类型 `0x04`)来提交该授权。
该授权可以由 EOA 自己提交,或由其他任何人提交。

EIP-7702 使 EOA 直接实现账户抽象成为可能。它是 EIP-4337 的扩展,
后者引入了具有灵活验证逻辑的智能合约钱包标准,但必须假设有一个独立的
UserOp mempool 和用于提交交易的 bundler 基础设施。

在以太坊基于账户的模型中,存在两个独立的角色 —— "费用支付方"(交易提交方,
即支付 gas 以执行交易的一方)和"资产所有者"(花费授权方,即持有可以从余额中花费的密钥的一方)。
最初,EOA 同时扮演这两个角色。在 EIP-4337 下,这些角色被分开 —— 智能合约钱包持有资产
(并有自己的逻辑来验证花费是否被授权),但费用仍然必须由 EOA 支付,因此这两个角色被明确分开。

而在 EIP-7702 下,EOA 被允许拥有代码,从而使同一个账户能够再次扮演这两个角色。

本质上,EIP-7702 使当今的 EOA 能够获得类似智能钱包的能力,
例如多签、社交恢复、会话密钥和 gas 赞助,**而无需放弃他们当前的账户**,
弥合了旧的 EOA 模型与完全账户抽象未来之间的鸿沟。

## Monad 上的 EIP-7702

在大多数情况下,EIP-7702 委托账户在 Monad 上的行为与在以太坊上相同。

两个主要细节是:

1. 如果一个 EOA 被 EIP-7702 委托,任何会将其余额降至 10 MON 以下的交易将
   无条件回滚。
   * 如果余额低于 10 MON 但此交易未改变或增加了余额,则交易成功
   * 如果委托被移除,则在某些条件下允许低于 10 MON
   * [详情](#delegated-eoas-can%E2%80%99t-dip-below-10-mon)
2. 当 EOA 被视为智能合约时,该代码不能调用 `CREATE` 或 `CREATE2`。
   [详情](#delegated-contract-code-cannot-call-create%2Fcreate2)

### 已委托的 EOA 不能低于 10 MON

在 Monad 中,[储备余额](/zh/developer-essentials/reserve-balance)规则为每个 EOA 划出了
10 MON 的预算,用于在共识时对该 EOA 的在途交易进行余额检查。("在途"是指自延迟状态视图
(3 个区块前)以来共识所看到的交易。)

执行会通过以下方式保护该预算:如果任何 EOA 的余额会\_低于\_ 10 MON,
且超出交易的最大 gas 费用,则回滚该交易。(*"低于"* 意味着\_"减少**且**降到 10 MON 以下"\_;
如果 EOA 的 MON 余额未改变,则不算低于。)

* 对于**未委托的** EOA,如果在过去几个区块内没有该 EOA 的交易,会对此执行时策略作出[例外](/zh/developer-essentials/reserve-balance#addressing-the-drawback)。
  该例外允许未委托的 EOA 提交会使其余额低于 10 MON、且下降的量超过交易最大 gas 费用的交易。

* 但是,此例外不能应用于 EIP-7702 委托账户。委托打破了 EOA 余额只能通过该 EOA
  签名的交易减少的不变量。共识时无法可靠地确认另一笔在途交易没有从 EIP-7702 委托账户中花费资金,
  因此为未委托账户所作的例外不适用于**已委托**账户。

已委托账户可以通过先取消委托来清空。

需要明确的是,EIP-7702 委托账户**不**要求持有 10 MON 余额。例如,余额为 5 MON 的已委托 EOA *A*
仍然可以被 gas 赞助方调用,只要 *A* 最终仍剩 5 MON 或更多,交易就会成功。

这在[此处](/zh/developer-essentials/reserve-balance#eip-7702-delegated-accounts)有进一步讨论。

### 已委托的合约代码不能调用 `CREATE/CREATE2`

还有一个差异:当合约代码在 EIP-7702 委托 EOA 的上下文中执行时
(例如,因为一个合约 `CALL` 了该 EOA 的地址),
`CREATE` 和 `CREATE2` opcode 是不允许的。
任何在此类调用帧中执行 `CREATE` 或 `CREATE2` 的尝试都会导致该调用帧回滚,
调用者(如果有)会观察到该调用失败
(`CALL`/`DELEGATECALL`/`CALLCODE` 返回 0)。

这可以防止已委托的代码以难以静态验证来自该账户的交易的方式更改 EOA 的 nonce。

相比之下,从已委托的 EOA 发送的普通合约创建交易(即没有 `to` 字段、交易 `data` 被视为
初始化代码的交易)是允许的,并且行为与以太坊上相同。

除这些差异外,EIP-7702 委托账户在 EOA 发送的普通交易和将 EOA 视为智能合约的交易方面
均正常行为。

## FAQ

<Accordion title="EIP-7702(设置代码交易)是什么样的?">
  EIP-7702 交易是一种 TransactionType 为 `0x04` 的 [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718)
  交易。

  此交易类型仅用于设置代码;一旦为 EOA 设置了代码,后续交易很可能会使用默认交易类型
  (TransactionType `0x02`;[EIP-1559](https://eips.ethereum.org/EIPS/eip-1559))
  来与该 EOA 交互。

  以下是区块浏览器中的 EIP-7702 交易示例:

  <img src="https://mintcdn.com/monadfoundation-40611fb6/c3ZcPFY7YVeS_v57/static/img/developer-essentials/eip-7702/1.png?fit=max&auto=format&n=c3ZcPFY7YVeS_v57&q=85&s=5c00461aa37ff2ecbc869a4a4c38ed9c" alt="explorer_example" width="2186" height="986" data-path="static/img/developer-essentials/eip-7702/1.png" />
</Accordion>

<Accordion title="EIP-7702 类型交易是否必须由 EOA 本身发起?">
  不是的,EOA 可以签署一个"授权元组",然后由赞助方使用它来发送交易。
  这将使 EOA 能够在没有任何 gas 资金的情况下表现得像智能合约!
</Accordion>

<Accordion title="我如何找出 EOA 当前委托给哪个地址?">
  成功委托给智能合约后,以下代码会部署在 EOA 的地址上。

  `0xef0100`(3 字节)+ `smart_contract_address`(20 字节)

  示例:如果 `0xabc...`(EOA)委托给 `0x493...`(智能合约),
  那么 `0xabc...`(EOA)处的代码为 `0xef0100493...`

  因此,您可以通过检查代码来确定委托的地址。
</Accordion>

<Accordion title="如果 EOA 指向另一个也指向智能合约的 EOA,会怎样?">
  不会跟随委托链;只会使用第一个 EOA 直接指向的代码。
</Accordion>

<Accordion title="如何清除 EOA 上的委托?">
  从 EOA 发起一个 `0x04` 类型的交易,将 `0x000...`(死地址)作为新的委托账户。
</Accordion>

<Accordion title="委托会过期吗?">
  不会,除非发送另一个将委托更改为其他账户(或空账户)的 `0x04` 交易,
  否则委托将永久有效。
</Accordion>

<Accordion title="EIP-7702 是否与 ERC-4337 兼容?">
  是的;使用 EIP-7702 委托后,任何 EOA 都可以像 EIP-4337 智能账户一样运行。
  只需发起一个 `0x04` 类型的交易,指向包含 4337 兼容智能账户代码的地址即可。
</Accordion>

<Accordion title="如果 EOA 指向一个预编译地址作为代码,会发生什么?">
  如果那是以太坊预编译,当有足够 gas 时,`CALL`、`STATICCALL`、`DELEGATECALL` 和 `CALLCODE` opcode
  会像 EOA 没有代码一样继续执行。

  如果那是 Monad 预编译,调用会回滚,就像 EOA 具有以无效指令开头的代码一样。
</Accordion>

<Accordion title="能给我一个使用 viem 提交 EIP-7702 交易的示例吗?">
  ```ts theme={null}
  import { createWalletClient, http, parseEther } from 'viem'
  import { monadTestnet } from 'viem/chains'
  import { privateKeyToAccount } from 'viem/accounts'

  const account = privateKeyToAccount('0x...')

  const walletClient = createWalletClient({
    account,
    chain: monadTestnet,
    transport: http(),
  })

  const authorization = await walletClient.signAuthorization({
    account,
    contractAddress: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2'
  })

  const hash = await walletClient.sendTransaction({
    authorizationList: [authorization],
    data: '0xdeadbeef',
    to: walletClient.account.address,
  })
  ```
</Accordion>
